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