⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 d_net.c

📁 The source code of Doom legacy for windows
💻 C
📖 第 1 页 / 共 3 页
字号:
// Emacs style mode select   -*- C++ -*- //-----------------------------------------------------------------------------//// $Id: d_net.c,v 1.15 2001/02/10 12:27:13 bpereira Exp $//// Copyright (C) 1993-1996 by id Software, Inc.// Portions Copyright (C) 1998-2000 by DooM Legacy Team.//// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License// as published by the Free Software Foundation; either version 2// of the License, or (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.////// $Log: d_net.c,v $// Revision 1.15  2001/02/10 12:27:13  bpereira// no message//// Revision 1.14  2000/10/21 08:43:28  bpereira// no message//// Revision 1.13  2000/10/16 20:02:29  bpereira// no message//// Revision 1.12  2000/10/08 13:29:59  bpereira// no message//// Revision 1.11  2000/09/28 20:57:14  bpereira// no message//// Revision 1.10  2000/09/15 19:49:21  bpereira// no message//// Revision 1.9  2000/09/10 10:38:18  metzgermeister// *** empty log message ***//// Revision 1.8  2000/09/01 19:34:37  bpereira// no message//// Revision 1.7  2000/09/01 18:23:42  hurdler// fix some issues with latest network code changes//// Revision 1.6  2000/08/31 14:30:55  bpereira// no message//// Revision 1.5  2000/04/16 18:38:07  bpereira// no message//// Revision 1.4  2000/03/29 19:39:48  bpereira// no message//// Revision 1.3  2000/02/27 00:42:10  hurdler// fix CR+LF problem//// Revision 1.2  2000/02/26 00:28:42  hurdler// Mostly bug fix (see borislog.txt 23-2-2000, 24-2-2000)////// DESCRIPTION://      DOOM Network game communication and protocol,//      all OS independend parts.////      Implemente a Sliding window protocol without receiver window//      (out of order reception)//      This protocol use mix of "goback n" and "selective repeat" implementation//      The NOTHING packet is send when connection is idle for acknowledge packets////-----------------------------------------------------------------------------#include "doomdef.h"#include "g_game.h"#include "i_net.h"#include "i_system.h"#include "m_argv.h"#include "d_net.h"#include "w_wad.h"#include "d_netfil.h"#include "d_clisrv.h"#include "z_zone.h"#include "i_tcp.h"//// NETWORKING//// gametic is the tic about to (or currently being) run// server://   maketic is the tic that hasn't had control made for it yet//   nettics : is the tic for eatch node//   firsttictosend : is the lowest value of nettics// client://   neededtic : is the tic needed by the client for run the game//   firsttictosend : is used to optimize a condition// normaly maketic>=gametic>0,#define FORCECLOSE         0x8000#define CONNECTIONTIMEOUT  (15*TICRATE)doomcom_t*  doomcom;doomdata_t* netbuffer;        // points inside doomcomFILE*       debugfile=NULL;        // put some net info in a file                              // during the game#define     MAXREBOUND 8static doomdata_t  reboundstore[MAXREBOUND];static short       reboundsize[MAXREBOUND];static int         rebound_head,rebound_tail;int         net_bandwidth;short       hardware_MAXPACKETLENGTH;void    (*I_NetGet) (void);void    (*I_NetSend) (void);boolean (*I_NetCanSend) (void);void    (*I_NetCloseSocket) (void);void    (*I_NetFreeNodenum) (int nodenum);int     (*I_NetMakeNode) (char *address);boolean (*I_NetOpenSocket) (void);// network statstic_t       statstarttic;int         getbytes=0;INT64       sendbytes=0;int         retransmit=0   ,duppacket=0;int         sendackpacket=0,getackpacket=0;int         ticruned=0     ,ticmiss=0;// globalsint    getbps,sendbps;float  lostpercent,duppercent,gamelostpercent;int    packetheaderlength;boolean Net_GetNetStat(void){    tic_t t=I_GetTime();static int oldsendbyte=0;    if( statstarttic+STATLENGTH<=t )    {        getbps=(getbytes*TICRATE)/(t-statstarttic);        sendbps=((sendbytes-oldsendbyte)*TICRATE)/(t-statstarttic);        if(sendackpacket)            lostpercent=100.0*(float)retransmit/(float)sendackpacket;        else            lostpercent=0;        if(getackpacket)            duppercent=100.0*(float)duppacket/(float)getackpacket;        else            duppercent=0;        if( ticruned )            gamelostpercent=100.0*(float)ticmiss/(float)ticruned;        else            gamelostpercent=0;        ticmiss=ticruned=0;        oldsendbyte=sendbytes;        getbytes=0;        sendackpacket=getackpacket=duppacket=retransmit=0;        statstarttic=t;        return 1;    }    return 0;}// -----------------------------------------------------------------//  Some stuct and function for acknowledgment of packets// -----------------------------------------------------------------#define MAXACKPACKETS    64 // minimum number of nodes#define MAXACKTOSEND     64#define URGENTFREESLOTENUM   6#define ACKTOSENDTIMEOUT  (TICRATE/17)typedef struct {  byte   acknum;  byte   nextacknum;  byte   destinationnode;  tic_t  senttime;  USHORT length;  USHORT resentnum;   char   pak[MAXPACKETLENGTH];} ackpak_t;typedef enum {    CLOSE  = 1,    // flag is set when connection is closing} node_flags_t;// table of packet that was not acknowleged can be resend (the sender window)static ackpak_t ackpak[MAXACKPACKETS];typedef struct {    // ack return to send (like slinding window protocol)    byte  firstacktosend;    // when no consecutive packet are received we keep in mind what packet     // we already received in a queu     byte  acktosend_head;    byte  acktosend_tail;    byte  acktosend[MAXACKTOSEND];    // automaticaly send keep alive packet when not enought trafic    tic_t lasttimeacktosend_sent;    // detect connection lost    tic_t lasttimepacketreceived;        // flow control : do not sent to mush packet with ack     byte  remotefirstack;    byte  nextacknum;        byte   flags;// jacobson tcp timeout evaluation algorithm (Karn variation)    fixed_t ping;    fixed_t varping;    int     timeout;   // computed with ping and varping} node_t;static node_t nodes[MAXNETNODES];#define  PINGDEFAULT     ((200*TICRATE*FRACUNIT)/1000)#define  VARPINGDEFAULT  ( (50*TICRATE*FRACUNIT)/1000)#define  TIMEOUT(p,v)    (p+4*v+FRACUNIT/2)>>FRACBITS;// return <0 if a<b (mod 256)//         0 if a=n (mod 256)//        >0 if a>b (mod 256)// mnemonic: to use it compare to 0 : cmpack(a,b)<0 is "a<b" ...static int cmpack(byte a,byte b){    register int d=a-b;    if(d>=127 || d<-128)        return -d;    return d;}// return a free acknum and copy netbuffer in the ackpak tablestatic boolean GetFreeAcknum(byte *freeack, boolean lowtimer){   node_t *node=&nodes[doomcom->remotenode];   int i,numfreeslote=0;   if(cmpack((node->remotefirstack+MAXACKTOSEND) % 256,node->nextacknum)<0)   {       DEBFILE(va("too fast %d %d\n",node->remotefirstack,node->nextacknum));       return false;   }   for(i=0;i<MAXACKPACKETS;i++)       if(ackpak[i].acknum==0)       {           // for low priority packet, make sure let freeslotes so urgents packets can be sent           numfreeslote++;           if( netbuffer->packettype >= PT_CANFAIL && numfreeslote<URGENTFREESLOTENUM)               continue;           ackpak[i].acknum=node->nextacknum;           ackpak[i].nextacknum=node->nextacknum;           node->nextacknum++;           if( node->nextacknum==0 )               node->nextacknum++;           ackpak[i].destinationnode=node-nodes;           ackpak[i].length=doomcom->datalength;           if(lowtimer)           {               // lowtime mean can't be sent now so try it soon as possible               ackpak[i].senttime=0;               ackpak[i].resentnum = 1;           }           else           {               ackpak[i].senttime=I_GetTime();               ackpak[i].resentnum = 0;           }           memcpy(ackpak[i].pak,netbuffer,ackpak[i].length);                      *freeack=ackpak[i].acknum;                      sendackpacket++; // for stat                      return true;       }#ifdef PARANOIA   if( devparm )       CONS_Printf("No more free ackpacket\n");#endif   if( netbuffer->packettype < PT_CANFAIL )       I_Error("Connection lost\n");   return false;}// Get a ack to send in the queu of this nodestatic byte GetAcktosend(int node){    nodes[node].lasttimeacktosend_sent = I_GetTime();    return nodes[node].firstacktosend;}static void Removeack(int i){    int node=ackpak[i].destinationnode;    fixed_t trueping=(I_GetTime()-ackpak[i].senttime)<<FRACBITS;    if( ackpak[i].resentnum )    {        // +FRACUNIT/2 for round        nodes[node].ping = (nodes[node].ping*7 + trueping)/8;        nodes[node].varping = (nodes[node].varping*7 + abs(nodes[node].ping-trueping))/8;        nodes[node].timeout = TIMEOUT(nodes[node].ping,nodes[node].varping);    }    DEBFILE(va("Remove ack %d trueping %d ping %f var %f timeout %d\n",ackpak[i].acknum,trueping>>FRACBITS,FIXED_TO_FLOAT(nodes[node].ping),FIXED_TO_FLOAT(nodes[node].varping),nodes[node].timeout));    ackpak[i].acknum=0;    if( nodes[node].flags & CLOSE )        Net_CloseConnection( node );}// we have got a packet proceed the ack request and ack returnstatic boolean inline Processackpak(){   int i;   boolean goodpacket=true;   node_t *node=&nodes[doomcom->remotenode];// received a ack return remove the ack in the list   if(netbuffer->ackreturn && cmpack(node->remotefirstack,netbuffer->ackreturn)<0)   {       node->remotefirstack=netbuffer->ackreturn;       // search the ackbuffer and free it       for(i=0;i<MAXACKPACKETS;i++)           if( ackpak[i].acknum &&               ackpak[i].destinationnode==node-nodes &&               cmpack(ackpak[i].acknum,netbuffer->ackreturn)<=0 )               Removeack(i);   }// received a packet with ack put it in to queue for send the ack back   if( netbuffer->ack )   {       byte ack=netbuffer->ack;       getackpacket++;       if( cmpack(ack,node->firstacktosend)<=0 )       {           DEBFILE(va("Discard(1) ack %d (duplicated)\n",ack));           duppacket++;           goodpacket=false; // discard packet (duplicat)       }       else       {           // check if it is not allready in the queue           for(i =node->acktosend_tail;               i!=node->acktosend_head;               i =(i+1)%MAXACKTOSEND    )               if(node->acktosend[i]==ack)               {                   DEBFILE(va("Discard(2) ack %d (duplicated)\n",ack));                   duppacket++;                   goodpacket=false; // discard packet (duplicat)                   break;               }           if( goodpacket )           {               // is a good packet so increment the acknoledge number,then search a "hole" in the queue               byte nextfirstack=node->firstacktosend+1;               if(nextfirstack==0) nextfirstack=1;               if(ack==nextfirstack)               {                    byte hm1; // head-1                   boolean change=true;                   node->firstacktosend=nextfirstack++;                   if(nextfirstack==0) nextfirstack=1;                   hm1=(node->acktosend_head-1+MAXACKTOSEND)%MAXACKTOSEND;                   while(change)                   {                       change=false;                       for( i=node->acktosend_tail;i!=node->acktosend_head;i=(i+1)%MAXACKTOSEND)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -