bool C4Network2IO::Ping() { bool fSuccess = true; // ping all connections for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext) if (pConn->isOpen()) { C4PacketPing Ping(pConn->getInPacketCounter(), pConn->getOutPacketCounter()); fSuccess &= pConn->Send(MkC4NetIOPacket(PID_Ping, Ping)); pConn->OnPing(); } return fSuccess; }
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 }