1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: d_net.c 1522 2020-05-05 03:30:58Z wesleyjohnson $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Portions Copyright (C) 1998-2016 by DooM Legacy Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 //
20 // $Log: d_net.c,v $
21 // Revision 1.18 2003/05/04 02:29:14 sburke
22 // Fix for big-endian machines.
23 //
24 // Revision 1.17 2001/08/26 15:27:29 bpereira
25 // added fov for glide and fixed newcoronas code
26 //
27 // Revision 1.16 2001/08/20 20:40:39 metzgermeister
28 // Revision 1.15 2001/02/10 12:27:13 bpereira
29 // Revision 1.14 2000/10/21 08:43:28 bpereira
30 // Revision 1.13 2000/10/16 20:02:29 bpereira
31 // Revision 1.12 2000/10/08 13:29:59 bpereira
32 // Revision 1.11 2000/09/28 20:57:14 bpereira
33 // Revision 1.10 2000/09/15 19:49:21 bpereira
34 // Revision 1.9 2000/09/10 10:38:18 metzgermeister
35 // Revision 1.8 2000/09/01 19:34:37 bpereira
36 //
37 // Revision 1.7 2000/09/01 18:23:42 hurdler
38 // fix some issues with latest network code changes
39 //
40 // Revision 1.6 2000/08/31 14:30:55 bpereira
41 // Revision 1.5 2000/04/16 18:38:07 bpereira
42 // Revision 1.4 2000/03/29 19:39:48 bpereira
43 // Revision 1.3 2000/02/27 00:42:10 hurdler
44 // Revision 1.2 2000/02/26 00:28:42 hurdler
45 // Mostly bug fix (see borislog.txt 23-2-2000, 24-2-2000)
46 //
47 //
48 // DESCRIPTION:
49 // DOOM Network game communication and protocol, Low level functions,
50 // all OS independent parts.
51 //
52 // Implements a Sliding window protocol, without receiver window
53 // (out of order reception).
54 // This protocol use mix of "goback n" and "selective repeat" implementation
55 // The NOTHING packet is sent when the connection is idle,
56 // to acknowledge packets
57 //
58 //-----------------------------------------------------------------------------
59
60 #include "doomincl.h"
61 #include "d_net.h"
62 #include "g_game.h"
63 #include "i_net.h"
64 #include "i_system.h"
65 #include "m_argv.h"
66 #include "w_wad.h"
67 #include "d_netfil.h"
68 #include "d_clisrv.h"
69 #include "i_tcp.h"
70 #include "m_swap.h"
71 #include "z_zone.h"
72
73 //
74 // NETWORKING
75 //
76 // gametic is the tic about to (or currently being) run
77 // maketic is the tic that hasn't had control made for it yet
78 // server:
79 // nettics is the tic for each node
80 // next_tic_send is the lowest value of nettics
81 // client:
82 // cl_need_tic is the tic needed by the client for run the game
83 // next_tic_send is used to optimize a condition
84 // normaly maketic>=gametic>0,
85
86 #define CONNECTION_TIMEOUT (15*TICRATE)
87
88 doomcom_t* doomcom = NULL;
89 netbuffer_t* netbuffer = NULL; // points inside doomcom
90
91 #ifdef DEBUGFILE
92 // Debug of some net info into a file, during the game.
93 FILE* debugfile = NULL;
94 #endif
95
96 // Rebound queue, self server to self client network.
97 #define MAXREBOUND 8
98 static netbuffer_t reboundstore[MAXREBOUND];
99 static uint16_t reboundsize[MAXREBOUND];
100 static byte rebound_head, rebound_tail;
101
102 // Network interfaces (i_net.h)
103 uint32_t net_bandwidth;
104 uint16_t hardware_MAXPACKETLENGTH;
105 network_error_e net_error;
106
107 byte (*I_NetGet) (void);
108 byte (*I_NetSend) (void);
109 boolean (*I_NetCanSend) (void);
110 void (*I_NetCloseSocket) (void);
111 void (*I_NetFreeNode) (byte nodenum);
112 byte (*I_NetMakeNode) (char *address);
113 boolean (*I_NetOpenSocket) (void);
114
115 // ---- Internal network, for single player game.
116
Internal_Get(void)117 byte Internal_Get(void)
118 {
119 doomcom->remotenode = -1;
120 // I_Error("Get without netgame\n");
121 net_error = NE_not_netgame;
122 return net_error;
123 }
124
125 // Function for I_NetSend().
Internal_Send(void)126 byte Internal_Send(void)
127 {
128 I_SoftError("Send without netgame\n");
129 net_error = NE_not_netgame;
130 return net_error;
131 }
132
Internal_FreeNode(byte nodenum)133 void Internal_FreeNode( byte nodenum )
134 {
135 }
136
137 // --- Network statistics
138
139 int net_packetheader_length;
140
141 // Network stats.
142 tic_t stat_starttic; // tic of start of stat interval
143 int stat_getbytes = 0; // bytes received this interval
144 uint64_t stat_sendbytes = 0; // bytes sent, total
145 int stat_retransmits = 0; // packets resent
146 int stat_duppacket = 0; // received duplicate packets
147 int stat_ackpacket_sent = 0; // sent ack packets
148 int stat_ackpacket_recv = 0; // received ack packets
149 int stat_tic_moved = 0; // tics to move player
150 int stat_tic_miss = 0; // tics moved that are missing TICCMD_RECEIVED
151
152 // NetStat globals
153 int netstat_recv_bps, netstat_send_bps;
154 float netstat_lost_percent, netstat_dup_percent; // packets
155 float netstat_gamelost_percent; // tics lost
156
157 // Return true when stats have been updated.
Net_GetNetStat(void)158 boolean Net_GetNetStat(void)
159 {
160 static uint64_t prev_stat_sendbyte = 0;
161
162 tic_t ct = I_GetTime();
163 if( stat_starttic+STAT_PERIOD <= ct )
164 {
165 // Stats are old, update them.
166 netstat_recv_bps = (stat_getbytes*TICRATE)/(ct - stat_starttic);
167 netstat_send_bps = ((stat_sendbytes - prev_stat_sendbyte)*TICRATE)
168 /(ct - stat_starttic);
169
170 netstat_lost_percent = (stat_ackpacket_sent)?
171 100.0*(float)stat_retransmits/(float)stat_ackpacket_sent
172 : 0.0;
173 netstat_dup_percent = (stat_ackpacket_recv)?
174 100.0*(float)stat_duppacket/(float)stat_ackpacket_recv
175 : 0.0;
176 netstat_gamelost_percent = ( stat_tic_moved )?
177 100.0*(float)stat_tic_miss/(float)stat_tic_moved
178 : 0.0;
179
180 prev_stat_sendbyte = stat_sendbytes;
181 stat_getbytes=0;
182 stat_ackpacket_sent = stat_ackpacket_recv = 0;
183 stat_duppacket = stat_retransmits = 0;
184 stat_tic_miss = stat_tic_moved = 0;
185 stat_starttic = ct;
186
187 return 1;
188 }
189 return 0;
190 }
191
192 // -----------------------------------------------------------------
193 // Some stuct and function of ACK packets
194 // -----------------------------------------------------------------
195 // Network Rules:
196 // When a packet with an ack_req number is received, it is acknowledged
197 // by returning that acknum in a later message to the same net node.
198 // If this is not done, the sender will resend, or eventually conclude
199 // that the connection has been lost.
200 // A regular packet has room for one ack_return. There is also a
201 // special packet that can send the whole ack queue to a node.
202 // An acknum is 1..255. An acknum==0 represents no ACK.
203 // The acknum for each net node are independent.
204 // Due to the cmpack comparison method, the waiting ack are limited to a
205 // range of 128. Any compared ack values must be within +/-128.
206
207 // The net node num (nnode) are internal to the Doom program communications.
208 // Net node num are 1..(MAX_CON_NETNODE-1), 0=myself,
209 // MAXNETNODES < MAX_CON_NETNODE
210 // BROADCAST_NODE=MAXNETNODES
211 // BROADCAST_NODE < MAX_CON_NETNODE
212 // limited to 254 (byte), 255=empty.
213 #if ( MAX_CON_NETNODE > 254 )
214 # error Required: MAX_CON_NETNODE <= 254
215 #endif
216 // Player net nodes num 1..MAXNETNODES,
217 // limited to 127 by chat message packing.
218 #if ( MAXNETNODES > 127 )
219 # error Required: MAXNETNODES <= 127
220 #endif
221 // MAXNETNODES must be within MAX_CON_NETNODE, or else it may be rejected
222 #if ( MAXNETNODES >= MAX_CON_NETNODE )
223 # error Required: MAXNETNODES < MAX_CON_NETNODE
224 #endif
225 // BROADCAST_NODE must be within MAX_CON_NETNODE, or else it may be rejected
226 #if ( BROADCAST_NODE >= MAX_CON_NETNODE )
227 # error Required: BROADCAST_NODE < MAX_CON_NETNODE
228 #endif
229
230 // Max ack packets that can be saved. Must exceed the max number of net nodes.
231 #define MAXACKPACKETS 64
232 #if ( MAXACKPACKETS <= MAXNETNODES )
233 # error Required: MAXACKPACKETS > MAXNETNODES
234 #endif
235
236 // Max number of acks to queue for return.
237 #define MAXACKTOSEND 64
238 #define URGENT_ACK_FREE_MIN 6
239 #define ACK_TIMEOUT (TICRATE/17)
240
241 // An aid to traverse a circular ACK queue.
242 #define ACKTOSEND_DEC( ats ) (((ats)+(MAXACKTOSEND-1))%MAXACKTOSEND)
243 #define ACKTOSEND_INC( ats ) (((ats)+1)%MAXACKTOSEND)
244
245 // INC the acknum, not using 0 which is not an ACK.
246 #define ACK_INC_STMT( akn ) if( (++(akn))==0 ) (akn)=1
247 #define ACK_DEC_STMT( akn ) if( (--(akn))==0 ) --(akn)
248
249
250
251 typedef struct {
252 byte acknum;
253 byte acknum_at_xmit; // the current acknum at transmit, and re-transmit.
254 byte destination_node; // dest of the packet (0..(MAXNETNODES-1))
255 byte resent_cnt; // num times has been resent (0..10)
256 tic_t senttime;
257 uint16_t length;
258 byte pak[MAXPACKETLENGTH]; // the packet, for retransmission
259 } ackpak_t;
260
261 typedef enum {
262 NODE_CLOSE = 1, // flag is set when connection is closing
263 } node_flags_e;
264
265 // Table of packets that are waiting for ACK, or to be sent again.
266 // Can be resent (the sender window).
267 static ackpak_t ackpak[MAXACKPACKETS];
268
269 // Node history and ack status.
270 typedef struct {
271 // The next ack to return (like slinding window protocol)
272 // All outstanding ack less than it will also be considered ACK-ed.
273 byte return_ack; // an acknum from a previous msg (0=none)
274
275 // Queue of ACK that must be returned (tail..(head-1)).
276 // Required when packets are not consecutive.
277 // Queue is empty when head=tail. Full when (head+1=tail).
278 byte acktosend_head; // index to acktosend, next insert
279 byte acktosend_tail; // index to acktosend, oldest acknum
280 byte acktosend[MAXACKTOSEND];
281
282 // Send packets with an ack request (reliable).
283 byte next_ackreq_num; // the next ack_req to use
284 // Flow control : to not send too many packets for ack
285 byte remote_prev_ack; // the last ack return received from the net node
286
287 // Automatically send ack packet when not enough traffic (keep alive).
288 tic_t lasttime_ack_returned;
289 // Detect connection lost.
290 tic_t lasttime_packet_received;
291
292 byte flags; // from node_flags_e
293 // jacobson tcp timeout evaluation algorithm (Karn variation)
294 fixed_t ping;
295 fixed_t varping;
296 int timeout; // computed with ping and varping
297 } netnode_t;
298
299 // Ack structure for player net nodes.
300 static netnode_t net_nodes[MAXNETNODES];
301
302 // #define NET_NODE_NUM( nnode ) ( nnode - net_nodes )
303
304 #define PINGDEFAULT ((200*TICRATE*FRACUNIT)/1000)
305 #define VARPINGDEFAULT ( (50*TICRATE*FRACUNIT)/1000)
306 #define PING_TIMEOUT(p,v) ((p)+(4*(v))+(FRACUNIT/2))>>FRACBITS;
307
308 // return <0 if a<b (mod 256)
309 // 0 if a=n (mod 256)
310 // >0 if a>b (mod 256)
311 // mnemonic: to use it compare to 0 : cmpack(a,b)<0 is "a<b" ...
cmpack(byte a,byte b)312 static int cmpack(byte a,byte b)
313 {
314 register int d=a-b;
315
316 if(d>=127 || d<-128)
317 return -d;
318 return d;
319 }
320
321 // Save the netbuffer packet in the ackpak table.
322 // lowtimer : delayed sending
323 // Return the assigned acknum.
324 // Return 0 when fails.
Save_packet_acknum(boolean lowtimer)325 static byte Save_packet_acknum( boolean lowtimer )
326 {
327 boolean low_priority = (netbuffer->packettype >= PT_CANFAIL); // low priority
328 int num_freeslot=0;
329 ackpak_t * ackpakp;
330 byte rnode;
331 netnode_t * np;
332
333 rnode = doomcom->remotenode;
334 if( rnode >= MAXNETNODES )
335 goto ret_fail; // not a player packet
336
337 np = & net_nodes[rnode];
338
339 // Flow control to avoid ack limitations.
340 if(cmpack((byte)(np->remote_prev_ack+MAXACKTOSEND), np->next_ackreq_num) < 0)
341 goto too_fast; // outstanding ack approaching limit of queue
342
343 for( ackpakp = &ackpak[0]; ackpakp < &ackpak[MAXACKPACKETS]; ackpakp++ )
344 {
345 // Visit unused ackpak.
346 if(ackpakp->acknum==0)
347 {
348 // Found an unused ackpak.
349 if( low_priority )
350 {
351 // For low priority packet, make sure to leave some ackpak
352 // free so urgent packets can be sent.
353 num_freeslot++;
354 if( num_freeslot < URGENT_ACK_FREE_MIN )
355 continue; // skip, until have enough free ackpak
356 }
357
358 // Save the packet and issue an acknum.
359 ackpakp->acknum = np->next_ackreq_num;
360 ackpakp->acknum_at_xmit = np->next_ackreq_num; // first transmit
361 ACK_INC_STMT( np->next_ackreq_num ); // skip acknum 0
362 ackpakp->destination_node = rnode;
363 ackpakp->length = doomcom->datalength;
364
365 if(lowtimer)
366 {
367 // lowtimer means it can't be sent now so try it soon as possible
368 ackpakp->senttime = 0;
369 ackpakp->resent_cnt = 1;
370 }
371 else
372 {
373 ackpakp->senttime = I_GetTime();
374 ackpakp->resent_cnt = 0;
375 }
376 memcpy(ackpakp->pak, netbuffer, ackpakp->length);
377
378 stat_ackpacket_sent++; // for stat
379
380 return ackpakp->acknum; // return the acknum
381 }
382 }
383 // Did not find free ackpacket.
384 #ifdef PARANOIA
385 if( devparm )
386 CONS_Printf("No more free ackpacket\n");
387 #endif
388 // FIXME: wrong message or wrong place for this message.
389 if( netbuffer->packettype < PT_CANFAIL ) // high priority
390 {
391 I_SoftError("Connection lost\n");
392 }
393 return 0;
394
395 // Rare errors.
396 too_fast:
397 DEBFILE(va("Node %: too fast %d %d\n",
398 rnode, np->remote_prev_ack, np->next_ackreq_num));
399 // Fail to send, to avoid overrunning dest buffers.
400 goto ret_fail;
401
402 ret_fail:
403 return 0;
404 }
405
406 // Get the ack to send, from the ack queue of this node.
407 // nnode: 0..(MAXNETNODES-1)
Get_return_ack(byte nnode)408 static byte Get_return_ack(byte nnode)
409 {
410 net_nodes[nnode].lasttime_ack_returned = I_GetTime();
411 return net_nodes[nnode].return_ack;
412 }
413
414 // Dispense with any packet that has been waiting for this ACK.
415 // ackpakp : the ackpak to be removed
416 // Called when have received an ack from the net node.
Remove_ackpak(ackpak_t * ackpakp)417 static void Remove_ackpak( ackpak_t * ackpakp )
418 {
419 netnode_t * dnp;
420 byte dnode = ackpakp->destination_node; // 0..(MAXNETNODES-1) by caller
421
422 if( dnode >= MAXNETNODES ) // invalid node number
423 {
424 ackpakp->acknum=0; // ackpak is now idle
425 return;
426 }
427
428 dnp = & net_nodes[dnode]; // dest node of the ackpak
429
430 // Stats
431 fixed_t trueping = (I_GetTime() - ackpakp->senttime) << FRACBITS;
432
433 if( ackpakp->resent_cnt )
434 {
435 // +FRACUNIT/2 for round
436 dnp->ping = (dnp->ping*7 + trueping)/8;
437 dnp->varping = (dnp->varping*7 + abs(dnp->ping - trueping))/8;
438 dnp->timeout = PING_TIMEOUT(dnp->ping, dnp->varping);
439 }
440 DEBFILE(va("Remove ack %d trueping %d ping %f var %f timeout %d\n",
441 ackpakp->acknum, trueping>>FRACBITS,
442 FIXED_TO_FLOAT(dnp->ping), FIXED_TO_FLOAT(dnp->varping),
443 dnp->timeout));
444
445 ackpakp->acknum=0; // ackpak is now idle
446
447 if( dnp->flags & NODE_CLOSE )
448 {
449 // Marked to close when all ACK have been settled.
450 Net_CloseConnection( dnode, 0 );
451 }
452 }
453
454 // We have got a packet, proceed with the ack request and ack return.
455 // Return false when acknum indicates it is a duplicate packet.
Process_packet_ack()456 static boolean Process_packet_ack()
457 {
458 int ati; // acktosend index
459 ackpak_t * ackpakp;
460 byte acknum;
461 byte nxtack; // ACK are 1..255, circular
462 byte rnode;
463 netnode_t * np;
464
465 rnode = doomcom->remotenode; // net node num
466 if( rnode >= MAXNETNODES )
467 goto ret_fail; // not a player net node
468
469 np = & net_nodes[rnode];
470
471 // Only process an ack return if it is greater than the previous ack.
472 if(netbuffer->ack_return
473 && cmpack(np->remote_prev_ack, netbuffer->ack_return) < 0)
474 {
475 // Received an ack_return, remove the ack from the ackpak.
476 np->remote_prev_ack = netbuffer->ack_return;
477 // Search the ackbuffer for net node and free it.
478 for( ackpakp = &ackpak[0]; ackpakp < &ackpak[MAXACKPACKETS]; ackpakp++ )
479 {
480 // Remove all ackpak waiting for acknum that are <= ack_return.
481 if( ackpakp->acknum
482 && ackpakp->destination_node == rnode
483 && cmpack(ackpakp->acknum, netbuffer->ack_return) <= 0 )
484 {
485 Remove_ackpak( ackpakp );
486 }
487 }
488 }
489
490 if( netbuffer->ack_req )
491 {
492 // Received a packet with ack_req, put it in queue to send the ack back.
493 acknum = netbuffer->ack_req;
494 stat_ackpacket_recv++;
495 if( cmpack(acknum, np->return_ack) <= 0 )
496 goto dup_by_range;
497
498 // Check if the acknum is already in the queue.
499 // Check active queue, tail..(head-1).
500 for(ati = np->acktosend_tail;
501 ati != np->acktosend_head;
502 ati = ACKTOSEND_INC(ati) )
503 {
504 if(np->acktosend[ati] == acknum) goto dup_ackpak_found;
505 }
506
507 // Is a good packet so update the queue and return_ack.
508 // Must search for holes in the queue.
509 // Can only return ack when all previous ack have been received.
510
511 // A missing acknum in the queue indicates a missing packet.
512 // Higher acknum will be blocked waiting for them.
513 // Because of this, received ack will not remove ack queue
514 // entries until return_ack is greater.
515
516 // Find next return_ack.
517 nxtack = np->return_ack;
518 ACK_INC_STMT( nxtack ); // skip acknum 0
519
520 if(acknum == nxtack)
521 {
522 // This packet is next in order, which allows for ack cleanup.
523 byte hm1; // head-1
524 boolean change=true;
525
526 np->return_ack = nxtack;
527 ACK_INC_STMT( nxtack ); // skip acknum 0
528
529 hm1 = ACKTOSEND_DEC( np->acktosend_head ); // latest queue entry
530 // Find which ackpak can be ACK by return_ack.
531 while(change)
532 {
533 change=false;
534 // Search queue tail..(head-1)
535 // Find each acknum in seq. Must deal with missing ack.
536 for( ati = np->acktosend_tail;
537 ati != np->acktosend_head;
538 ati= ACKTOSEND_INC(ati) )
539 {
540 if( cmpack(np->acktosend[ati],nxtack) <= 0 )
541 {
542 // Older acknum that is covered by this ack.
543 if( np->acktosend[ati]==nxtack )
544 {
545 // Found the next acknum.
546 // ACK this packet, and all older acknum.
547 np->return_ack = nxtack;
548 ACK_INC_STMT( nxtack ); // skip acknum 0
549 change=true;
550 // The ack will only be released if it is at the
551 // tail or head of the queue.
552 }
553 // The queue is in order of arrival of ack_req,
554 // which will not always be acknum ordered.
555 // All acknum less than nxtack will be considered
556 // ACK-ed by the current return_ack. This also
557 // catches out-of-order ack_req.
558 if( ati == np->acktosend_tail )
559 {
560 // Release the covered acknum at the tail.
561 np->acktosend[np->acktosend_tail] = 0;
562 np->acktosend_tail = ACKTOSEND_INC(ati);
563 }
564 else if( ati == hm1 )
565 {
566 // Release the latest queue entry.
567 np->acktosend[hm1] = 0;
568 np->acktosend_head = hm1; // move queue head
569 hm1 = ACKTOSEND_DEC( hm1 );
570 break; // this was last checkable queue entry
571 }
572 // Putting holes in the queue would interfere with
573 // the cmpack test, which cannot handle 0. It would
574 // not save any queue space unless entries were moved.
575 }
576 }
577 }
578 }
579 else
580 { // Out of order packet ( acknum != nxtack ).
581 // Do not update the return_ack.
582 // Put this ack in asktosend queue.
583 // return_ack will be incremented when the next ack comes.
584 byte newhead = ACKTOSEND_INC(np->acktosend_head);
585 DEBFILE(va("Out of order packet: expected %d\n", nxtack));
586 if(newhead == np->acktosend_tail) goto queue_full;
587
588 np->acktosend[np->acktosend_head] = acknum;
589 np->acktosend_head = newhead;
590 }
591 }
592 return true;
593
594 queue_full:
595 // The ack queue is full. Discard the packet, sender will resend it.
596 // If we admit the packet we will not detect the duplication after :(
597 DEBFILE("Ack Queue full.\n");
598 return false;
599
600 dup_by_range:
601 // Any acknum < return_ack have already been considered ACK-ed.
602 // Duplicate packet (per ack_req).
603 DEBFILE(va("Discard (by range) ack %d (duplicated)\n", acknum));
604 goto dup_reject;
605
606 dup_ackpak_found:
607 // Already received, ack is in the queue.
608 DEBFILE(va("Discard ack %d (duplicated)\n", acknum));
609 goto dup_reject;
610
611 dup_reject:
612 stat_duppacket++;
613 // Discard the packet (duplicate)
614 ret_fail:
615 return false;
616 }
617
618 #if MAXACKTOSEND > MAX_NETBYTE_LEN
619 # error Netbuffer: MAXACKTOSEND > MAX_NETBYTE_LEN
620 #endif
621
622 // Send a special packet with only the ack queue.
623 // to_node: 0..(MAXNETNODES-1)
Net_Send_AcksPacket(int to_node)624 void Net_Send_AcksPacket(int to_node)
625 {
626 // Send an packet with the ack queue.
627 netbuffer->packettype = PT_ACKS;
628 memcpy(netbuffer->u.bytepak.b, net_nodes[to_node].acktosend, MAXACKTOSEND);
629 HSendPacket( to_node, 0, 0, MAXACKTOSEND );
630 }
631
632 // Receive the special packet with only acks.
Got_AcksPacket(void)633 static void Got_AcksPacket(void)
634 {
635 int j;
636 byte rnode;
637 byte recv_acknum; // acknum from the packet
638 ackpak_t * ackpakp;
639
640 rnode = doomcom->remotenode;
641 if( rnode >= MAXNETNODES )
642 return; // not a player packet
643
644 // The body of the packet bytepak is the ack queue.
645 for(j=0;j<MAXACKTOSEND;j++)
646 {
647 recv_acknum = netbuffer->u.bytepak.b[j]; // from the queue in the packet
648 if( recv_acknum == 0 ) continue; // 0=invalid
649
650 // Find recv_acknum in our ack packets queue.
651 // Without regards to queue head or tail.
652 for( ackpakp = &ackpak[0]; ackpakp < &ackpak[MAXACKPACKETS]; ackpakp++ )
653 {
654 if( ackpakp->acknum
655 && ackpakp->destination_node == rnode)
656 {
657 if( ackpakp->acknum == recv_acknum )
658 {
659 // Dispense with any packets that have been ACK'ed.
660 Remove_ackpak( ackpakp );
661 }
662 else
663 {
664 // As later acknum are received there is bigger
665 // chance a packet is lost.
666 // When the packet is first transmitted, or resent,
667 // acknum_at_xmit is updated to the
668 // net_nodes[rnode].next_ackreq_num.
669 if( cmpack(ackpakp->acknum_at_xmit, recv_acknum) <= 0 )
670 {
671 // Will cause sooner retransmits of older packets
672 // as the packet's acknum age.
673 if( ackpakp->senttime > 0 )
674 ackpakp->senttime--; // hurry up
675 }
676 }
677 }
678 }
679 }
680 }
681
682
683 // nnode: 1..(MAXNETNODES-1)
Net_ConnectionTimeout(byte nnode)684 void Net_ConnectionTimeout( byte nnode )
685 {
686 netbuffer_t * rebp = & reboundstore[rebound_head];
687 // Send a very special packet to self (hack the reboundstore queu).
688 // Main code will handle it.
689 rebp->packettype = PT_NODE_TIMEOUT;
690 rebp->ack_req = 0;
691 rebp->ack_return = 0;
692 rebp->u.bytepak.b[0] = nnode;
693
694 reboundsize[rebound_head] = PACKET_BASE_SIZE+1;
695 rebound_head=(rebound_head+1)%MAXREBOUND;
696
697 // do not redo it quickly (if we do not close connection is for a good reason !)
698 net_nodes[nnode].lasttime_packet_received = I_GetTime();
699 }
700
701 // Resend some packets, if needed.
Net_AckTicker(void)702 void Net_AckTicker(void)
703 {
704 int nn; // net node num
705 // Get the time once. It does not change that fast, and this
706 // keeps the record times consistent in this function.
707 tic_t curtime = I_GetTime();
708 ackpak_t * ackpakp;
709 netnode_t * np;
710
711 // Check all ackpak for old packets.
712 for( ackpakp = &ackpak[0]; ackpakp < &ackpak[MAXACKPACKETS]; ackpakp++ )
713 {
714 if(ackpakp->acknum == 0) continue; // 0=inactive
715
716 // An active ackpak.
717 np = & net_nodes[ackpakp->destination_node];
718 if((ackpakp->senttime + np->timeout) >= curtime) continue;
719
720 // Need to retransmit
721 nn = ackpakp->destination_node;
722 if( (ackpakp->resent_cnt > 10) && (np->flags & NODE_CLOSE) )
723 {
724 DEBFILE(va("Node %d: ack %d sent 10 times so connection is supposed lost\n",
725 nn, ackpakp->acknum));
726 Net_CloseConnection( nn, 1 ); // forced close
727
728 ackpakp->acknum = 0; // inactive
729 continue;
730 }
731
732 // Retransmit
733 DEBFILE(va("Node %d: Resend ack %d, %d+%d<%d\n", nn,
734 ackpakp->acknum, ackpakp->senttime, np->timeout, curtime));
735 memcpy(netbuffer, ackpakp->pak, ackpakp->length);
736 ackpakp->senttime = curtime;
737 ackpakp->resent_cnt++;
738 ackpakp->acknum_at_xmit = np->next_ackreq_num;
739 HSendPacket( nn, 0, ackpakp->acknum, ackpakp->length - PACKET_BASE_SIZE );
740 stat_retransmits++; // for stat
741 }
742
743 for( nn=1; nn<MAXNETNODES; nn++)
744 {
745 np = & net_nodes[nn];
746 // Using this something like a node open flag.
747 if( np->return_ack )
748 {
749 // If we haven't sent a packet for a long time,
750 // send acknowledge packets if needed.
751 if( (np->lasttime_ack_returned + ACK_TIMEOUT) < curtime )
752 Net_Send_AcksPacket(nn);
753
754 if( (np->lasttime_packet_received + CONNECTION_TIMEOUT) < curtime
755 && (np->flags & NODE_CLOSE) == 0 )
756 {
757 Net_ConnectionTimeout( nn );
758 }
759 }
760 }
761 }
762
763
764 // Cancel the ack of the last packet received. This forces the net node
765 // to resend it. This is an escape when the higher layer don't have room,
766 // or something else ....)
767 // nnode: 0..(MAXNETNODES-1)
Net_Cancel_Packet_Ack(int nnode)768 void Net_Cancel_Packet_Ack(int nnode)
769 {
770 netnode_t * np;
771 int hm1;
772 byte nxtack;
773 byte cancel_acknum = netbuffer->ack_req; // acknum to cancel
774
775 DEBFILE(va("UnAck node %d\n",nnode));
776
777 if(!nnode)
778 return; // net node 0 is self
779 if(cancel_acknum==0)
780 return; // cannot cancel acknum==0
781
782 np = & net_nodes[nnode];
783 nxtack = np->return_ack;
784 hm1 = ACKTOSEND_DEC( np->acktosend_head ); // last entry
785 if( np->acktosend[hm1] == cancel_acknum )
786 {
787 // Remove canceled ack from the queue head.
788 np->acktosend[hm1] = 0;
789 np->acktosend_head = hm1;
790 }
791 else
792 #if 0
793 // This is unneeded as it is a subset of the next case.
794 if( nxtack == cancel_acknum )
795 {
796 // Only one ack needs to be undone.
797 ACK_DEC_STMT( nxtack );
798 np->return_ack = nxtack;
799 }
800 else
801 #endif
802 {
803 // Put at the queue tail, all the intervening ack num.
804 // If nxtack==cancel_acknum already, then only the return_ack needs
805 // to be updated.
806 // Leaving a hole in the queue would indicate missing packets, and it
807 // would wait for them, never sending the later ACK.
808 // This assumes they all fit, since they were just all removed.
809 // The canceled acknum must NOT be put in the queue.
810 while (nxtack != cancel_acknum)
811 {
812 // Put nxtack back into the queue.
813 np->acktosend_tail = ACKTOSEND_DEC( np->acktosend_tail );
814 np->acktosend[np->acktosend_tail] = nxtack;
815
816 ACK_DEC_STMT( nxtack );
817 }
818 // nxtack==cancel_acknum, and the canceled acknum is NOT in the queue.
819 #if 1
820 // The return_ack must be set just before the canceled acknum.
821 nxtack = cancel_acknum;
822 ACK_DEC_STMT( nxtack );
823 #else
824 // [WDJ] Bug: For the nxtack!=cancel_acknum case, it undid the DEC of
825 // return_ack, which would have left return_ack greater than the
826 // canceled acknum. This would be the same as not canceling the ack.
827 ACK_INC_STMT( nxtack );
828 // This has now been combined with the nxtack==acknum case, because
829 // the return_ack must be set just less than the canceled acknum in
830 // both cases.
831 #endif
832 np->return_ack = nxtack;
833 }
834 }
835
836 // Return true if all ackpak have been received.
Net_Test_AllAckReceived(void)837 boolean Net_Test_AllAckReceived(void)
838 {
839 ackpak_t * ackpakp;
840
841 for( ackpakp = &ackpak[0]; ackpakp < &ackpak[MAXACKPACKETS]; ackpakp++ )
842 {
843 if(ackpakp->acknum)
844 return false;
845 }
846
847 return true;
848 }
849
850 // Wait for all ack_return.
851 // timeout : in seconds
Net_Wait_AllAckReceived(uint32_t timeout)852 void Net_Wait_AllAckReceived( uint32_t timeout )
853 {
854 tic_t ct = I_GetTime(); // current time
855
856 timeout = ct + timeout*TICRATE; // convert timeout to absolute time
857
858 HGetPacket();
859 while( !Net_Test_AllAckReceived() )
860 {
861 while(ct == I_GetTime()) { } // wait for next tic
862 HGetPacket();
863 Net_AckTicker();
864 ct = I_GetTime();
865 if( ct > timeout ) break; // Timeout
866 }
867 }
868
869 // Init Ack for player net nodes.
870 // nnode: 0..(MAXNETNODES-1)
InitNode(int nnode)871 static void InitNode( int nnode )
872 {
873 netnode_t * np = & net_nodes[nnode];
874 np->acktosend_head = 0;
875 np->acktosend_tail = 0;
876 np->ping = PINGDEFAULT;
877 np->varping = VARPINGDEFAULT;
878 np->timeout = PING_TIMEOUT(np->ping,np->varping);
879 np->return_ack = 0;
880 np->next_ackreq_num = 1;
881 np->remote_prev_ack = 0;
882 np->flags = 0;
883 }
884
InitAck()885 static void InitAck()
886 {
887 int i;
888
889 for(i=0;i<MAXACKPACKETS;i++)
890 ackpak[i].acknum=0;
891
892 for(i=0;i<MAXNETNODES;i++)
893 InitNode( i ); // Init Ack for player net nodes.
894 }
895
896 // Remove from retransmit any packets of the indicated type.
Net_AbortPacketType(byte packettype)897 void Net_AbortPacketType(byte packettype)
898 {
899 ackpak_t * ackpakp;
900
901 // Check the retransmit ackpak for these type packets.
902 for( ackpakp = &ackpak[0]; ackpakp < &ackpak[MAXACKPACKETS]; ackpakp++ )
903 {
904 if( ackpakp->acknum == 0 ) continue;
905 #if 1
906 if( ((netbuffer_t *)ackpakp->pak)->packettype==packettype )
907 #else
908 // [WDJ] UNUSED: and not likely to be used.
909 // packettype=255 is ANY packet
910 if( packettype==255
911 || (((netbuffer_t *)ackpakp->pak)->packettype==packettype) )
912 #endif
913 {
914 // Free the ackpak.
915 ackpakp->acknum=0;
916 }
917 }
918 }
919
920 // -----------------------------------------------------------------
921 // end of acknowledge function
922 // -----------------------------------------------------------------
923
924
925 // Server
926 // Client also calls this to close connection to server.
927 // Remove a node, clear all ack from this node and reset askret
928 // nnode : the net node number, 0..(MAX_CON_NETNODE-1)
929 // forceclose : do not wait for ACK, close now
Net_CloseConnection(byte nnode,byte forceclose)930 void Net_CloseConnection(byte nnode, byte forceclose)
931 {
932 ackpak_t * ackpakp;
933
934 if( nnode >= MAXNETNODES )
935 {
936 // invalid node number, or BROADCAST_NODE
937 if( nnode < MAX_CON_NETNODE ) goto free_done; // old code like dosnet
938 return;
939 }
940
941 if( nnode == 0 )
942 return; // Cannot close self connection.
943
944 // Shutdown player net node.
945 net_nodes[nnode].flags |= NODE_CLOSE;
946
947 // Try to Send ack back (two army problem).
948 if( net_nodes[nnode].return_ack )
949 {
950 // Send some empty packets with acks.
951 Net_Send_AcksPacket( nnode );
952 Net_Send_AcksPacket( nnode );
953 }
954
955 // Check if we have to wait for ack from this node.
956 for( ackpakp = &ackpak[0]; ackpakp < &ackpak[MAXACKPACKETS]; ackpakp++ )
957 {
958 if( ackpakp->acknum
959 && ackpakp->destination_node == nnode )
960 {
961 if( !forceclose )
962 return; // connection will be closed when ack is returned
963
964 // Net Timeout, ack not likely. Force close.
965 ackpakp->acknum = 0; // inactive
966 }
967 }
968
969 // No waiting for ack from this net node.
970 Abort_SendFiles(nnode);
971 InitNode(nnode);
972
973 free_done:
974 I_NetFreeNode(nnode);
975 return;
976 }
977
978 //
979 // Checksum
980 //
981 // Return in net endian
Netbuffer_Checksum(void)982 static uint32_t Netbuffer_Checksum (void)
983 {
984 int i, len;
985 uint32_t cs;
986 unsigned char *buf;
987
988 cs = 0x1234567;
989
990 len = doomcom->datalength - 4;
991 buf = (unsigned char*)netbuffer+4;
992 for (i=0 ; i<len ; i++,buf++)
993 cs += (*buf) * (i+1);
994
995 return LE_SWAP32_FAST(cs);
996 }
997
998 #ifdef DEBUGFILE
999
1000 // Align to 4 byte
1001 #define ALIGN4(p) (byte *)(((uintptr_t)(p) + 3) & ~0x03)
1002
1003 static inline
DN_read_N16(N16_t * vf)1004 uint16_t DN_read_N16( N16_t * vf )
1005 {
1006 // LSB first
1007 return (((uint16_t)(vf->b[1]))<<8) | vf->b[0];
1008 }
1009
1010 static inline
DN_read_N32(N32_t * vf)1011 uint32_t DN_read_N32( N32_t * vf )
1012 {
1013 // LSB first
1014 return (((((((uint32_t)(vf->b[3]))<<8) | vf->b[2])<<8) | vf->b[1])<<8) | vf->b[0];
1015 }
1016
1017
fprintfstring(byte * s,byte len)1018 static void fprintfstring(byte *s,byte len)
1019 {
1020 int i;
1021 int mode=0;
1022
1023 for (i=0 ; i<len ; i++)
1024 {
1025 if(s[i]<32)
1026 {
1027 if(mode==0) {
1028 fprintf (debugfile,"[%d", s[i]);
1029 mode = 1;
1030 } else
1031 fprintf (debugfile,",%d", s[i]);
1032 }
1033 else
1034 {
1035 if(mode==1) {
1036 fprintf (debugfile,"]");
1037 mode=0;
1038 }
1039 fprintf (debugfile,"%c", s[i]);
1040 }
1041 }
1042 if(mode==1) fprintf (debugfile,"]");
1043 fprintf(debugfile,"\n");
1044 }
1045
1046 static const char *packettypename[NUMPACKETTYPE]={
1047 "NOTHING",
1048 "SERVERCFG",
1049 "CLIENTCMD",
1050 "CLIENTMIS",
1051 "CLIENT2CMD", // NO LONGER USED
1052 "CLIENT2MIS", // NO LONGER USED
1053 "NODEKEEPALIVE",
1054 "NODEKEEPALIVEMIS",
1055 "SERVERTICS",
1056 "SERVERREFUSE",
1057 "SERVERSHUTDOWN",
1058 "CLIENTQUIT",
1059
1060 "ASKINFO",
1061 "SERVERINFO",
1062 "REQUESTFILE",
1063 "DUMMY15",
1064 "ACKS",
1065 "STATE",
1066 "DUMMY18",
1067 "DUMMY19",
1068
1069 "FILEFRAGMENT",
1070 "TEXTCMD",
1071 "TEXTCMD2", // NO LONGER USED
1072 "CLIENTJOIN",
1073 "NODETIMEOUT",
1074 "NETWAITINFO",
1075 "CLIENTREADY",
1076 "REPAIR",
1077 "CONTROL",
1078 "REQ_SERVERPLAYER",
1079 "SERVERPLAYER",
1080 "REQ_SERVERLEVEL",
1081 "SERVERLEVEL",
1082 "REQ_CLIENTCFG",
1083 };
1084
1085 static const char * control_name[]={
1086 "state", // no node command
1087 "normal",
1088 "download_savegame",
1089 "wait_game_start",
1090 "game_start",
1091 "wait_timer",
1092 };
1093
1094 static const char * player_state_name[]={
1095 // [1]
1096 "PLAYER",
1097 "PLAYER_FROM_SERVER",
1098 "PLAYER_FROM_SAVEGAME",
1099 "BOT",
1100 "JOIN_WAIT_GAME_START",
1101 "ADDED",
1102 "ADDED_COMMIT"
1103 // [8]
1104 };
1105
1106
1107 static const char * repair_name_to_client[]={
1108 "NULL",
1109 "PLAYER",
1110 "SUG_SAVEGAME",
1111 #if 0
1112 "MONSTER", // not yet implemented
1113 "OBJECT", // not yet implemented
1114 #endif
1115 };
1116 // to server [32]
1117 static const char * repair_name_to_server[]={
1118 "REQ_TO_SERVER",
1119 "REQ_SAVEGAME",
1120 "REQ_PLAYER",
1121 "REQ_ALLPLAYER",
1122 };
1123 // Ack/Nak [64]
1124 static const char * repair_name_ack[]={
1125 "CLOSE_ACK",
1126 "CLOSE_NACK",
1127 "SAVEGAME_REJ",
1128 };
1129
1130
DF_PrintRand(random_state_t * rs)1131 static void DF_PrintRand( random_state_t * rs )
1132 {
1133 fprintf(debugfile, " P_rand index %i, B_rand_index %i, E_rand1 %4X E_rand2 %4X\n",
1134 rs->p_rand_index, rs->b_rand_index, DN_read_N32(&rs->e_rand1), DN_read_N32(&rs->e_rand2) );
1135 }
1136
DF_Print_textbuf(textbuf_t * tp)1137 static void DF_Print_textbuf( textbuf_t * tp )
1138 {
1139 fprintf(debugfile, " len %d text=", tp->len );
1140 fprintfstring( (byte*)&tp->text, tp->len );
1141 // return sizeof_textbuf_t(tp->len);
1142 }
1143
DF_Print_textitem(textcmd_item_t * ti)1144 static unsigned int DF_Print_textitem( textcmd_item_t * ti )
1145 {
1146 fprintf(debugfile, " player %d", ti->pn );
1147 DF_Print_textbuf( &ti->textbuf );
1148 return sizeof_textcmd_item_t( ti->textbuf.len );
1149 }
1150
DF_Print_servertic_textcmd(servertic_textcmd_t * stcp)1151 static unsigned int DF_Print_servertic_textcmd( servertic_textcmd_t * stcp )
1152 {
1153 int stlen = DN_read_N16( & stcp->len );
1154 fprintf(debugfile, " servertic_textcmd tic %8d len %d\n", ExpandTics(stcp->tic), stlen );
1155 byte * bp = (byte*) & stcp->textitem;
1156 byte * endbp = bp + stlen;
1157 while( bp < endbp )
1158 {
1159 bp += DF_Print_textitem( (textcmd_item_t*) bp );
1160 }
1161 return sizeof_servertic_textcmd_t( stlen );
1162 }
1163
DF_Print_MobjPos(mobj_pos_t * mp)1164 static void DF_Print_MobjPos( mobj_pos_t * mp )
1165 {
1166 fprintf(debugfile, " x %i.%i, y %i.%i, z %i.%i, momx %i.%i, momy %i.%i, momz %i,%i, angle %0x\n",
1167 mp->x >> 16, mp->x & 0xFFFF,
1168 mp->y >> 16, mp->y & 0xFFFF,
1169 mp->z >> 16, mp->z & 0xFFFF,
1170 mp->momx >> 16, mp->momx & 0xFFFF,
1171 mp->momy >> 16, mp->momy & 0xFFFF,
1172 mp->momz >> 16, mp->momz & 0xFFFF,
1173 mp->angle );
1174 }
1175
DF_Print_PlayerDesc(player_desc_t * pdsp)1176 static void DF_Print_PlayerDesc( player_desc_t * pdsp )
1177 {
1178 byte * bp = (byte*) &pdsp->pd;
1179 byte cnt = pdsp->entry_count;
1180 byte desc_flags = pdsp->desc_flags;
1181 fprintf(debugfile, " player desc: desc_flags %d, entry_count %d\n", desc_flags, cnt );
1182
1183 while(cnt--)
1184 {
1185 int i;
1186 bp = ALIGN4(bp); // align to 4 bytes
1187 pd_player_t * pdp = (pd_player_t*) bp;
1188
1189 fprintf(debugfile, " id_num %d state %d flags %X health %d armortype %d armor %d weapon %d\n",
1190 pdp->pid, pdp->playerstate, pdp->flags, LE_SWAP16(pdp->health), pdp->armortype, LE_SWAP16(pdp->armor), pdp->readyweapon );
1191 DF_Print_MobjPos(& pdp->pos );
1192 fprintf(debugfile, " ammo:");
1193 for( i=0; i<NUMAMMO; i++ )
1194 {
1195 fprintf(debugfile, " %d/%d", LE_SWAP16( pdp->ammo[i] ), LE_SWAP16( pdp->maxammo[i] ) );
1196 }
1197 bp += offsetof( pd_player_t, optional );
1198
1199 if( desc_flags & PDI_inventory )
1200 {
1201 pd_inventory_t * pi = (pd_inventory_t*) bp;
1202 fprintf(debugfile, " inventory: slot %d ", pi->inventoryslotnum );
1203 for( i=0; i<NUMINVENTORYSLOTS; i++ )
1204 {
1205 fprintf(debugfile, " (%d,%d)", pi->inventory[i].type, pi->inventory[i].count );
1206 }
1207 bp += sizeof(pd_inventory_t);
1208 }
1209 }
1210 }
1211
1212
DebugPrintpacket(char * header)1213 static void DebugPrintpacket(char *header)
1214 {
1215 fprintf(debugfile, "%-12s (node %d,ackreq %d,ackret %d,size %d) type(%d) : %s\n",
1216 header,
1217 doomcom->remotenode,
1218 netbuffer->ack_req, netbuffer->ack_return,
1219 doomcom->datalength,
1220 netbuffer->packettype,packettypename[netbuffer->packettype] );
1221
1222 switch(netbuffer->packettype)
1223 {
1224 case PT_ASKINFO:
1225 fprintf(debugfile, " send_time %u\n",
1226 (unsigned int)netbuffer->u.askinfo.send_time );
1227 break;
1228 case PT_CLIENTJOIN:
1229 fprintf(debugfile, " number_players %d mode %d flags %X\n",
1230 netbuffer->u.clientcfg.num_node_players,
1231 netbuffer->u.clientcfg.mode,
1232 netbuffer->u.clientcfg.flags );
1233 break;
1234 case PT_SERVERTICS:
1235 {
1236 byte num_cmd = netbuffer->u.serverpak.num_cmds_present;
1237 byte num_txt = netbuffer->u.serverpak.num_textcmd;
1238 byte * bp;
1239 fprintf(debugfile, " firsttic %8d num_tics %d cmd_player_mask %X flags %X cmds_offset %i num_cmd %i num_textcmd %i\n",
1240 ExpandTics (netbuffer->u.serverpak.starttic), netbuffer->u.serverpak.numtics,
1241 DN_read_N32(&netbuffer->u.serverpak.cmd_player_mask), netbuffer->u.serverpak.flags,
1242 netbuffer->u.serverpak.cmds_offset, num_cmd, num_txt );
1243 // textcmd
1244 bp = (byte *)&netbuffer->u.serverpak.cmds[num_cmd];
1245 while(num_txt--)
1246 {
1247 bp += DF_Print_servertic_textcmd( (servertic_textcmd_t *)bp );
1248 }
1249 }
1250 break;
1251 case PT_CLIENTCMD:
1252 case PT_CLIENT2CMD:
1253 case PT_CLIENTMIS:
1254 case PT_CLIENT2MIS:
1255 case PT_NODEKEEPALIVE:
1256 case PT_NODEKEEPALIVEMIS:
1257 fprintf(debugfile, " tic %8d resendfrom %4d pind_mask %X\n",
1258 ExpandTics (netbuffer->u.clientpak.client_tic),
1259 ExpandTics (netbuffer->u.clientpak.resendfrom),
1260 netbuffer->u.clientpak.pind_mask );
1261 break;
1262 case PT_TEXTCMD:
1263 case PT_TEXTCMD2:
1264 {
1265 byte num_txt = netbuffer->u.textcmdpak.num_textitem;
1266 byte * bp = (byte*)&netbuffer->u.textcmdpak.textitem;
1267 while(num_txt--)
1268 {
1269 bp += DF_Print_textitem( (textcmd_item_t*) bp );
1270 }
1271 }
1272 break;
1273 case PT_SERVERCFG:
1274 fprintf(debugfile, " playermask %X numplayers %d clientnode %d serverplayer %d gametic %8u gamestate %d command %s\n",
1275 DN_read_N32(&netbuffer->u.servercfg.playerdetected),
1276 netbuffer->u.servercfg.num_game_players,
1277 netbuffer->u.servercfg.clientnode,
1278 netbuffer->u.servercfg.serverplayer,
1279 DN_read_N32(&netbuffer->u.servercfg.gametic),
1280 netbuffer->u.servercfg.gamestate,
1281 control_name[netbuffer->u.servercfg.command] );
1282 break;
1283 case PT_SERVERINFO :
1284 fprintf(debugfile, " '%s' player %i/%i, map %s, filenum %d, time %u, deathmatch %d \n",
1285 netbuffer->u.serverinfo.servername,
1286 netbuffer->u.serverinfo.num_active_players, netbuffer->u.serverinfo.maxplayer,
1287 netbuffer->u.serverinfo.mapname,
1288 netbuffer->u.serverinfo.num_fileneed,
1289 (unsigned int)netbuffer->u.serverinfo.trip_time,
1290 netbuffer->u.serverinfo.deathmatch );
1291 fprintfstring(netbuffer->u.serverinfo.fileneed,(char *)netbuffer+doomcom->datalength-(char *)netbuffer->u.serverinfo.fileneed);
1292 break;
1293 case PT_SERVERREFUSE :
1294 fprintf(debugfile, " reason %s\n",
1295 netbuffer->u.stringpak.str );
1296 break;
1297 case PT_REPAIR :
1298 {
1299 byte repairtype = netbuffer->u.repair.repair_type;
1300 const char * rtstr = NULL;
1301 if( repairtype < 3 )
1302 rtstr = repair_name_to_client[repairtype];
1303 else if( (repairtype >= 32) && (repairtype < (32+4)) )
1304 rtstr = repair_name_to_server[repairtype - 32];
1305 else if( (repairtype >= 64) && (repairtype < (64+3)) )
1306 rtstr = repair_name_ack[repairtype - 64];
1307
1308 if( rtstr )
1309 fprintf(debugfile, " %s", rtstr );
1310 else
1311 fprintf(debugfile, " repairtype %i", repairtype );
1312
1313 fprintf(debugfile, " tic %8d", DN_read_N32(&netbuffer->u.repair.gametic) );
1314 DF_PrintRand( &netbuffer->u.repair.rs );
1315 switch(netbuffer->u.repair.repair_type)
1316 {
1317 case RQ_REQ_PLAYER:
1318 fprintf(debugfile, " player %d\n", netbuffer->u.repair.u.player_id );
1319 break;
1320 case RQ_PLAYER:
1321 DF_Print_PlayerDesc( & netbuffer->u.repair.u.player_desc );
1322 break;
1323 default:
1324 fprintf(debugfile, "\n" );
1325 break;
1326 };
1327 }
1328 break;
1329 case PT_STATE :
1330 fprintf(debugfile, " tic %8d, sever_pause %d\n",
1331 DN_read_N32(&netbuffer->u.state.gametic), netbuffer->u.state.server_pause );
1332 DF_PrintRand( &netbuffer->u.repair.rs );
1333 break;
1334 case PT_CONTROL :
1335 fprintf(debugfile, " %s: tic %8d, gameepisode %d, gamemap %d, data %i\n",
1336 control_name[netbuffer->u.control.command], DN_read_N32(&netbuffer->u.control.gametic),
1337 netbuffer->u.control.gameepisode, netbuffer->u.control.gamemap,
1338 DN_read_N16(&netbuffer->u.control.data) );
1339 if( netbuffer->u.control.player_num < MAXPLAYERS )
1340 fprintf(debugfile, " player %d player_state %d\n",
1341 netbuffer->u.control.player_num, netbuffer->u.control.player_state );
1342 break;
1343 case PT_FILEFRAGMENT :
1344 fprintf(debugfile, " fileid %d position %8lu datasize %d\n",
1345 netbuffer->u.filetxpak.fileid,
1346 (unsigned long)netbuffer->u.filetxpak.position,
1347 netbuffer->u.filetxpak.size );
1348 break;
1349 case PT_NETWAIT :
1350 fprintf(debugfile, " num_netplayer %d wait_netplayer %d wait_tics %d\n",
1351 netbuffer->u.netwait.num_netplayer, netbuffer->u.netwait.wait_netplayer, netbuffer->u.netwait.wait_tics );
1352 DF_PrintRand( &netbuffer->u.netwait.rs );
1353 break;
1354 case PT_SERVERPLAYER :
1355 {
1356 fprintf(debugfile, " gametic %8d serverplayer %d skill %d\n playerstate=",
1357 DN_read_N32( & netbuffer->u.playerstate.gametic ), netbuffer->u.playerstate.serverplayer, netbuffer->u.playerstate.skill );
1358 byte pn;
1359 for( pn=0; pn<MAXPLAYERS; pn++ )
1360 {
1361 byte npst = netbuffer->u.playerstate.playerstate[pn];
1362 if( (npst >=1) && (npst < 8) )
1363 fprintf(debugfile, " %s,", player_state_name[npst] );
1364 else
1365 fprintf(debugfile, " %i,", npst );
1366 }
1367 fprintf(debugfile, "\n" );
1368 }
1369 break;
1370 case PT_SERVERLEVEL :
1371 fprintf(debugfile, " gamestate %d episode %d map %d skill %d nomonsters %d deathmatch %d\n",
1372 netbuffer->u.levelcfg.gamestate, netbuffer->u.levelcfg.gameepisode, netbuffer->u.levelcfg.gamemap,
1373 netbuffer->u.levelcfg.skill, netbuffer->u.levelcfg.nomonsters, netbuffer->u.levelcfg.deathmatch );
1374 break;
1375 case PT_REQ_SERVERPLAYER :
1376 case PT_REQ_SERVERLEVEL :
1377 case PT_REQ_CLIENTCFG :
1378 case PT_SERVERSHUTDOWN :
1379 case PT_CLIENTQUIT :
1380 case PT_CLIENTREADY :
1381 break;
1382 case PT_REQUESTFILE :
1383 case PT_NODE_TIMEOUT :
1384 case PT_ACKS :
1385 default : // write as a raw packet
1386 fprintfstring(netbuffer->u.bytepak.b, (char *)netbuffer + doomcom->datalength - (char *)netbuffer->u.bytepak.b);
1387 break;
1388 }
1389 }
1390 #endif
1391
1392 // Generic print for network errors.
network_error_print(byte errcode,const char * who)1393 void network_error_print( byte errcode, const char * who )
1394 {
1395 const char * errtext = "unknown net error";
1396 switch( errcode )
1397 {
1398 case NE_fail: errtext = "network operation failed";
1399 break;
1400 case NE_refused_again: errtext = "operation refused, try again";
1401 break;
1402 case NE_network_reset: errtext = "network reset";
1403 break;
1404 case NE_network_unreachable: errtext = "network unreachable";
1405 break;
1406 case NE_node_unconnected: errtext = "network node unconnected";
1407 break;
1408 case NE_nodes_exhausted: errtext = "network nodes exhausted";
1409 break;
1410 case NE_not_netgame: errtext = "not netgame";
1411 break;
1412 case NE_fatal: errtext = "fatal network error";
1413 break;
1414 default:
1415 break;
1416 }
1417 GenPrintf(EMSG_warn, "Network: %s, %s\n", who, errtext );
1418 }
1419
1420 //#define PACKETQUEUE
1421 #ifdef PACKETQUEUE
1422
1423 // Over 128 is severe congestion, over 64 requires throttling.
1424 byte net_congestion = 0;
1425
1426 #define MAXQUEUENUM 128
1427 typedef struct packet_queue_s {
1428 struct packet_queue_s * link;
1429 byte to_node;
1430 byte flags;
1431 byte acknum;
1432 unsigned int packetlength ;
1433 byte data; // variable length netbuffer copy
1434 } packet_queue_t;
1435 byte packet_queue_num = 0;
1436 byte packet_queue_max = 0;
1437 packet_queue_t * packet_queue = NULL; // malloc
1438
calc_congestion(void)1439 void calc_congestion( void )
1440 {
1441 // start throttling at 1/4 full buffer.
1442 int c = (int)packet_queue_num * 64 / (MAXQUEUENUM/4);
1443 net_congestion = (c>255)? 255 : c; // limit to 255
1444 }
1445
1446 // Queue up the packet until it can be sent.
1447 // Makes HSendPacket calls much simpler.
1448 // Avoids clumbsy error handling when network has slowdown.
1449 // Rarely invoked, does not need to be fast.
1450 // Return NE_xx
NetQueue_put(byte to_node,byte flags,byte acknum,int packetlength)1451 byte NetQueue_put( byte to_node, byte flags, byte acknum, int packetlength )
1452 {
1453 packet_queue_t * pq;
1454 int netbuffer_length = packetlength + PACKET_BASE_SIZE;
1455
1456 if( packet_queue_num >= MAXQUEUENUM ) goto queue_full;
1457
1458 pq = malloc( sizeof(packet_queue_t) + netbuffer_length );
1459 if( pq == NULL ) goto queue_full;
1460
1461 if( packet_queue )
1462 {
1463 // Append to end of list.
1464 packet_queue_t * pq_end = packet_queue;
1465 while( pq_end->link ) pq_end = pq_end->link; // end of list
1466 pq_end->link = pq;
1467 }
1468 else
1469 {
1470 // end of list is the head
1471 packet_queue = pq;
1472 }
1473 pq->link = NULL;
1474 pq->to_node = to_node;
1475 pq->flags = flags;
1476 pq->acknum = acknum;
1477 pq->packetlength = packetlength;
1478 memcpy( &pq->data, netbuffer, netbuffer_length );
1479
1480 // stats and warnings
1481 packet_queue_num ++;
1482 if( packet_queue_num > packet_queue_max )
1483 {
1484 packet_queue_max = packet_queue_num;
1485 GenPrintf(EMSG_warn, "Packet Queue max %i\n", packet_queue_max );
1486 }
1487 calc_congestion();
1488 return NE_queued;
1489
1490 queue_full:
1491 return NE_queue_full;
1492 }
1493
1494 // Do not call when there is something in the netbuffer.
NetQueue_send(void)1495 byte NetQueue_send( void )
1496 {
1497 byte q_net_error = 0;
1498
1499 while( packet_queue )
1500 {
1501 packet_queue_t * pq = packet_queue;
1502 int netbuffer_length = pq->packetlength + PACKET_BASE_SIZE;
1503 memcpy( netbuffer, &pq->data, netbuffer_length );
1504 // Recursive call, so do not allow SP_queue.
1505 q_net_error = HSendPacket( pq->to_node, pq->flags & ~SP_queue, pq->acknum, pq->packetlength );
1506 if( q_net_error > 0 )
1507 return q_net_error;
1508
1509 // successfully sent, clear it from the queue
1510 packet_queue = pq->link; // unlink
1511 free( pq );
1512
1513 if( packet_queue_num > 0 )
1514 {
1515 packet_queue_num --;
1516 }
1517 calc_congestion();
1518 }
1519
1520 return NE_success;
1521 }
1522 #endif
1523
1524
1525 //
1526 // HSendPacket
1527 //
1528 // packetlength: number of bytes in u part of packet
1529 // acknum: retransmit of a packet with this acknum
1530 // flags: SP_ flags
1531 // Return network_error_e (NE_xx).
HSendPacket(byte to_node,byte flags,byte acknum,int packetlength)1532 byte HSendPacket(byte to_node, byte flags, byte acknum, int packetlength)
1533 {
1534 byte errcode;
1535
1536 #ifdef PACKETQUEUE
1537 // Check if anything is in queue already.
1538 if( (flags & SP_queue) && packet_queue_num ) goto queue_first;
1539 #endif
1540
1541 // PACKET_BASE_SIZE is not 0, so datalength cannot be 0.
1542 // #define PACKET_BASE_SIZE_ZERO
1543 doomcom->datalength = packetlength + PACKET_BASE_SIZE;
1544
1545 // Node 0 is always self.
1546 if(to_node == 0)
1547 {
1548 // Send packet to self.
1549 if((rebound_head+1)%MAXREBOUND==rebound_tail)
1550 {
1551 #ifdef PARANOIA
1552 CONS_Printf("Full rebound buf\n");
1553 #endif
1554 goto cannot_send;
1555 }
1556 memcpy(&reboundstore[rebound_head],netbuffer,doomcom->datalength);
1557 reboundsize[rebound_head]=doomcom->datalength;
1558 rebound_head=(rebound_head+1)%MAXREBOUND;
1559 #ifdef DEBUGFILE
1560 if (debugfile)
1561 {
1562 doomcom->remotenode = to_node;
1563 DebugPrintpacket("SENDLOCAL");
1564 }
1565 #endif
1566 return NE_success;
1567 }
1568
1569 // if (demoplayback)
1570 // return NE_success;
1571
1572 if (!netgame) goto not_netgame;
1573
1574 // Do this before Save_packet_acknum() because that function will
1575 // backup the current packet.
1576 doomcom->remotenode = to_node;
1577 #ifdef PACKET_BASE_SIZE_ZERO
1578 if(doomcom->datalength <= 0) goto empty_packet;
1579 #endif
1580
1581 #ifdef DOSNET_SUPPORT
1582 doomcom->numplayers = num_player_slot;
1583 #endif
1584
1585 // Include any pending return_ack, player nodes only.
1586 netbuffer->ack_return = (to_node<MAXNETNODES)?
1587 Get_return_ack(to_node) // ack a previous packet
1588 : 0; // broadcast, no ack
1589
1590 if( flags & SP_reliable )
1591 {
1592 // Packet sent with an ack_req, and retransmitted if necessary.
1593 if( I_NetCanSend && !I_NetCanSend() )
1594 {
1595 // Network cannot transmit right now.
1596 DEBFILE("HSendPacket : Out of bandwidth\n");
1597 // Enhancement for slow networks, not required.
1598 if( netbuffer->packettype < PT_CANFAIL )
1599 {
1600 // High priority, deferred transmit.
1601 netbuffer->ack_req = Save_packet_acknum(true);
1602 if( netbuffer->ack_req == 0 )
1603 goto cannot_send; // out of ack packets
1604 return NE_queued; // in ack
1605 }
1606 goto cannot_send;
1607 }
1608 // Save packet, issue an acknum.
1609 netbuffer->ack_req = Save_packet_acknum(false);
1610 if( netbuffer->ack_req == 0 )
1611 goto cannot_send; // out of ack packets
1612 }
1613 else
1614 {
1615 // Either acknum==0, or this is a retransmit using existing acknum.
1616 netbuffer->ack_req = acknum;
1617 }
1618
1619 netbuffer->checksum = Netbuffer_Checksum();
1620 stat_sendbytes += (net_packetheader_length + doomcom->datalength); // for stat
1621
1622 #if 0
1623 // DEBUG
1624 // simulate internet :)
1625 if( rand() > RAND_MAX/5 )
1626 {
1627 // Simulate a failure.
1628 #ifdef DEBUGFILE
1629 if (debugfile)
1630 DebugPrintpacket("SENDLOST");
1631 #endif
1632 return NE_success; // indicates sent, but gets lost
1633 }
1634 #ifdef DEBUGFILE
1635 if (debugfile)
1636 DebugPrintpacket("SEND");
1637 #endif
1638 #endif
1639
1640 errcode = I_NetSend();
1641 if( errcode >= NE_fail ) goto ret_errcode;
1642 return NE_success;
1643
1644 cannot_send:
1645 #ifdef PACKETQUEUE
1646 if( flags & SP_queue )
1647 {
1648 // Queue for later send.
1649 errcode = NetQueue_put( to_node, flags, acknum, packetlength );
1650 goto ret_errcode; // may be NE_queued, which does not print out
1651 }
1652 #endif
1653 goto ret_fail;
1654
1655 #ifdef PACKETQUEUE
1656 queue_first:
1657 // Queue this message first, to prevent reversing message order.
1658 errcode = NetQueue_put( to_node, flags, acknum, packetlength );
1659 if( errcode == NE_queue_full ) goto ret_errcode;
1660 // Send all queued messages. This calls HSendPacket.
1661 errcode = NetQueue_send();
1662 // Report errors on the state of the network.
1663 goto ret_errcode;
1664 #endif
1665
1666
1667 // Rare errors
1668 not_netgame:
1669 I_SoftError ("HSendPacket: not in netgame\n");
1670 errcode = NE_not_netgame;
1671 goto ret_errcode;
1672
1673 #ifdef PACKET_BASE_SIZE_ZERO
1674 empty_packet:
1675 DEBFILE("HSendPacket: abort send of empty packet\n");
1676 #ifdef DEBUGFILE
1677 if (debugfile)
1678 DebugPrintpacket("SENDEMPTY");
1679 #endif
1680 errcode = NE_empty_packet;
1681 goto ret_errcode;
1682 #endif
1683
1684 ret_fail:
1685 errcode = NE_fail;
1686 ret_errcode:
1687 // report some errcode, sometimes not an error
1688 if( (flags & SP_error_handler) && (errcode >= NE_fail) )
1689 network_error_print( errcode, "HSendPacket" );
1690
1691 return errcode;
1692 }
1693
1694 //
1695 // HGetPacket
1696 // Returns false if no packet is waiting
1697 // Check Datalength and checksum
1698 //
HGetPacket(void)1699 boolean HGetPacket (void)
1700 {
1701 if (rebound_tail!=rebound_head)
1702 {
1703 // Receive from self. Get a packet from my local net queue.
1704 memcpy(netbuffer,&reboundstore[rebound_tail],reboundsize[rebound_tail]);
1705 doomcom->datalength = reboundsize[rebound_tail];
1706 if( netbuffer->packettype == PT_NODE_TIMEOUT )
1707 doomcom->remotenode = netbuffer->u.bytepak.b[0]; // to node timeout
1708 else
1709 doomcom->remotenode = 0; // from self
1710
1711 rebound_tail=(rebound_tail+1)%MAXREBOUND;
1712 #ifdef DEBUGFILE
1713 if (debugfile)
1714 DebugPrintpacket("GETLOCAL");
1715 #endif
1716 return true;
1717 }
1718
1719 if (!netgame) goto fail_ret;
1720
1721 byte errcode = I_NetGet();
1722 if( errcode >= NE_fail )
1723 goto ret_errcode; // some other error
1724 if( errcode >= NE_empty )
1725 return false; // no packet
1726 if( doomcom->remotenode < 0 )
1727 return false; // no packet
1728
1729 stat_getbytes += (net_packetheader_length + doomcom->datalength); // for stat
1730
1731 if( doomcom->remotenode < MAXNETNODES )
1732 {
1733 // Player netnode
1734 net_nodes[doomcom->remotenode].lasttime_packet_received = I_GetTime();
1735 }
1736 else if (doomcom->remotenode >= MAX_CON_NETNODE) goto bad_node_num;
1737
1738 if (netbuffer->checksum != Netbuffer_Checksum()) goto bad_checksum;
1739
1740 #ifdef DEBUGFILE
1741 if (debugfile)
1742 DebugPrintpacket("GET");
1743 #endif
1744
1745 // Process the ack_num and ack_return fields.
1746 if(!Process_packet_ack()) goto fail_ret; // discated (duplicated)
1747
1748 // a packet with just ack_return
1749 if( netbuffer->packettype == PT_ACKS)
1750 {
1751 // Detect the special acks packet.
1752 Got_AcksPacket();
1753 return false;
1754 }
1755
1756 return true;
1757
1758 // Rare errors
1759 bad_node_num:
1760 DEBFILE(va("HGetPacket: receive packet from node %d !\n", doomcom->remotenode));
1761 goto fail_ret;
1762
1763 bad_checksum:
1764 DEBFILE("HGetPacket: Bad packet checksum\n");
1765 goto fail_ret;
1766
1767 ret_errcode:
1768 // report some errcode, sometimes not an error
1769 if( errcode >= NE_fail )
1770 network_error_print( errcode, "HSendPacket" );
1771 fail_ret:
1772 return false;
1773 }
1774
1775
1776 //
1777 // D_Startup_NetGame
1778 // Works out player numbers among the net participants
1779 //
1780 // Returns true when a network game is started by command line.
D_Startup_NetGame(void)1781 boolean D_Startup_NetGame(void)
1782 {
1783 boolean client;
1784 int num;
1785
1786 // Bring up low level functions.
1787 InitAck();
1788 rebound_tail=0;
1789 rebound_head=0;
1790
1791 stat_starttic = I_GetTime(); // start netstat interval
1792
1793 // Default
1794 I_NetGet = Internal_Get;
1795 I_NetSend = Internal_Send;
1796 I_NetCanSend = NULL;
1797 I_NetCloseSocket = NULL;
1798 I_NetFreeNode = Internal_FreeNode;
1799 I_NetMakeNode = NULL;
1800
1801 // The default mode is server.
1802 // Set to Client mode when connect to another server.
1803 server = true;
1804 netgame = false;
1805 multiplayer = false;
1806
1807 // Need dedicated and server determined, before most other Init.
1808 num = MAXNETNODES+9; // invalid, cv_wait_players already has default.
1809 // dedicated set by d_main.c
1810 dedicated = ( M_CheckParm("-dedicated") != 0 );
1811 if( dedicated )
1812 {
1813 server = true;
1814 netgame = true;
1815 num = 0; // dedicated number players
1816 // -server can set some other wait nodes value
1817 }
1818
1819 if ( M_CheckParm ("-server"))
1820 {
1821 server = true;
1822 netgame = true;
1823
1824 // If a number of clients (i.e. nodes) is specified, the server will
1825 // wait for the clients to connect before starting.
1826 // If no number is specified here, the server starts with 1 client,
1827 // others can join in-game.
1828 // A value of 0 allows join in-game, and wait_timeout game start,
1829 // with an unknown number of players.
1830 if( M_IsNextParm() )
1831 {
1832 // Number of players.
1833 num = atoi(M_GetNextParm());
1834 if( num < 0 )
1835 num = 0;
1836 if( num > MAXNETNODES )
1837 num = MAXNETNODES;
1838 }
1839 else
1840 num = 1;
1841 // Wait for player nodes during startup.
1842 }
1843
1844 if( num < MAXNETNODES+1 )
1845 {
1846 // It is possible to escape to menus, and direct setting only the
1847 // value interferes with menu setting of the value.
1848 CV_SetValue( &cv_wait_players, num );
1849 }
1850
1851 client = ( M_CheckParm ("-connect") != 0 );
1852 if( client )
1853 {
1854 if( netgame ) // from -dedicated or -server
1855 {
1856 I_SoftError( "Ignore -connect: conflict with -dedicated, -server.\n" );
1857 }
1858 else
1859 {
1860 // Command_connect is invoked by Init_TCP_Network.
1861 server = false;
1862 // Init_TCP_Network tests -connect, and tests netgame,
1863 // then issues connect command that sets netgame, and multiplayer.
1864 // netgame = true;
1865 }
1866 }
1867
1868 if( netgame )
1869 multiplayer = true;
1870
1871
1872 // I_InitNetwork sets port dependent settings in doomcom and netgame.
1873 // Check and initialize the network driver.
1874
1875 // [WDJ] Can simplify this and doomcom when drop support for DOS net.
1876 // Only dos version with external driver will return true.
1877 // It uses -net to select DOSNET (vrs TCP or IP). Does not set netgame.
1878 if( ! I_InitNetwork() ) // startup DOSNET
1879 {
1880 // InitNetwork did not init doomcom.
1881 // Init doomcom and netgame.
1882 doomcom=Z_Malloc(sizeof(doomcom_t),PU_STATIC,NULL);
1883 memset(doomcom,0,sizeof(doomcom_t));
1884 doomcom->id = DOOMCOM_ID;
1885 #ifdef DOSNET_SUPPORT
1886 doomcom->unused_deathmatch = 0; // unused
1887 doomcom->consoleplayer = 0;
1888 #endif
1889 doomcom->extratics = 0;
1890
1891 I_Init_TCP_Network();
1892 }
1893 #ifdef DOSNET_SUPPORT
1894 doomcom->num_player_netnodes = 0;
1895 doomcom->unused_ticdup = 1; // unused
1896 #endif
1897 netbuffer = (netbuffer_t *)&doomcom->data;
1898
1899 if (M_CheckParm ("-extratic"))
1900 {
1901 // extratic causes redundant transmission of tics, to prevent
1902 // retransmission of player movement
1903 // Combination of the vanilla -extratic and -dup
1904 num = 1; // default param on -extratic
1905 if( M_IsNextParm() )
1906 {
1907 num = atoi(M_GetNextParm());
1908 if( num < 0 )
1909 num = 0;
1910 if( num > 20 )
1911 num = 20; // reasonable
1912 }
1913 CONS_Printf("Set extratic to %d\n", num);
1914 doomcom->extratics = num;
1915 }
1916
1917 // Defaults
1918 hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
1919 net_bandwidth = 3000;
1920
1921 if(M_CheckParm ("-bandwidth"))
1922 {
1923 // set the expected network bandwith, in bytes per second
1924 // default is 3K
1925 if(M_IsNextParm())
1926 {
1927 net_bandwidth = atoi(M_GetNextParm());
1928 if( net_bandwidth<1000 )
1929 net_bandwidth=1000;
1930 if( net_bandwidth>100000 )
1931 hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
1932 CONS_Printf("Network bandwidth set to %d\n",net_bandwidth);
1933 }
1934 else
1935 I_Error("usage : -bandwidth <byte_per_sec>");
1936 }
1937
1938 software_MAXPACKETLENGTH=hardware_MAXPACKETLENGTH;
1939 if(M_CheckParm ("-packetsize"))
1940 {
1941 num = atoi(M_GetNextParm());
1942 if(num < 75)
1943 num = 75;
1944 if(num > hardware_MAXPACKETLENGTH)
1945 num = hardware_MAXPACKETLENGTH;
1946 software_MAXPACKETLENGTH = num;
1947 }
1948
1949 #ifdef PARANOIA
1950 if (doomcom->id != DOOMCOM_ID)
1951 I_Error ("Doomcom buffer invalid!");
1952 #endif
1953
1954 #ifdef DEBUGFILE
1955 if (M_CheckParm ("-debugfile"))
1956 {
1957 char filename[20];
1958 #ifdef DOSNET_SUPPORT
1959 int k=doomcom->consoleplayer-1;
1960 #else
1961 int k= consoleplayer - 1;
1962 #endif
1963 if( M_IsNextParm() )
1964 k = atoi(M_GetNextParm())-1;
1965
1966 while (!debugfile && k<MAXPLAYERS)
1967 {
1968 k++;
1969 sprintf (filename,"debug%i.txt",k);
1970 debugfile = fopen (filename,"w");
1971 }
1972 if( debugfile )
1973 CONS_Printf ("debug output to: %s\n",filename);
1974 else
1975 CONS_Printf ("\2cannot debug output to file !\n",filename);
1976 }
1977 #endif
1978
1979 // Bring up higher level functions.
1980 D_Init_ClientServer(); // inits numplayers=0
1981
1982 // Last because these need dedicated and server flags.
1983 SV_ResetServer();
1984 if(dedicated)
1985 SV_SpawnServer();
1986
1987 return netgame;
1988 }
1989
1990
1991 // Server or Client
D_CloseConnection(void)1992 extern void D_CloseConnection( void )
1993 {
1994 int i;
1995
1996 if( netgame )
1997 {
1998 // wait the ack_return with timeout of 5 Sec
1999 Net_Wait_AllAckReceived(5);
2000
2001 // close all connection
2002 for( i=0; i<MAX_CON_NETNODE; i++ )
2003 Net_CloseConnection(i, 1); // force close
2004
2005 InitAck();
2006
2007 if( I_NetCloseSocket )
2008 I_NetCloseSocket();
2009
2010 I_NetGet = Internal_Get;
2011 I_NetSend = Internal_Send;
2012 I_NetCanSend = NULL;
2013 I_NetCloseSocket = NULL;
2014 I_NetFreeNode = Internal_FreeNode;
2015 I_NetMakeNode = NULL;
2016
2017 netgame = false;
2018 }
2019 }
2020