void C4Network2Players::HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn) { if (!pConn) return; // find associated client C4Network2Client *pClient = ::Network.Clients.GetClient(pConn); if (!pClient) pClient = ::Network.Clients.GetClientByID(pConn->getClientID()); #define GETPKT(type, name) \ assert(pPacket); const type &name = \ static_cast<const type &>(*pPacket); // player join request? if (cStatus == PID_PlayerInfoUpdReq) { GETPKT(C4PacketPlayerInfoUpdRequest, pkPlrInfo); // this packet is sent to the host only, and thus cannot have been sent from the host if (!::Network.isHost()) return; // handle this packet HandlePlayerInfoUpdRequest(&pkPlrInfo.Info, false); } else if (cStatus == PID_LeagueRoundResults) { GETPKT(C4PacketLeagueRoundResults, pkLeagueInfo); // accepted from the host only if (!pClient || !pClient->isHost()) return; // process Game.RoundResults.EvaluateLeague(pkLeagueInfo.sResultsString.getData(), pkLeagueInfo.fSuccess, pkLeagueInfo.Players); } #undef GETPKT }
void C4Network2ClientList::HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn) { // find associated client C4Network2Client *pClient = GetClient(pConn); if (!pClient) return; #define GETPKT(type, name) \ assert(pBasePkt); const type &name = \ static_cast<const type &>(*pBasePkt); switch (cStatus) { case PID_Addr: // address propagation { GETPKT(C4PacketAddr, rPkt) // find client pClient = GetClientByID(rPkt.getClientID()); if (pClient) { C4Network2Address addr = rPkt.getAddr(); // IP zero? Set to IP from where the packet came if (addr.isIPNull()) { addr.SetIP(pConn->getPeerAddr()); } // add (no announce) if (pClient->AddAddr(addr, true)) // new address? Try to connect pClient->DoConnectAttempt(pIO); } } break; case PID_TCPSimOpen: { GETPKT(C4PacketTCPSimOpen, rPkt) pClient = GetClientByID(rPkt.getClientID()); if (pClient) { C4Network2Address addr = rPkt.getAddr(); pClient->DoTCPSimultaneousOpen(pIO, addr); } } break; } #undef GETPKT }
void C4Network2ResList::HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn) { // security if (!pConn) return; #define GETPKT(type, name) \ assert(pPacket); const type &name = \ static_cast<const type &>(*pPacket); switch (cStatus) { case PID_NetResDis: // resource discover { if (!pConn->isOpen()) break; GETPKT(C4PacketResDiscover, Pkt); // search matching resources CStdShareLock ResListLock(&ResListCSec); for (C4Network2Res *pRes = pFirst; pRes; pRes = pRes->pNext) if (Pkt.isIDPresent(pRes->getResID())) // must be binary compatible if (pRes->IsBinaryCompatible()) pRes->OnDiscover(pConn); } break; case PID_NetResStat: // resource status { if (!pConn->isOpen()) break; GETPKT(C4PacketResStatus, Pkt); // matching resource? CStdShareLock ResListLock(&ResListCSec); C4Network2Res *pRes = getRes(Pkt.getResID()); // present / being loaded? call handler if (pRes) pRes->OnStatus(Pkt.getChunks(), pConn); } break; case PID_NetResDerive: // resource derive { GETPKT(C4Network2ResCore, Core); if (Core.getDerID() < 0) break; // Check if there is a anonymous derived resource with matching parent. CStdShareLock ResListLock(&ResListCSec); for (C4Network2Res *pRes = pFirst; pRes; pRes = pRes->pNext) if (pRes->isAnonymous() && pRes->getCore().getDerID() == Core.getDerID()) pRes->FinishDerive(Core); } break; case PID_NetResReq: // resource request { GETPKT(C4PacketResRequest, Pkt); // find resource CStdShareLock ResListLock(&ResListCSec); C4Network2Res *pRes = getRes(Pkt.getReqID()); // send requested chunk if (pRes && pRes->IsBinaryCompatible()) pRes->SendChunk(Pkt.getReqChunk(), pConn->getClientID()); } break; case PID_NetResData: // a chunk of data is coming in { GETPKT(C4Network2ResChunk, Chunk); // find resource CStdShareLock ResListLock(&ResListCSec); C4Network2Res *pRes = getRes(Chunk.getResID()); // send requested chunk if (pRes) pRes->OnChunk(Chunk); } break; } #undef GETPKT }
void C4Network2IO::HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn) { // security if (!pConn) return; #define GETPKT(type, name) \ assert(pPacket); const type &name = \ static_cast<const type &>(*pPacket); switch (cStatus) { case PID_Conn: // connection request { if (!pConn->isOpen()) break; // get packet GETPKT(C4PacketConn, rPkt) // set connection ID pConn->SetRemoteID(rPkt.getConnID()); // check auto-accept if (doAutoAccept(rPkt.getCCore(), *pConn)) { // send answer back C4PacketConnRe pcr(true, false, "auto accept"); if (!pConn->Send(MkC4NetIOPacket(PID_ConnRe, pcr))) pConn->Close(); // accept pConn->SetStatus(CS_HalfAccepted); pConn->SetCCore(rPkt.getCCore()); pConn->SetAutoAccepted(); } // note that this packet will get processed by C4Network2, too (main thread) } break; case PID_ConnRe: // connection request reply { if (!pConn->isOpen()) break; // conn not sent? That's fishy. // FIXME: Note this happens if the peer has exclusive connection mode on. if (!pConn->isConnSent()) { pConn->Close(); break; } // get packet GETPKT(C4PacketConnRe, rPkt) // auto accept connection if (rPkt.isOK()) { if (pConn->isHalfAccepted() && pConn->isAutoAccepted()) pConn->SetAccepted(); } } break; case PID_Ping: { if (!pConn->isOpen()) break; GETPKT(C4PacketPing, rPkt) // pong C4PacketPing PktPong = rPkt; pConn->Send(MkC4NetIOPacket(PID_Pong, PktPong)); // remove received packets from log pConn->ClearPacketLog(rPkt.getPacketCounter()); } break; case PID_Pong: { if (!pConn->isOpen()) break; GETPKT(C4PacketPing, rPkt); // save pConn->SetPingTime(rPkt.getTravelTime()); } break; case PID_FwdReq: { GETPKT(C4PacketFwd, rPkt); HandleFwdReq(rPkt, pConn); } break; case PID_Fwd: { GETPKT(C4PacketFwd, rPkt); // only received accidently? if (!rPkt.DoFwdTo(LCCore.getID())) break; // handle C4NetIOPacket Packet(rPkt.getData(), pConn->getPeerAddr()); HandlePacket(Packet, pConn, true); } break; case PID_PostMortem: { GETPKT(C4PacketPostMortem, rPkt); // Get connection C4Network2IOConnection *pConn = GetConnectionByID(rPkt.getConnID()); if (!pConn) return; // Handle all packets uint32_t iCounter; for (iCounter = pConn->getInPacketCounter(); ; iCounter++) { // Get packet const C4NetIOPacket *pPkt = rPkt.getPacket(iCounter); if (!pPkt) break; // Handle it HandlePacket(*pPkt, pConn, true); } // Log if (iCounter > pConn->getInPacketCounter()) Application.InteractiveThread.ThreadLogS("Network: Recovered %d packets", iCounter - pConn->getInPacketCounter()); // Remove the connection from our list if (!pConn->isClosed()) pConn->Close(); RemoveConnection(pConn); } break; } #undef GETPKT }