void CNet::SendRawPacket(int conn, unsigned char* data, int length, int packetNum) { Connection* c=&connections[conn]; *(int*)&tempbuf[0]=packetNum; *(int*)&tempbuf[4]=c->lastInOrder; int hsize=9; if(!c->waitingPackets.empty() && c->waitingPackets.find(c->lastInOrder+1)==c->waitingPackets.end()) { tempbuf[8]=1; *(int*)&tempbuf[9]=c->waitingPackets.begin()->first-1; hsize=13; } else { tempbuf[8]=0; } memcpy(&tempbuf[hsize],data,length); // if(rand()&7) if(sendto(mySocket,(char*)tempbuf,length+hsize,0,(sockaddr*)&c->addr,sizeof(c->addr))==SOCKET_ERROR) { if (IsFakeError()) return; char test[100]; sprintf(test,"Error sending data. %d",WSAGetLastError()); handleerror(NULL,test,"SHUTDOWN ERROR", MBF_OK | MBF_INFO); exit(0); } }
void CRemoteConnection::SendRawPacket(const unsigned char* data, const unsigned length, const int packetNum) { if (!active) return; const unsigned hsize = 9; unsigned char tempbuf[NETWORK_BUFFER_SIZE]; *(int*)tempbuf = packetNum; *(int*)(tempbuf+4) = lastInOrder; if(!waitingPackets.empty() && waitingPackets.find(lastInOrder+1)==waitingPackets.end()){ int nak = (waitingPackets.begin()->first-1) - lastInOrder; assert(nak >= 0); if (nak <= 255) *(unsigned char*)(tempbuf+8) = (unsigned char)nak; else *(unsigned char*)(tempbuf+8) = 255; } else { *(unsigned char*)(tempbuf+8) = 0; } memcpy(&tempbuf[hsize],data,length); if(sendto(*mySocket,(char*)tempbuf,length+hsize,0,(sockaddr*)&addr,sizeof(addr))==SOCKET_ERROR){ if (IsFakeError()) return; throw network_error("Error sending data: "+GetErrorMsg()); } dataSent += length; sentOverhead += hsize; }
void UDPConnectedSocket::Send(const unsigned char* const buf, const unsigned dataLength) const { int error = send(mySocket, (char*)buf, dataLength, 0); if (error == SOCKET_ERROR && !IsFakeError()) { throw network_error(std::string("Error sending data to socket: ") + GetErrorMsg()); } }
unsigned UDPConnectedSocket::Recv(unsigned char* buf, const unsigned bufLength) const { const int data = recv(mySocket,(char*)buf,bufLength,0); if (data == SOCKET_ERROR) { if (IsFakeError()) { return 0; } else { throw network_error(std::string("Error receiving data from socket: ") + GetErrorMsg()); } } return (unsigned)data; }
void CNet::Update(void) { Uint64 t; t = SDL_GetTicks(); curTime=float(t)/1000.f; if(playbackDemo) ReadDemoFile(); if(onlyLocal) { return; } sockaddr_in from; socklen_t fromsize; fromsize=sizeof(from); int r; unsigned char inbuf[16000]; if(connected) while(true) { if((r=recvfrom(mySocket,(char*)inbuf,16000,0,(sockaddr*)&from,&fromsize))==SOCKET_ERROR) { if (IsFakeError()) break; char test[500]; sprintf(test,"Error receiving data. %i %d",(int)imServer,WSAGetLastError()); handleerror(NULL,test,"SHUTDOWN ERROR",MBF_OK | MBF_INFO); exit(0); } int conn=ResolveConnection(&from); if(conn==-1) { if(waitOnCon && r>=12 && (*(int*)inbuf)==0 && (*(int*)&inbuf[4])==-1 && inbuf[8]==0 && inbuf[9]==NETMSG_ATTEMPTCONNECT && inbuf[11]==NETWORK_VERSION) { conn=InitNewConn(&from,false,inbuf[10]); } else { continue; } } inInitialConnect=false; int packetNum=(*(int*)inbuf); ProcessRawPacket(inbuf,r,conn); } for(int a=0; a<gs->activePlayers; ++a) { Connection* c=&connections[a]; if(c->localConnection || !c->active) continue; std::map<int,Packet*>::iterator wpi; while((wpi=c->waitingPackets.find(c->lastInOrder+1))!=c->waitingPackets.end()) { //process all in order packets that we have waiting if(c->readyLength+wpi->second->length>=NETWORK_BUFFER_SIZE) { logOutput.Print("Overflow in incoming network buffer"); break; } memcpy(&c->readyData[c->readyLength],wpi->second->data,wpi->second->length); c->readyLength+=wpi->second->length; delete wpi->second; c->waitingPackets.erase(wpi); c->lastInOrder++; } if(inInitialConnect && c->lastSendTime<curTime-1) { //server hasnt responded so try to send the connection attempt again SendRawPacket(a,c->unackedPackets[0]->data,c->unackedPackets[0]->length,0); c->lastSendTime=curTime; } if(c->lastSendTime<curTime-5 && !inInitialConnect) { //we havent sent anything for a while so send something to prevent timeout SendData(NETMSG_HELLO); } if(c->lastSendTime<curTime-0.2f && !c->waitingPackets.empty()) { //we have at least one missing incomming packet lying around so send a packet to ensure the other side get a nak SendData(NETMSG_HELLO); } if(c->lastReceiveTime < curTime-(inInitialConnect ? 40 : 30)) { //other side has timed out c->active=false; } if(c->outgoingLength>0 && (c->lastSendTime < (curTime-0.2f+c->outgoingLength*0.01f) || c->lastSendFrame < gs->frameNum-1)) { FlushConnection(a); } } }