📄 d_net.c
字号:
if( cmpack(node->acktosend[i],nextfirstack)<=0 ) { if( node->acktosend[i]==nextfirstack ) { node->firstacktosend=nextfirstack++; if(nextfirstack==0) nextfirstack=1; change=true; } if( i==node->acktosend_tail ) { node->acktosend[node->acktosend_tail] = 0; node->acktosend_tail = (i+1)%MAXACKTOSEND; } else if( i==hm1 ) { node->acktosend[hm1] = 0; node->acktosend_head = hm1; hm1=(hm1-1+MAXACKTOSEND)%MAXACKTOSEND; } } } } else { // out of order packet // don't increment firsacktosend, put it in asktosend queue // will be incremented when the nextfirstack come (code above) byte newhead=(node->acktosend_head+1)%MAXACKTOSEND; DEBFILE(va("out of order packet (%d expected)\n",nextfirstack)); if(newhead != node->acktosend_tail) { node->acktosend[node->acktosend_head]=ack; node->acktosend_head = newhead; } else // buffer full discard packet, sender will resend it // remark that we can admit the packet but we will not detect the duplication after :( { DEBFILE("no more freeackret\n"); goodpacket=false; } } } } } return goodpacket;}// send special packet with only ack on itextern void Net_SendAcks(int node){ netbuffer->packettype = PT_NOTHING; memcpy(netbuffer->u.textcmd,nodes[node].acktosend,MAXACKTOSEND); HSendPacket(node,false,0,MAXACKTOSEND);}static void GotAcks(void){ int i,j; for(j=0;j<MAXACKTOSEND;j++) if( netbuffer->u.textcmd[j] ) for(i=0;i<MAXACKPACKETS;i++) if( ackpak[i].acknum && ackpak[i].destinationnode==doomcom->remotenode) { if( ackpak[i].acknum==netbuffer->u.textcmd[j]) Removeack(i); else // nextacknum is first equal to acknum, then when receiving bigger ack // there is big chance the packet is lost // when resent, nextacknum=nodes[node].nextacknum this will redo the same but with differant value if( cmpack(ackpak[i].nextacknum,netbuffer->u.textcmd[j])<=0 && ackpak[i].senttime>0) ackpak[i].senttime--; // hurry up }}void Net_ConnectionTimeout( int node ){ // send a very special packet to self (hack the reboundstore queu) // main code will handle it reboundstore[rebound_head].packettype = PT_NODETIMEOUT; reboundstore[rebound_head].ack = 0; reboundstore[rebound_head].ackreturn = 0; reboundstore[rebound_head].u.textcmd[0] = node; reboundsize[rebound_head]=BASEPACKETSIZE+1; rebound_head=(rebound_head+1)%MAXREBOUND; // do not redo it quickly (if we do not close connection is for a good reason !) nodes[node].lasttimepacketreceived = I_GetTime();}// resend the data if neededextern void Net_AckTicker(void){ int i; for(i=0;i<MAXACKPACKETS;i++) { node_t *node=&nodes[ackpak[i].destinationnode]; if(ackpak[i].acknum) if(ackpak[i].senttime+node->timeout<I_GetTime()) { if( ackpak[i].resentnum > 10 && (node->flags & CLOSE) ) { DEBFILE(va("ack %d sent 20 time so connection is supposed lost : node %d\n",i,node-nodes)); Net_CloseConnection( (node-nodes) | FORCECLOSE); ackpak[i].acknum = 0; continue; } DEBFILE(va("Resend ack %d, %d<%d\n",ackpak[i].acknum, ackpak[i].senttime, node->timeout, I_GetTime())); memcpy(netbuffer,ackpak[i].pak,ackpak[i].length); ackpak[i].senttime=I_GetTime(); ackpak[i].resentnum++; ackpak[i].nextacknum=node->nextacknum; retransmit++; // for stat HSendPacket(node-nodes,false,ackpak[i].acknum,ackpak[i].length-BASEPACKETSIZE); } } for(i=1;i<MAXNETNODES;i++) { // this is something like node open flag if( nodes[i].firstacktosend ) { // we haven't sent a packet since long time acknoledge packet if needed if( nodes[i].lasttimeacktosend_sent + ACKTOSENDTIMEOUT < I_GetTime() ) Net_SendAcks(i); if( (nodes[i].flags & CLOSE) == 0 && nodes[i].lasttimepacketreceived + CONNECTIONTIMEOUT < I_GetTime() ) Net_ConnectionTimeout( i ); } }}// remove last packet received ack before the resend the ackret// (the higer layer don't have room, or something else ....)extern void Net_UnAcknowledgPacket(int node){ int hm1=(nodes[node].acktosend_head-1+MAXACKTOSEND)%MAXACKTOSEND; DEBFILE(va("UnAcknowledg node %d\n",node)); if(!node) return; if( nodes[node].acktosend[hm1] == netbuffer->ack ) { nodes[node].acktosend[hm1] = 0; nodes[node].acktosend_head = hm1; } else if( nodes[node].firstacktosend == netbuffer->ack ) { nodes[node].firstacktosend--; if( nodes[node].firstacktosend==0 ) nodes[node].firstacktosend--; } else { while (nodes[node].firstacktosend!=netbuffer->ack) { nodes[node].acktosend_tail = (nodes[node].acktosend_tail-1+MAXACKTOSEND)%MAXACKTOSEND; nodes[node].acktosend[nodes[node].acktosend_tail]=nodes[node].firstacktosend; nodes[node].firstacktosend--; if( nodes[node].firstacktosend==0 ) nodes[node].firstacktosend--; } nodes[node].firstacktosend++; if( nodes[node].firstacktosend==0 ) nodes[node].firstacktosend++; }// I_Error("can't Removing ackret\n");}extern boolean Net_AllAckReceived(void){ int i; for(i=0;i<MAXACKPACKETS;i++) if(ackpak[i].acknum) return false; return true;}// wait the all ackreturn with timout in secondextern void Net_WaitAllAckReceived( ULONG timeout ){ tic_t tictac=I_GetTime(); timeout=tictac+timeout*TICRATE; HGetPacket(); while(timeout>I_GetTime() && !Net_AllAckReceived()) { while(tictac==I_GetTime()) ; tictac=I_GetTime(); HGetPacket(); Net_AckTicker(); }}static void InitNode( int node ){ nodes[node].acktosend_head = 0; nodes[node].acktosend_tail = 0; nodes[node].ping = PINGDEFAULT; nodes[node].varping = VARPINGDEFAULT; nodes[node].timeout = TIMEOUT(nodes[node].ping,nodes[node].varping); nodes[node].firstacktosend = 0; nodes[node].nextacknum = 1; nodes[node].remotefirstack = 0; nodes[node].flags = 0;}static void InitAck(){ int i; for(i=0;i<MAXACKPACKETS;i++) ackpak[i].acknum=0; for(i=0;i<MAXNETNODES;i++) InitNode( i );}extern void Net_AbortPacketType(char packettype){ int i; for( i=0;i<MAXACKPACKETS;i++ ) if( ackpak[i].acknum && (((doomdata_t *)ackpak[i].pak)->packettype==packettype || packettype==-1 )) ackpak[i].acknum=0;}// -----------------------------------------------------------------// end of acknowledge function// -----------------------------------------------------------------// remove a node, clear all ack from this node and reset askretextern void Net_CloseConnection(int node){ int i; boolean forceclose = (node & FORCECLOSE)!=0; node &= ~FORCECLOSE; if( !node ) return; nodes[node].flags |= CLOSE; // try to Send ack back (two army problem) if( GetAcktosend(node) ) { Net_SendAcks( node ); Net_SendAcks( node ); } // check if we wait ack from this node for(i=0;i<MAXACKPACKETS;i++) if( ackpak[i].acknum && ackpak[i].destinationnode==node) { if( !forceclose ) return; // connection will be closed when ack is returned else ackpak[i].acknum = 0; } InitNode(node); AbortSendFiles(node); I_NetFreeNodenum(node);}//// Checksum//static unsigned NetbufferChecksum (void){ unsigned c; int i,l; unsigned char *buf; c = 0x1234567; l = doomcom->datalength - 4; buf = (unsigned char*)netbuffer+4; for (i=0 ; i<l ; i++,buf++) c += (*buf) * (i+1); return c;}#ifdef DEBUGFILEstatic void fprintfstring(char *s,byte len){ int i; int mode=0; for (i=0 ; i<len ; i++) if(s[i]<32) if(mode==0) { fprintf (debugfile,"[%d",(byte)s[i]); mode = 1; } else fprintf (debugfile,",%d",(byte)s[i]); else { if(mode==1) { fprintf (debugfile,"]"); mode=0; } fprintf (debugfile,"%c",s[i]); } if(mode==1) fprintf (debugfile,"]"); fprintf(debugfile,"\n");}static char *packettypename[NUMPACKETTYPE]={ "NOTHING", "SERVERCFG", "CLIENTCMD", "CLIENTMIS", "CLIENT2CMD", "CLIENT2MIS", "NODEKEEPALIVE", "NODEKEEPALIVEMIS", "SERVERTICS", "SERVERREFUSE", "SERVERSHUTDOWN", "CLIENTQUIT", "ASKINFO", "SERVERINFO", "REQUESTFILE", "FILEFRAGMENT", "TEXTCMD", "TEXTCMD2", "CLIENTJOIN", "NODETIMEOUT",};static void DebugPrintpacket(char *header){ fprintf (debugfile,"%-12s (node %d,ack %d,ackret %d,size %d) type(%d) : %s\n" ,header ,doomcom->remotenode ,netbuffer->ack ,netbuffer->ackreturn ,doomcom->datalength ,netbuffer->packettype,packettypename[netbuffer->packettype]); switch(netbuffer->packettype) { case PT_ASKINFO: fprintf(debugfile ," time %u\n" ,(unsigned int)netbuffer->u.askinfo.time); break; case PT_CLIENTJOIN: fprintf(debugfile ," number %d mode %d\n" ,netbuffer->u.clientcfg.localplayers ,netbuffer->u.clientcfg.mode); break; case PT_SERVERTICS: fprintf(debugfile ," firsttic %d ply %d tics %d ntxtcmd %d\n " ,ExpandTics (netbuffer->u.serverpak.starttic) ,netbuffer->u.serverpak.numplayers ,netbuffer->u.serverpak.numtics ,(int)(&((char *)netbuffer)[doomcom->datalength] - (char *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numplayers*netbuffer->u.serverpak.numtics])); fprintfstring( (char *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numplayers*netbuffer->u.serverpak.numtics] ,&((char *)netbuffer)[doomcom->datalength] - (char *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numplayers*netbuffer->u.serverpak.numtics]); break; case PT_CLIENTCMD:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -