void C4Network2IO::SendConnPackets() { CStdLock ConnListLock(&ConnListCSec); // exlusive conn? if (fExclusiveConn) // find a live connection for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext) if (pConn->isAccepted() || (!pConn->isClosed() && pConn->isConnSent())) // do not sent additional conn packets - no other connection should succeed return; // sent pending welcome packet(s) for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext) if (pConn->isOpen() && !pConn->isConnSent()) { // make packet CStdLock LCCoreLock(&LCCoreCSec); C4NetIOPacket Pkt = MkC4NetIOPacket(PID_Conn, C4PacketConn(LCCore, pConn->getID(), pConn->getPassword())); LCCoreLock.Clear(); // send if (!pConn->Send(Pkt)) pConn->Close(); else { // set flag pConn->SetConnSent(); // only one conn packet at a time if (fExclusiveConn) return; } } }
// C4NetIO interface bool C4Network2IO::OnConn(const C4NetIO::addr_t &PeerAddr, const C4NetIO::addr_t &ConnectAddr, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO) { // puncher answer? We just make sure here a connection /can/ be established, so close it instantly. if (pNetIO == pNetIO_UDP) if (PuncherAddr.sin_addr.s_addr && AddrEqual(PuncherAddr, ConnectAddr)) { // got an address? if (pOwnAddr) OnPunch(*pOwnAddr); // this is only a test connection - close it instantly return false; } #if(C4NET2IO_DUMP_LEVEL > 1) Application.InteractiveThread.ThreadLogS("OnConn: %s %s", C4TimeMilliseconds::Now().AsString().getData(), getNetIOName(pNetIO)); #endif // search connection C4Network2IOConnection *pConn = NULL; if (ConnectAddr.sin_addr.s_addr) pConn = GetConnectionByConnAddr(ConnectAddr, pNetIO); // not found? if (!pConn) { // allow connect? if (!fAllowConnect) return false; // create new connection object uint32_t iConnID = iNextConnID++; pConn = new C4Network2IOConnection(); pConn->Set(pNetIO, getNetIOProt(pNetIO), PeerAddr, ConnectAddr, CS_Connected, NULL, iConnID); // add to list AddConnection(pConn); } else { // already closed this connection (attempt)? if (pConn->isClosed()) return false; if (!pConn->isOpen()) { // change status pConn->SetStatus(CS_Connected); pConn->SetPeerAddr(PeerAddr); } } // send welcome packet, if appropriate SendConnPackets(); #if(C4NET2IO_DUMP_LEVEL > 0) // log Application.InteractiveThread.ThreadLogS("Network: got %s connection from %s:%d", getNetIOName(pNetIO), inet_ntoa(PeerAddr.sin_addr), htons(PeerAddr.sin_port)); #endif // do event (disabled - unused) // pConn->AddRef(); PushNetEv(NE_Conn, pConn); // ok return true; }
void C4Network2IO::BeginBroadcast(bool fSelectAll) { // lock BroadcastCSec.Enter(); // reset all broadcast flags CStdLock ConnListLock(&ConnListCSec); for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext) if (pConn->isOpen()) pConn->SetBroadcastTarget(fSelectAll); }
bool C4Network2IO::Broadcast(const C4NetIOPacket &rPkt) { bool fSuccess = true; // There is no broadcasting atm, emulate it CStdLock ConnListLock(&ConnListCSec); for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext) if (pConn->isOpen() && pConn->isBroadcastTarget()) fSuccess &= pConn->Send(rPkt); if(!fSuccess) Log("Network: Warning! Broadcast failed."); return fSuccess; }
void C4Network2Client::CloseConns(const char *szMsg) { C4PacketConnRe Pkt(false, false, szMsg); C4Network2IOConnection *pConn; while (pConn = pMsgConn) { // send packet, close if (pConn->isOpen()) { pConn->Send(MkC4NetIOPacket(PID_ConnRe, Pkt)); pConn->Close(); } // remove RemoveConn(pConn); } }
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::GenerateStatistics(int iInterval) { int iTCPIRateSum = 0, iTCPORateSum = 0, iUDPIRateSum = 0, iUDPORateSum = 0; // acquire lock, get connection statistics CStdLock ConnListLock(&ConnListCSec); for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext) if (pConn->isOpen()) { bool fTCP = pConn->getNetClass() == pNetIO_TCP; pConn->DoStatistics(iInterval, fTCP ? &iTCPIRateSum : &iUDPIRateSum, fTCP ? &iTCPORateSum : &iUDPORateSum); } ConnListLock.Clear(); // get broadcast statistics int inTCPBCRate = 0, inUDPBCRate = 0; if (pNetIO_TCP) pNetIO_TCP->GetStatistic(&inTCPBCRate); if (pNetIO_UDP) pNetIO_UDP->GetStatistic(&inUDPBCRate); // normalize everything iTCPIRateSum = iTCPIRateSum * 1000 / iInterval; iTCPORateSum = iTCPORateSum * 1000 / iInterval; iUDPIRateSum = iUDPIRateSum * 1000 / iInterval; iUDPORateSum = iUDPORateSum * 1000 / iInterval; inTCPBCRate = inTCPBCRate * 1000 / iInterval; inUDPBCRate = inUDPBCRate * 1000 / iInterval; // clear if (pNetIO_TCP) pNetIO_TCP->ClearStatistic(); if (pNetIO_UDP) pNetIO_UDP->ClearStatistic(); // save back iTCPIRate = iTCPIRateSum; iTCPORate = iTCPORateSum; iTCPBCRate = inTCPBCRate; iUDPIRate = iUDPIRateSum; iUDPORate = iUDPORateSum; iUDPBCRate = inUDPBCRate; }