/********************************************************* 函数名称:AddFriend 功能描述:添加好友 参数说明:msg-消息结构体 pSocket-接收到消息的pSocket 返 回 值: 备 注: *********************************************************/ int CSocketServerDlg::AddFriend(struct MSG_TRANSPOND * msg_addfrd, CChatSocket * pSocket) { struct MSG_SYS *msg_sys = new struct MSG_SYS; msg_sys->nType = IDS_SYSTEM_MESSAGE; if(msg_addfrd->nReturn == ADD_FRIEND_AGREE) {// 同意好友申请 int nRes; nRes = m_data.MakeFriend(msg_addfrd->FromID, msg_addfrd->ToID); if(nRes == TRUE) {// 添加成功 msg_sys->nIDPrompt = IDS_ADD_FRIEND_SUCCESS; } else if(nRes == IDS_ERR_FRIEND_ADD_SELF) {// 不能添加自己为好友 msg_sys->nIDPrompt = IDS_ERR_FRIEND_ADD_SELF; } else if(nRes == IDS_ERR_FRIEND_HAD_EXIST) {// 好友已经存在 msg_sys->nIDPrompt = IDS_ERR_FRIEND_HAD_EXIST; } // 分别向双方发送消息 strcpy_s(msg_sys->nID, pSocket->m_userID); pSocket->Send(msg_sys, sizeof(*msg_sys)); strcpy_s(msg_sys->nID, msg_addfrd->FromID); SendSystemMsg(msg_sys); // 在这个函数里面会将msg_sys释放 } else { msg_sys->nIDPrompt = IDS_ADD_FRIEND_REFUSE; strcpy_s(msg_sys->nID, msg_addfrd->FromID); SendSystemMsg(msg_sys); // 在这个函数里面会将msg_sys释放 } return TRUE; }
BOOL CLibInfoCharSvr::UseSkill(CInfoCharSvr *pInfoChar, DWORD dwSkillID) { BOOL bRet, bResult; PCInfoSkillBase pInfoSkill; CPacketCHAR_STATUS PacketCHAR_STATUS; bRet = FALSE; if (pInfoChar == NULL) { goto Exit; } bResult = pInfoChar->HaveSkill (dwSkillID); if (bResult == FALSE) { goto Exit; } pInfoSkill = (PCInfoSkillBase)m_pLibInfoSkill->GetPtr (dwSkillID); if (pInfoSkill == NULL) { goto Exit; } if (pInfoChar->m_dwSP < pInfoSkill->m_dwSP) { SendSystemMsg (pInfoChar->m_dwSessionID, "SPが足りません", SYSTEMMSGTYPE_NOLOG); goto Exit; } switch (pInfoSkill->m_nTypeMain) { case SKILLTYPEMAIN_NONE: /* 能力 */ break; case SKILLTYPEMAIN_BATTLE: /* 戦闘 */ switch (pInfoSkill->m_nTypeSub) { case SKILLTYPESUB_BATTLE_MOVEATACK: /* 移動して攻撃 */ bRet = UseSkillBATTLE_MOVEATACK (pInfoChar, pInfoSkill); break; case SKILLTYPESUB_BATTLE_HEAL: /* 回復 */ bRet = UseSkillNONE_HEAL (pInfoChar, pInfoSkill); break; } break; case SKILLTYPEMAIN_LIFE: /* 生活 */ switch (pInfoSkill->m_nTypeSub) { case SKILLTYPESUB_LIFE_FISHING: /* 釣り */ bRet = UseSkillFISHING (pInfoChar, pInfoSkill); break; } break; } if (bRet) { pInfoChar->m_dwSP -= pInfoSkill->m_dwSP; PacketCHAR_STATUS.Make (pInfoChar); m_pMainFrame->SendToClient (pInfoChar->m_dwSessionID, &PacketCHAR_STATUS); } Exit: return bRet; }
bool CGameServer::Update() { if(lastSyncRequest<gu->gameTime-2){ lastSyncRequest=gu->gameTime; if (game && game->playing) { //check if last times sync responses is correct if (outstandingSyncFrame > 0) { // I've disabled majority voting for now. // Should be tested in a few big multiplayer games first. #if 0 std::map<CChecksum, int> freq; // maps checksums to their frequency for(int a = 0; a < gs->activePlayers; ++a) if(gs->players[a]->active) { //if the checksum really happens to be 0 we will get lots of falls positives here if(!syncResponses[a]) { if (!serverNet->playbackDemo) logOutput.Print("No response from %s", gs->players[a]->playerName.c_str()); } else ++freq[syncResponses[a]]; } if (freq.size() != 1) { CChecksum correctSync; int highestFreq = 0; for (std::map<CChecksum, int>::const_iterator it = freq.begin(); it != freq.end(); ++it) if (it->second > highestFreq) { correctSync = it->first; highestFreq = it->second; } if (correctSync) for (int a = 0; a < gs->activePlayers; ++a) if (gs->players[a]->active && syncResponses[a] && correctSync != syncResponses[a]) { char buf[10]; SendSystemMsg("Sync error for %s %i %s", gs->players[a]->playerName.c_str(), outstandingSyncFrame, correctSync.diff(buf, syncResponses[a])); } } #else CChecksum correctSync; bool err = false; for(int a = 0; a < gs->activePlayers; ++a) if(gs->players[a]->active) { //if the checksum really happens to be 0 we will get lots of falls positives here if(!syncResponses[a] && !serverNet->playbackDemo) { logOutput.Print("No response from %s", gs->players[a]->playerName.c_str()); continue; } if (correctSync && correctSync != syncResponses[a]) { char buf[10]; SendSystemMsg("Sync error for %s %i %s", gs->players[a]->playerName.c_str(), outstandingSyncFrame, correctSync.diff(buf, syncResponses[a])); err = true; continue; } //this assumes the lowest num player is the correct one, should maybe some sort of majority voting instead correctSync = syncResponses[a]; } #endif #ifdef SYNCDEBUG if (err || fakeDesync) { CSyncDebugger::GetInstance()->ServerTriggerSyncErrorHandling(serverframenum); fakeDesync = false; } #else // SYNCDEBUG if (err && gu->autoQuit) serverNet->SendData(NETMSG_QUIT); #endif // !SYNCDEBUG } for(int a=0;a<gs->activePlayers;++a) syncResponses[a]=0; if(!serverNet->playbackDemo){ //send sync request serverNet->SendData<int>(NETMSG_SYNCREQUEST, serverframenum); outstandingSyncFrame=serverframenum; } int firstReal=0; if(gameSetup) firstReal=gameSetup->numDemoPlayers; //send info about the players for(int a=firstReal;a<gs->activePlayers;++a){ if(gs->players[a]->active){ serverNet->SendData<unsigned char, float, int>( NETMSG_PLAYERINFO, a, gs->players[a]->cpuUsage, gs->players[a]->ping); } } //decide new internal speed float maxCpu=0; for(int a=0;a<gs->activePlayers;++a){ if(gs->players[a]->cpuUsage>maxCpu && gs->players[a]->active){ maxCpu=gs->players[a]->cpuUsage; } } if (maxCpu != 0) { float wantedCpu=0.35f+(1-gs->speedFactor/gs->userSpeedFactor)*0.5f; //float speedMod=1+wantedCpu-maxCpu; float newSpeed=gs->speedFactor*wantedCpu/maxCpu; //logOutput.Print("Speed %f %f %f %f",maxCpu,wantedCpu,speedMod,newSpeed); newSpeed=(newSpeed+gs->speedFactor)*0.5f; if(newSpeed>gs->userSpeedFactor) newSpeed=gs->userSpeedFactor; if(newSpeed<0.1f) newSpeed=0.1f; if(newSpeed!=gs->speedFactor) serverNet->SendData<float>(NETMSG_INTERNAL_SPEED, newSpeed); } } } if(!ServerReadNet()){ logOutput.Print("Server read net wanted quit"); return false; } if (game && game->playing && !serverNet->playbackDemo){ Uint64 currentFrame; currentFrame = SDL_GetTicks(); float timeElapsed=((float)(currentFrame - lastframe))/1000.f; if(gameEndDetected) gameEndTime+=timeElapsed; // logOutput.Print("float value is %f",timeElapsed); if(gameClientUpdated){ gameClientUpdated=false; maxTimeLeft=2; } if(timeElapsed>maxTimeLeft) timeElapsed=maxTimeLeft; maxTimeLeft-=timeElapsed; timeLeft+=GAME_SPEED*gs->speedFactor*timeElapsed; lastframe=currentFrame; while((timeLeft>0) && (!gs->paused || game->bOneStep)){ if(!game->creatingVideo){ game->bOneStep=false; CreateNewFrame(true); } timeLeft--; } } serverNet->Update(); CheckForGameEnd(); return true; }
bool CGameServer::ServerReadNet() { static int lastMsg[MAX_PLAYERS],thisMsg=0; for(int a=0;a<gs->activePlayers;a++){ int inbufpos=0; int inbuflength=0; if(gs->players[a]->active && (!gameSetup || a>=gameSetup->numDemoPlayers)){ if((inbuflength=serverNet->GetData(inbuf,NETWORK_BUFFER_SIZE,a))==-1){ PUSH_CODE_MODE; //this could lead to some nasty errors if the other thread switches code mode... ENTER_MIXED; gs->players[a]->active=false; POP_CODE_MODE; inbuflength=0; serverNet->SendData<unsigned char, unsigned char>(NETMSG_PLAYERLEFT, a, 0); } } // logOutput << serverNet->numConnected << "\n"; while(inbufpos<inbuflength){ thisMsg=inbuf[inbufpos]; int lastLength=0; switch (inbuf[inbufpos]){ case NETMSG_ATTEMPTCONNECT: //handled directly in CNet lastLength=3; break; case NETMSG_HELLO: lastLength=1; break; case NETMSG_RANDSEED: lastLength=5; serverNet->SendData(&inbuf[inbufpos],5); //forward data break; case NETMSG_NEWFRAME: gs->players[a]->ping=serverframenum-*(int*)&inbuf[inbufpos+1]; lastLength=5; break; case NETMSG_PAUSE: if(inbuf[inbufpos+2]!=a){ logOutput.Print("Server: Warning got pause msg from %i claiming to be from %i",a,inbuf[inbufpos+2]); } else { assert(game); if(game->gamePausable || a==0){ timeLeft=0; serverNet->SendData(&inbuf[inbufpos],3); } } lastLength=3; break; case NETMSG_INTERNAL_SPEED: logOutput.Print("Server shouldnt get internal speed msgs?"); lastLength=5; break; case NETMSG_USER_SPEED: { float speed=*((float*)&inbuf[inbufpos+1]); assert(game); if(speed>game->maxUserSpeed) speed=game->maxUserSpeed; if(speed<game->minUserSpeed) speed=game->minUserSpeed; if(gs->userSpeedFactor!=speed){ if(gs->speedFactor==gs->userSpeedFactor || gs->speedFactor>speed) serverNet->SendData<float>(NETMSG_INTERNAL_SPEED, speed); serverNet->SendData(&inbuf[inbufpos],5); //forward data } lastLength=5; break;} case NETMSG_CPU_USAGE: ENTER_MIXED; gs->players[a]->cpuUsage=*((float*)&inbuf[inbufpos+1]); ENTER_UNSYNCED; lastLength=5; break; case NETMSG_EXECHECKSUM: if(exeChecksum!=*((unsigned int*)&inbuf[inbufpos+1])){ SendSystemMsg("Wrong exe checksum from %i got %X instead of %X",a,*((unsigned int*)&inbuf[inbufpos+1]),exeChecksum); } lastLength=5; break; case NETMSG_QUIT: ENTER_MIXED; gs->players[a]->active=false; ENTER_UNSYNCED; serverNet->connections[a].active=false; serverNet->SendData<unsigned char, unsigned char>(NETMSG_PLAYERLEFT, a, 1); lastLength=1; break; case NETMSG_PLAYERNAME: if(inbuf[inbufpos+2]!=a && a!=0){ SendSystemMsg("Server: Warning got playername msg from %i claiming to be from %i",a,inbuf[inbufpos+2]); } else { ENTER_MIXED; gs->players[inbuf[inbufpos+2]]->playerName=(char*)(&inbuf[inbufpos+3]); gs->players[inbuf[inbufpos+2]]->readyToStart=true; gs->players[inbuf[inbufpos+2]]->active=true; ENTER_UNSYNCED; SendSystemMsg("Player %s joined as %i",&inbuf[inbufpos+3],inbuf[inbufpos+2]); serverNet->SendData(&inbuf[inbufpos],inbuf[inbufpos+1]); //forward data } lastLength=inbuf[inbufpos+1]; break; case NETMSG_CHAT: if(inbuf[inbufpos+2]!=a){ SendSystemMsg("Server: Warning got chat msg from %i claiming to be from %i",a,inbuf[inbufpos+2]); } else { serverNet->SendData(&inbuf[inbufpos],inbuf[inbufpos+1]); //forward data } lastLength=inbuf[inbufpos+1]; break; case NETMSG_SYSTEMMSG: if(inbuf[inbufpos+2]!=a){ logOutput.Print("Server: Warning got system msg from %i claiming to be from %i",a,inbuf[inbufpos+2]); } else { serverNet->SendData(&inbuf[inbufpos],inbuf[inbufpos+1]); //forward data } lastLength=inbuf[inbufpos+1]; break; case NETMSG_STARTPOS: if(inbuf[inbufpos+1]!=gs->players[a]->team && a!=0){ SendSystemMsg("Server: Warning got select msg from %i claiming to be from team %i",a,inbuf[inbufpos+1]); } else { serverNet->SendData(&inbuf[inbufpos],15); //forward data } lastLength=15; break; case NETMSG_COMMAND: if(inbuf[inbufpos+3]!=a){ SendSystemMsg("Server: Warning got command msg from %i claiming to be from %i",a,inbuf[inbufpos+3]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],*((short int*)&inbuf[inbufpos+1])); //forward data } lastLength=*((short int*)&inbuf[inbufpos+1]); break; case NETMSG_SELECT: if(inbuf[inbufpos+3]!=a){ SendSystemMsg("Server: Warning got select msg from %i claiming to be from %i",a,inbuf[inbufpos+3]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],*((short int*)&inbuf[inbufpos+1])); //forward data } lastLength=*((short int*)&inbuf[inbufpos+1]); break; case NETMSG_AICOMMAND: if(inbuf[inbufpos+3]!=a){ SendSystemMsg("Server: Warning got aicommand msg from %i claiming to be from %i",a,inbuf[inbufpos+3]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],*((short int*)&inbuf[inbufpos+1])); //forward data } lastLength=*((short int*)&inbuf[inbufpos+1]); break; case NETMSG_SYNCRESPONSE:{ if(inbuf[inbufpos+1]!=a){ SendSystemMsg("Server: Warning got syncresponse msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->playbackDemo){ int frame = *(int*)&inbuf[inbufpos+2]; if(outstandingSyncFrame == frame) syncResponses[inbuf[inbufpos+1]] = *(CChecksum*)&inbuf[inbufpos+6]; else logOutput.Print("Delayed respone from %s (%i instead of %i)", gs->players[inbuf[inbufpos+1]]->playerName.c_str(), frame, outstandingSyncFrame); } } lastLength=6+sizeof(CChecksum);} break; case NETMSG_SHARE: if(inbuf[inbufpos+1]!=a){ SendSystemMsg("Server: Warning got share msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],12); //forward data } lastLength=12; break; case NETMSG_SETSHARE: if(inbuf[inbufpos+1]!=gs->players[a]->team){ SendSystemMsg("Server: Warning got setshare msg from player %i claiming to be from team %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],10); //forward data } lastLength=10; break; case NETMSG_PLAYERSTAT: if(inbuf[inbufpos+1]!=a){ SendSystemMsg("Server: Warning got stat msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { serverNet->SendData(&inbuf[inbufpos],sizeof(CPlayer::Statistics)+2); //forward data } lastLength=sizeof(CPlayer::Statistics)+2; break; case NETMSG_MAPDRAW: serverNet->SendData(&inbuf[inbufpos],inbuf[inbufpos+1]); //forward data lastLength=inbuf[inbufpos+1]; break; #ifdef DIRECT_CONTROL_ALLOWED case NETMSG_DIRECT_CONTROL: if(inbuf[inbufpos+1]!=a){ SendSystemMsg("Server: Warning got direct control msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],2); //forward data } lastLength=2; break; case NETMSG_DC_UPDATE: if(inbuf[inbufpos+1]!=a){ SendSystemMsg("Server: Warning got dc update msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],7); //forward data } lastLength=7; break; #endif default: #ifdef SYNCDEBUG // maybe something for the sync debugger? lastLength = CSyncDebugger::GetInstance()->ServerReceived(&inbuf[inbufpos]); if (!lastLength) #endif { logOutput.Print("Unknown net msg in server %d from %d pos %d last %d", (int)inbuf[inbufpos], a, inbufpos, lastMsg[a]); lastLength=1; } break; } if(lastLength<=0){ logOutput.Print("Server readnet got packet type %i length %i pos %i from %i??",thisMsg,lastLength,inbufpos,a); lastLength=1; } inbufpos+=lastLength; lastMsg[a]=thisMsg; } if(inbufpos!=inbuflength){ char txt[200]; sprintf(txt,"Wrong packet length got %d from %d instead of %d",inbufpos,a,inbuflength); logOutput.Print(txt); handleerror(0,txt,"Server network error",0); } } #ifdef SYNCDEBUG CSyncDebugger::GetInstance()->ServerHandlePendingBlockRequests(); #endif return true; }
bool CGameServer::HandleSyncResponses() { //check if last times sync responses is correct if (outstandingSyncFrame > 0 && !serverNet->playbackDemo) { CChecksum correctSync; for(int a = 0; a < gs->activePlayers; ++a) { if(gs->players[a]->active) { switch (syncResponseState[a]) { case SRS_WAITING: break; case SRS_TBH: // To Be Handled if (correctSync) { if (correctSync != syncResponses[a]) { char buf[10]; SendSystemMsg("Sync error for %s %i %s", gs->players[a]->playerName.c_str(), outstandingSyncFrame, correctSync.diff(buf, syncResponses[a])); if (outstandingChecksumFrame <= 0 && (correctSync.x != syncResponses[a].x || correctSync.y != syncResponses[a].y || correctSync.z != syncResponses[a].z)) { // try to resync by sending out a CHECKSUMREQUEST (only on XYZ sync errors) serverNet->SendData<int>(NETMSG_CHECKSUMREQUEST, serverframenum); outstandingChecksumFrame = serverframenum; lastChecksumRequest = gu->gameTime; for (int b = 0; b < gs->activePlayers; ++b) checksumResponses[b].resize(1, 0xFFFF); } syncResponseState[a] = SRS_WRONG; } else syncResponseState[a] = SRS_RIGHT; } else { //this assumes the lowest num player is the correct one, should maybe some sort of majority voting instead correctSync = syncResponses[a]; syncResponseState[a] = SRS_RIGHT; } break; case SRS_WRONG: break; case SRS_RIGHT: correctSync = syncResponses[a]; break; } } } } // Every 2 seconds, reset the sync repsonses and push a new SYCNREQUEST out. if(lastSyncRequest < gu->gameTime - 2){ lastSyncRequest = gu->gameTime; if (outstandingSyncFrame > 0) { for (int a = 0; a < gs->activePlayers; ++a) { if (gs->players[a]->active) { if (syncResponseState[a] == SRS_WAITING) info->AddLine("No sync response from %s", gs->players[a]->playerName.c_str()); } } outstandingSyncFrame = -1; } // wait with pushing a new syncrequest until all resync is finished. if (!serverNet->playbackDemo && outstandingChecksumFrame <= 0) { // reset for (int a = 0; a < gs->activePlayers; ++a) { syncResponses[a] = 0; syncResponseState[a] = SRS_WAITING; } //send sync request serverNet->SendData<int>(NETMSG_SYNCREQUEST, serverframenum); outstandingSyncFrame = serverframenum; } return true; } return false; }
bool CGameServer::ServerReadNet() { static int lastMsg[MAX_PLAYERS],thisMsg=0; for(int a=0;a<gs->activePlayers;a++){ int inbufpos=0; int inbuflength=0; if(gs->players[a]->active && (!gameSetup || a>=gameSetup->numDemoPlayers)){ if((inbuflength=serverNet->GetData(inbuf,NETWORK_BUFFER_SIZE,a))==-1){ PUSH_CODE_MODE; //this could lead to some nasty errors if the other thread switches code mode... ENTER_MIXED; gs->players[a]->active=false; POP_CODE_MODE; inbuflength=0; serverNet->SendData<unsigned char, unsigned char>(NETMSG_PLAYERLEFT, a, 0); } } // (*info) << serverNet->numConnected << "\n"; while(inbufpos<inbuflength){ thisMsg=inbuf[inbufpos]; int lastLength=0; switch (inbuf[inbufpos]){ case NETMSG_ATTEMPTCONNECT: //handled directly in CNet lastLength=3; break; case NETMSG_HELLO: lastLength=1; break; case NETMSG_RANDSEED: lastLength=5; serverNet->SendData(&inbuf[inbufpos],5); //forward data break; case NETMSG_NEWFRAME: gs->players[a]->ping=serverframenum-*(int*)&inbuf[inbufpos+1]; lastLength=5; break; case NETMSG_PAUSE: if(inbuf[inbufpos+2]!=a){ info->AddLine("Server: Warning got pause msg from %i claiming to be from %i",a,inbuf[inbufpos+2]); } else { if(game->gamePausable || a==0){ timeLeft=0; serverNet->SendData(&inbuf[inbufpos],3); } } lastLength=3; break; case NETMSG_INTERNAL_SPEED: info->AddLine("Server shouldnt get internal speed msgs?"); lastLength=5; break; case NETMSG_USER_SPEED: { float speed=*((float*)&inbuf[inbufpos+1]); if(speed>game->maxUserSpeed) speed=game->maxUserSpeed; if(speed<game->minUserSpeed) speed=game->minUserSpeed; if(gs->userSpeedFactor!=speed){ if(gs->speedFactor==gs->userSpeedFactor || gs->speedFactor>speed) serverNet->SendData<float>(NETMSG_INTERNAL_SPEED, speed); serverNet->SendData(&inbuf[inbufpos],5); //forward data } lastLength=5; break;} case NETMSG_CPU_USAGE: ENTER_MIXED; gs->players[a]->cpuUsage=*((float*)&inbuf[inbufpos+1]); ENTER_UNSYNCED; lastLength=5; break; case NETMSG_EXECHECKSUM: if(exeChecksum!=*((unsigned int*)&inbuf[inbufpos+1])){ SendSystemMsg("Wrong exe checksum from %i got %X instead of %X",a,*((unsigned int*)&inbuf[inbufpos+1]),exeChecksum); } lastLength=5; break; case NETMSG_MAPNAME: if(inbuf[inbufpos+1]) lastLength=inbuf[inbufpos+1]; break; case NETMSG_QUIT: ENTER_MIXED; gs->players[a]->active=false; ENTER_UNSYNCED; serverNet->connections[a].active=false; serverNet->SendData<unsigned char, unsigned char>(NETMSG_PLAYERLEFT, a, 1); lastLength=1; break; case NETMSG_PLAYERNAME: if(inbuf[inbufpos+2]!=a && a!=0){ SendSystemMsg("Server: Warning got playername msg from %i claiming to be from %i",a,inbuf[inbufpos+2]); } else { ENTER_MIXED; gs->players[inbuf[inbufpos+2]]->playerName=(char*)(&inbuf[inbufpos+3]); gs->players[inbuf[inbufpos+2]]->readyToStart=true; gs->players[inbuf[inbufpos+2]]->active=true; ENTER_UNSYNCED; SendSystemMsg("Player %s joined as %i",&inbuf[inbufpos+3],inbuf[inbufpos+2]); serverNet->SendData(&inbuf[inbufpos],inbuf[inbufpos+1]); //forward data } lastLength=inbuf[inbufpos+1]; break; case NETMSG_CHAT: if(inbuf[inbufpos+2]!=a){ SendSystemMsg("Server: Warning got chat msg from %i claiming to be from %i",a,inbuf[inbufpos+2]); } else { serverNet->SendData(&inbuf[inbufpos],inbuf[inbufpos+1]); //forward data } lastLength=inbuf[inbufpos+1]; break; case NETMSG_SYSTEMMSG: if(inbuf[inbufpos+2]!=a){ info->AddLine("Server: Warning got system msg from %i claiming to be from %i",a,inbuf[inbufpos+2]); } else { serverNet->SendData(&inbuf[inbufpos],inbuf[inbufpos+1]); //forward data } lastLength=inbuf[inbufpos+1]; break; case NETMSG_STARTPOS: if(inbuf[inbufpos+1]!=gs->players[a]->team && a!=0){ SendSystemMsg("Server: Warning got select msg from %i claiming to be from team %i",a,inbuf[inbufpos+1]); } else { serverNet->SendData(&inbuf[inbufpos],15); //forward data } lastLength=15; break; case NETMSG_COMMAND: if(inbuf[inbufpos+3]!=a){ SendSystemMsg("Server: Warning got command msg from %i claiming to be from %i",a,inbuf[inbufpos+3]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],*((short int*)&inbuf[inbufpos+1])); //forward data } lastLength=*((short int*)&inbuf[inbufpos+1]); break; case NETMSG_SELECT: if(inbuf[inbufpos+3]!=a){ SendSystemMsg("Server: Warning got select msg from %i claiming to be from %i",a,inbuf[inbufpos+3]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],*((short int*)&inbuf[inbufpos+1])); //forward data } lastLength=*((short int*)&inbuf[inbufpos+1]); break; case NETMSG_AICOMMAND: if(inbuf[inbufpos+3]!=a){ SendSystemMsg("Server: Warning got aicommand msg from %i claiming to be from %i",a,inbuf[inbufpos+3]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],*((short int*)&inbuf[inbufpos+1])); //forward data } lastLength=*((short int*)&inbuf[inbufpos+1]); break; case NETMSG_SYNCRESPONSE:{ if(inbuf[inbufpos+1]!=a){ SendSystemMsg("Server: Warning got syncresponse msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->playbackDemo){ int frame = *(int*)&inbuf[inbufpos+2]; if(outstandingSyncFrame == frame) { syncResponses[inbuf[inbufpos+1]] = *(CChecksum*)&inbuf[inbufpos+6]; syncResponseState[inbuf[inbufpos+1]] = SRS_TBH; } else info->AddLine("Delayed sync respone from %s (%i instead of %i)", gs->players[inbuf[inbufpos+1]]->playerName.c_str(), frame, outstandingSyncFrame); } } lastLength=6+sizeof(CChecksum);} break; case NETMSG_SHARE: if(inbuf[inbufpos+1]!=a){ SendSystemMsg("Server: Warning got share msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],12); //forward data } lastLength=12; break; case NETMSG_SETSHARE: if(inbuf[inbufpos+1]!=gs->players[a]->team){ SendSystemMsg("Server: Warning got setshare msg from player %i claiming to be from team %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],10); //forward data } lastLength=10; break; case NETMSG_PLAYERSTAT: if(inbuf[inbufpos+1]!=a){ SendSystemMsg("Server: Warning got stat msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { serverNet->SendData(&inbuf[inbufpos],sizeof(CPlayer::Statistics)+2); //forward data } lastLength=sizeof(CPlayer::Statistics)+2; break; case NETMSG_MAPDRAW: serverNet->SendData(&inbuf[inbufpos],inbuf[inbufpos+1]); //forward data lastLength=inbuf[inbufpos+1]; break; #ifdef DIRECT_CONTROL_ALLOWED case NETMSG_DIRECT_CONTROL: if(inbuf[inbufpos+1]!=a){ SendSystemMsg("Server: Warning got direct control msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],2); //forward data } lastLength=2; break; case NETMSG_DC_UPDATE: if(inbuf[inbufpos+1]!=a){ SendSystemMsg("Server: Warning got dc update msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],7); //forward data } lastLength=7; break; #endif case NETMSG_CHECKSUMRESPONSE: /* unsigned char NETMSG_CHECKSUMRESPONSE @0 short int size @1 unsigned char myPlayerNum @3 int frameNum @4 std::vector<unsigned short> @8 */ if(inbuf[inbufpos+3]!=a){ SendSystemMsg("Server: Warning got checksum response msg from %i claiming to be from %i", a, inbuf[inbufpos+1]); } else { if(!serverNet->playbackDemo){ int player = inbuf[inbufpos+3]; int frame = *(int*)&inbuf[inbufpos+4]; if(outstandingChecksumFrame == frame) { int numelem = (*((short int*)&inbuf[inbufpos+1]) - 8) / sizeof(short); const unsigned short* begin = (unsigned short*)&inbuf[inbufpos+8]; const unsigned short* end = begin + numelem; checksumResponses[player].resize(numelem); std::copy(begin, end, checksumResponses[player].begin()); } else info->AddLine("Delayed checksum respone from %s (%i instead of %i)", gs->players[player]->playerName.c_str(), frame, outstandingChecksumFrame); } } lastLength=*((short int*)&inbuf[inbufpos+1]); assert(lastLength > 0); break; case NETMSG_RESYNCRESPONSE: { /* unsigned char NETMSG_RESYNCRESPONSE @0 int frameNum @1 CResyncUnit unit data @5 */ int* frame = (int*)&inbuf[inbufpos+1]; // Adjust frame to the right value. *frame = serverframenum; lastLength=5+sizeof(CResyncUnit);} if(!serverNet->playbackDemo) serverNet->SendData(&inbuf[inbufpos],lastLength); //forward data to everyone break; default: char txt[200]; sprintf(txt,"Unknown net msg in server %d from %d pos %d last %d",(int)inbuf[inbufpos],a,inbufpos,lastMsg[a]); info->AddLine(txt); //handleerror(0,txt,"Network error",0); lastLength=1; break; } if(lastLength<=0){ info->AddLine("Server readnet got packet type %i length %i pos %i from %i??",thisMsg,lastLength,inbufpos,a); lastLength=1; } inbufpos+=lastLength; lastMsg[a]=thisMsg; } if(inbufpos!=inbuflength){ char txt[200]; sprintf(txt,"Wrong packet length got %d from %d instead of %d",inbufpos,a,inbuflength); info->AddLine(txt); handleerror(0,txt,"Server network error",0); } } return true; }
void CGameServer::CheckSync() { #ifdef SYNCCHECK // Check sync std::deque<int>::iterator f = outstandingSyncFrames.begin(); while (f != outstandingSyncFrames.end()) { //maps incorrect checksum to players with that checksum std::map<unsigned, std::vector<int> > desyncGroups; bool bComplete = true; bool bGotCorrectChecksum = false; unsigned correctChecksum = 0; for (int a = 0; a < MAX_PLAYERS; ++a) { if (!gs->players[a]->active) continue; std::map<int, unsigned>::iterator it = syncResponse[a].find(*f); if (it == syncResponse[a].end()) { if (*f >= serverframenum - SYNCCHECK_TIMEOUT) bComplete = false; else logOutput.Print("No sync response from %s for frame %d", gs->players[a]->playerName.c_str(), *f); } else { if (!bGotCorrectChecksum) { bGotCorrectChecksum = true; correctChecksum = it->second; } else if (it->second != correctChecksum) { desyncGroups[it->second].push_back(a); } } } // If anything's in it, we have a desync. // TODO take care of !bComplete case? // Should we start resync then immediately or wait for the missing packets (while paused)? if (bComplete && !desyncGroups.empty()) { if (!syncErrorFrame || (*f - syncErrorFrame > SYNCCHECK_MSG_TIMEOUT)) { syncErrorFrame = *f; // TODO enable this when we have resync //serverNet->SendData<unsigned char, unsigned char>(NETMSG_PAUSE, gu->myPlayerNum, true); //For each group, output a message with list of playernames in it. // TODO this should be linked to the resync system so it can roundrobin // the resync checksum request packets to multiple clients in the same group. std::map<unsigned, std::vector<int> >::const_iterator g = desyncGroups.begin(); for (; g != desyncGroups.end(); ++g) { std::string players; std::vector<int>::const_iterator p = g->second.begin(); for (; p != g->second.end(); ++p) { if (!players.empty()) players += ", "; players += gs->players[*p]->playerName; } SendSystemMsg("Sync error for %s in frame %d (0x%X)", players.c_str(), *f, g->first ^ correctChecksum); } } } // Remove complete sets (for which all player's checksums have been received). if (bComplete) { // if (*f >= serverframenum - SYNCCHECK_TIMEOUT) // logOutput.Print("Succesfully purged outstanding sync frame %d from the deque", *f); for (int a = 0; a < MAX_PLAYERS; ++a) { if (gs->players[a]->active) syncResponse[a].erase(*f); } f = outstandingSyncFrames.erase(f); } else ++f; } #else // Make it clear this build isn't suitable for release. if (!syncErrorFrame || (serverframenum - syncErrorFrame > SYNCCHECK_MSG_TIMEOUT)) { syncErrorFrame = serverframenum; SendSystemMsg("Warning: Sync checking disabled!"); } #endif }
bool CGameServer::Update(void) { if(lastSyncRequest<gu->gameTime-2){ lastSyncRequest=gu->gameTime; if(game->playing){ //check if last times sync responses is correct if(outstandingSyncFrame>0){ int correctSync=0; for(int a=0;a<MAX_PLAYERS;++a){ if(gs->players[a]->active){ if(!syncResponses[a] && !serverNet->playbackDemo){ //if the checksum really happens to be 0 we will get lots of falls positives here info->AddLine("No sync response from %s",gs->players[a]->playerName.c_str()); continue; } if(correctSync && correctSync!=syncResponses[a]){ SendSystemMsg("Sync error for %s %i %X %X",gs->players[a]->playerName.c_str(),outstandingSyncFrame,correctSync,syncResponses[a]); continue; } correctSync=syncResponses[a]; //this assumes the lowest num player is the correct one, should maybe use some sort of majority voting instead } } } for(int a=0;a<MAX_PLAYERS;++a) syncResponses[a]=0; if(!serverNet->playbackDemo){ //send sync request outbuf[0]=NETMSG_SYNCREQUEST; (*((int*)&outbuf[1]))=serverframenum; serverNet->SendData(outbuf,5); outstandingSyncFrame=serverframenum; } int firstReal=0; if(gameSetup) firstReal=gameSetup->numDemoPlayers; //send info about the players for(int a=firstReal;a<MAX_PLAYERS;++a){ if(gs->players[a]->active){ outbuf[0]=NETMSG_PLAYERINFO; outbuf[1]=a; *(float*)&outbuf[2]=gs->players[a]->cpuUsage; *(int*)&outbuf[6]=gs->players[a]->ping; serverNet->SendData(outbuf,10); } } //decide new internal speed float maxCpu=0; for(int a=0;a<MAX_PLAYERS;++a){ if(gs->players[a]->cpuUsage>maxCpu && gs->players[a]->active){ maxCpu=gs->players[a]->cpuUsage; } } float wantedCpu=0.35+(1-gs->speedFactor/gs->userSpeedFactor)*0.5; //float speedMod=1+wantedCpu-maxCpu; float newSpeed=gs->speedFactor*wantedCpu/maxCpu; //info->AddLine("Speed %f %f %f %f",maxCpu,wantedCpu,speedMod,newSpeed); newSpeed=(newSpeed+gs->speedFactor)*0.5; if(newSpeed>gs->userSpeedFactor) newSpeed=gs->userSpeedFactor; if(newSpeed<0.1) newSpeed=0.1; if(newSpeed!=gs->speedFactor){ outbuf[0]=NETMSG_INTERNAL_SPEED; *((float*)&outbuf[1])=newSpeed; serverNet->SendData(outbuf,5); } } } if(!ServerReadNet()){ info->AddLine("Server read net wanted quit"); return false; } if (game->playing && !serverNet->playbackDemo){ LARGE_INTEGER currentFrame; QueryPerformanceCounter(¤tFrame); double timeElapsed=((double)(currentFrame.QuadPart - lastframe.QuadPart))/timeSpeed.QuadPart; if(gameEndDetected) gameEndTime+=timeElapsed; // info->AddLine("float value is %f",timeElapsed); if(gameClientUpdated){ gameClientUpdated=false; maxTimeLeft=2; } if(timeElapsed>maxTimeLeft) timeElapsed=maxTimeLeft; maxTimeLeft-=timeElapsed; timeLeft+=GAME_SPEED*gs->speedFactor*timeElapsed; lastframe=currentFrame; while((timeLeft>0) && (!gs->paused || game->bOneStep)){ if(!game->creatingVideo){ game->bOneStep=false; CreateNewFrame(true); } timeLeft--; } } serverNet->Update(); CheckForGameEnd(); return true; }
bool CGameServer::ServerReadNet() { static int lastMsg[MAX_PLAYERS],thisMsg=0; for(int a=0; a<gs->activePlayers; a++) { int inbufpos=0; int inbuflength=0; if (gs->players[a]->active && ((!net->localDemoPlayback && (!gameSetup || a>=gameSetup->numDemoPlayers)) || (net->localDemoPlayback && a == (gameSetup ? gameSetup->myPlayer : 0) ))) { if((inbuflength=serverNet->GetData(inbuf,netcode::NETWORK_BUFFER_SIZE,a))==-1) { PUSH_CODE_MODE; //this could lead to some nasty errors if the other thread switches code mode... ENTER_MIXED; gs->players[a]->active=false; POP_CODE_MODE; inbuflength=0; serverNet->SendPlayerLeft(a, 0); } } // dont bother handling anything if we are just sending a demo to // localhost, this would result in double chat messages and server warnings.. if (net->localDemoPlayback) continue; // logOutput << serverNet->numConnected << "\n"; while(inbufpos<inbuflength) { thisMsg=inbuf[inbufpos]; int lastLength=0; // TODO rearrange this in order of importance (most used to the front) switch (inbuf[inbufpos]) { case NETMSG_HELLO: lastLength=1; break; case NETMSG_ATTEMPTCONNECT: //handled directly in CNet lastLength=3; break; case NETMSG_RANDSEED: lastLength=5; serverNet->SendRandSeed(inbuf[inbufpos+1]); //forward data break; case NETMSG_NEWFRAME: gs->players[a]->ping=serverframenum-*(int*)&inbuf[inbufpos+1]; lastLength=5; break; case NETMSG_PAUSE: if(inbuf[inbufpos+1]!=a) { logOutput.Print("Server: Warning got pause msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if (!inbuf[inbufpos+2]) // reset sync checker syncErrorFrame = 0; assert(game); if(game->gamePausable || a==0) { timeLeft=0; serverNet->SendPause(inbuf[inbufpos+1],inbuf[inbufpos+2]); } } lastLength=3; break; case NETMSG_INTERNAL_SPEED: logOutput.Print("Server shouldnt get internal speed msgs?"); lastLength=5; break; case NETMSG_USER_SPEED: { float speed=*((float*)&inbuf[inbufpos+1]); assert(game); if(speed>game->maxUserSpeed) speed=game->maxUserSpeed; if(speed<game->minUserSpeed) speed=game->minUserSpeed; if(gs->userSpeedFactor!=speed) { if(gs->speedFactor==gs->userSpeedFactor || gs->speedFactor>speed) serverNet->SendInternalSpeed(speed); serverNet->SendUserSpeed(speed); //forward data } lastLength=5; break; } case NETMSG_CPU_USAGE: ENTER_MIXED; gs->players[a]->cpuUsage=*((float*)&inbuf[inbufpos+1]); ENTER_UNSYNCED; lastLength=5; break; case NETMSG_QUIT: ENTER_MIXED; gs->players[a]->active=false; ENTER_UNSYNCED; serverNet->connections[a]->active=false; serverNet->SendPlayerLeft(a, 1); lastLength=1; break; case NETMSG_PLAYERNAME: { unsigned char playerNum = inbuf[inbufpos+2]; if(playerNum!=a && a!=0) { SendSystemMsg("Server: Warning got playername msg from %i claiming to be from %i",a,playerNum); } else { ENTER_MIXED; gs->players[playerNum]->playerName=(char*)(&inbuf[inbufpos+3]); gs->players[playerNum]->readyToStart=true; gs->players[playerNum]->active=true; ENTER_UNSYNCED; SendSystemMsg("Player %s joined as %i",&inbuf[inbufpos+3],playerNum); serverNet->SendPlayerName(playerNum,gs->players[playerNum]->playerName); } lastLength=inbuf[inbufpos+1]; break; } case NETMSG_CHAT: if(inbuf[inbufpos+2]!=a) { SendSystemMsg("Server: Warning got chat msg from %i claiming to be from %i",a,inbuf[inbufpos+2]); } else { serverNet->SendChat(inbuf[inbufpos+2], (char*)(&inbuf[inbufpos+3])); } lastLength=inbuf[inbufpos+1]; break; case NETMSG_SYSTEMMSG: if(inbuf[inbufpos+2]!=a) { logOutput.Print("Server: Warning got system msg from %i claiming to be from %i",a,inbuf[inbufpos+2]); } else { serverNet->SendSystemMessage(inbuf[inbufpos+2], (char*)(&inbuf[inbufpos+3])); } lastLength=inbuf[inbufpos+1]; break; case NETMSG_STARTPOS: if(inbuf[inbufpos+1]!=gs->players[a]->team && a!=0) { SendSystemMsg("Server: Warning got startpos msg from %i claiming to be from team %i",a,inbuf[inbufpos+1]); } else { serverNet->SendStartPos(inbuf[inbufpos+1],inbuf[inbufpos+2], *((float*)&inbuf[inbufpos+3]), *((float*)&inbuf[inbufpos+7]), *((float*)&inbuf[inbufpos+11])); //forward data } lastLength=15; break; case NETMSG_COMMAND: if(inbuf[inbufpos+3]!=a) { SendSystemMsg("Server: Warning got command msg from %i claiming to be from %i",a,inbuf[inbufpos+3]); } else { if(!serverNet->IsDemoServer()) serverNet->RawSend(&inbuf[inbufpos],*((short int*)&inbuf[inbufpos+1])); //forward data } lastLength=*((short int*)&inbuf[inbufpos+1]); break; case NETMSG_SELECT: if(inbuf[inbufpos+3]!=a) { SendSystemMsg("Server: Warning got select msg from %i claiming to be from %i",a,inbuf[inbufpos+3]); } else { if(!serverNet->IsDemoServer()) serverNet->RawSend(&inbuf[inbufpos],*((short int*)&inbuf[inbufpos+1])); //forward data } lastLength=*((short int*)&inbuf[inbufpos+1]); break; case NETMSG_AICOMMAND: if(inbuf[inbufpos+3]!=a) { SendSystemMsg("Server: Warning got aicommand msg from %i claiming to be from %i",a,inbuf[inbufpos+3]); } else if (gs->noHelperAIs) { SendSystemMsg("Server: Player %i is using a helper AI illegally", a); } else if(!serverNet->IsDemoServer()) { serverNet->RawSend(&inbuf[inbufpos],*((short int*)&inbuf[inbufpos+1])); //forward data } lastLength=*((short int*)&inbuf[inbufpos+1]); break; case NETMSG_AICOMMANDS: if(inbuf[inbufpos+3]!=a) { SendSystemMsg("Server: Warning got aicommands msg from %i claiming to be from %i",a,inbuf[inbufpos+3]); } else if (gs->noHelperAIs) { SendSystemMsg("Server: Player %i is using a helper AI illegally", a); } else if(!serverNet->IsDemoServer()) { serverNet->RawSend(&inbuf[inbufpos],*((short int*)&inbuf[inbufpos+1])); //forward data } lastLength=*((short int*)&inbuf[inbufpos+1]); break; case NETMSG_SYNCRESPONSE: #ifdef SYNCCHECK if(inbuf[inbufpos+1]!=a) { SendSystemMsg("Server: Warning got syncresponse msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->IsDemoServer()) { int frameNum = *(int*)&inbuf[inbufpos+2]; if (outstandingSyncFrames.empty() || frameNum >= outstandingSyncFrames.front()) syncResponse[a][frameNum] = *(unsigned*)&inbuf[inbufpos+6]; else if (serverframenum - delayedSyncResponseFrame > SYNCCHECK_MSG_TIMEOUT) { delayedSyncResponseFrame = serverframenum; logOutput.Print("Delayed respone from %s for frame %d (current %d)", gs->players[a]->playerName.c_str(), frameNum, serverframenum); } } } #endif lastLength=10; break; case NETMSG_SHARE: if(inbuf[inbufpos+1]!=a) { SendSystemMsg("Server: Warning got share msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->IsDemoServer()) serverNet->SendShare(inbuf[inbufpos+1], inbuf[inbufpos+2], inbuf[inbufpos+3], *((float*)&inbuf[inbufpos+4]), *((float*)&inbuf[inbufpos+8])); } lastLength=12; break; case NETMSG_SETSHARE: if(inbuf[inbufpos+1]!=gs->players[a]->team) { SendSystemMsg("Server: Warning got setshare msg from player %i claiming to be from team %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->IsDemoServer()) serverNet->SendSetShare(inbuf[inbufpos+1], *((float*)&inbuf[inbufpos+2]), *((float*)&inbuf[inbufpos+6])); } lastLength=10; break; case NETMSG_PLAYERSTAT: if(inbuf[inbufpos+1]!=a) { SendSystemMsg("Server: Warning got stat msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { serverNet->RawSend(&inbuf[inbufpos],sizeof(CPlayer::Statistics)+2); //forward data } lastLength=sizeof(CPlayer::Statistics)+2; break; case NETMSG_MAPDRAW: serverNet->RawSend(&inbuf[inbufpos],inbuf[inbufpos+1]); //forward data lastLength=inbuf[inbufpos+1]; break; #ifdef DIRECT_CONTROL_ALLOWED case NETMSG_DIRECT_CONTROL: if(inbuf[inbufpos+1]!=a) { SendSystemMsg("Server: Warning got direct control msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->IsDemoServer()) serverNet->SendDirectControl(inbuf[inbufpos+1]); } lastLength=2; break; case NETMSG_DC_UPDATE: if(inbuf[inbufpos+1]!=a) { SendSystemMsg("Server: Warning got dc update msg from %i claiming to be from %i",a,inbuf[inbufpos+1]); } else { if(!serverNet->IsDemoServer()) serverNet->SendDirectControlUpdate(inbuf[inbufpos+1], inbuf[inbufpos+2], *((short*)&inbuf[inbufpos+3]), *((short*)&inbuf[inbufpos+5])); } lastLength=7; break; #endif default: #ifdef SYNCDEBUG // maybe something for the sync debugger? lastLength = CSyncDebugger::GetInstance()->ServerReceived(&inbuf[inbufpos]); if (!lastLength) #endif { logOutput.Print("Unknown net msg in server %d from %d pos %d last %d", (int)inbuf[inbufpos], a, inbufpos, lastMsg[a]); lastLength=1; } break; } if(lastLength<=0) { logOutput.Print("Server readnet got packet type %i length %i pos %i from %i??",thisMsg,lastLength,inbufpos,a); lastLength=1; } inbufpos+=lastLength; lastMsg[a]=thisMsg; } if(inbufpos!=inbuflength) { char txt[200]; sprintf(txt,"Wrong packet length got %d from %d instead of %d",inbufpos,a,inbuflength); logOutput.Print("%s", txt); handleerror(0,txt,"Server network error",0); } } #ifdef SYNCDEBUG CSyncDebugger::GetInstance()->ServerHandlePendingBlockRequests(); #endif return true; }