26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
39 #define C4NET2IO_DUMP_LEVEL 1
44 : tLastExecute(0), tLastPing(0), tLastStatistic(0)
53 bool C4Network2IO::Init(int16_t iPortTCP, int16_t iPortUDP, int16_t iPortDiscover, int16_t iPortRefServer,
bool fBroadcast,
bool enable_upnp)
70 if (enable_upnp && (iPortTCP > 0 || iPortUDP > 0))
88 LogSilentF(
"Network: TCP initialized on port %d", iPortTCP);
111 LogSilentF(
"Network: UDP initialized on port %d", iPortUDP);
125 LogFatal(
"Network: fatal - no protocols available!");
133 if (iPortDiscover > 0)
145 LogSilentF(
"Network: discovery initialized on port %d", iPortDiscover);
152 if (iPortRefServer > 0)
163 LogSilentF(
"Network: reference server initialized on port %d", iPortRefServer);
190 pNext = pConn->pNext;
197 ConnListLock.
Clear();
243 if (!pNetIO)
return false;
251 pConn->
Set(pNetIO, eProt, paddr, addr,
CS_Connect, szPassword, iConnID);
301 if (!pConn->isClosed())
310 while (pAutoAcceptList)
314 pAutoAcceptList = pAcc->
Next;
327 pAcc->
Next = pAutoAcceptList;
328 pAutoAcceptList = pAcc;
335 AutoAccept *pAcc = pAutoAcceptList, *pLast =
nullptr;
342 (pLast ? pLast->Next : pAutoAcceptList) = pAcc;
359 if (pConn->isAccepted())
360 if (pConn->getClientID() == iClientID)
361 if (pConn->getProtocol() ==
P_UDP || !pRes)
373 if (pConn->isAccepted())
374 if (pConn->getClientID() == iClientID)
375 if (pConn->getProtocol() ==
P_TCP || !pRes)
390 pConn->SetBroadcastTarget(fSelectAll);
401 bool fSuccess =
true;
405 if (pConn->isOpen() && pConn->isBroadcastTarget())
406 fSuccess &= pConn->Send(rPkt);
408 Log(
"Network: Warning! Broadcast failed.");
416 if (!pConn)
return false;
418 bool fSuccess = pConn->
Send(rPkt);
432 if (pConn->isAccepted())
434 if (pConn->getProtocol() ==
P_UDP)
435 pConn->SetBroadcastTarget(
true);
436 else if (pConn->getProtocol() ==
P_TCP)
440 pConn->SetBroadcastTarget(
true);
467 assert(!
"Unexpected address family");
508 #if(C4NET2IO_DUMP_LEVEL > 1)
515 if (!ConnectAddr.
IsNull())
543 #if(C4NET2IO_DUMP_LEVEL > 0)
564 #if(C4NET2IO_DUMP_LEVEL > 1)
573 #if(C4NET2IO_DUMP_LEVEL > 0)
593 #if C4NET2IO_DUMP_LEVEL > 1
596 #if(C4NET2IO_DUMP_LEVEL > 1)
606 if (!rPacket.
getSize())
return;
614 #if(C4NET2IO_DUMP_LEVEL > 2)
616 if (iFindConnectionBlocked > 100)
624 #if(C4NET2IO_DUMP_LEVEL > 1)
626 if (iHandlingBlocked > 100)
718 default:
return nullptr;
724 if (!pNetIO)
return "nullptr";
732 if (!pNetIO)
return P_NONE;
757 if (pAct->
pNext == pConn)
773 if (pConn->getNetClass() == pNetIO && pConn->getPeerAddr() == addr)
783 if (pConn->getNetClass() == pNetIO && pConn->getConnectAddr() == addr)
793 if (pConn->getID() == iConnID)
821 if (pConn->isAccepted() &&
834 if (!pConn)
return false;
859 #if(C4NET2IO_DUMP_LEVEL > 0)
874 bool fSendToMainThread =
false, fHandled =
false;
879 if (!pHData->ProcByThread == !fThread)
885 #if(C4NET2IO_DUMP_LEVEL > 2)
892 #if(C4NET2IO_DUMP_LEVEL > 2)
894 if (fThread && iBlockedTime > 100)
903 else if (!pHData->ProcByThread && fThread)
906 fSendToMainThread =
true;
911 if (fSendToMainThread)
923 if (!fHandled && !pConn->
isClosed())
984 #define GETPKT(type, name) \
985 assert(pPacket); const type &name = \
986 static_cast<const type &>(*pPacket);
993 if (!pConn->
isOpen())
break;
1016 if (!pConn->
isOpen())
break;
1037 if (!pConn->
isOpen())
break;
1049 if (!pConn->
isOpen())
break;
1135 ConnListLock.
Clear();
1152 ConnListLock.
Clear();
1174 bool fSuccess =
true;
1177 if (pConn->isOpen())
1179 C4PacketPing Ping(pConn->getInPacketCounter(), pConn->getOutPacketCounter());
1193 pNext = pConn->pNext;
1195 if (!pConn->isClosed() && !pConn->isAccepted())
1202 if (pConn->isAccepted())
1203 if ((pConn->getLag() != -1 ? pConn->getLag() : 1000 * difftime(time(
nullptr), pConn->getTimestamp()))
1211 if (pConn->isClosed())
1219 int iTCPIRateSum = 0, iTCPORateSum = 0, iUDPIRateSum = 0, iUDPORateSum = 0;
1224 if (pConn->isOpen())
1226 bool fTCP = pConn->getNetClass() ==
pNetIO_TCP;
1227 pConn->DoStatistics(iInterval, fTCP ? &iTCPIRateSum : &iUDPIRateSum,
1228 fTCP ? &iTCPORateSum : &iUDPORateSum);
1230 ConnListLock.
Clear();
1233 int inTCPBCRate = 0, inUDPBCRate = 0;
1238 iTCPIRateSum = iTCPIRateSum * 1000 / iInterval;
1239 iTCPORateSum = iTCPORateSum * 1000 / iInterval;
1240 iUDPIRateSum = iUDPIRateSum * 1000 / iInterval;
1241 iUDPORateSum = iUDPORateSum * 1000 / iInterval;
1242 inTCPBCRate = inTCPBCRate * 1000 / iInterval;
1243 inUDPBCRate = inUDPBCRate * 1000 / iInterval;
1262 if (pConn->isAccepted() || (!pConn->isClosed() && pConn->isConnSent()))
1268 if (pConn->isOpen() && !pConn->isConnSent())
1275 if (!pConn->Send(Pkt))
1280 pConn->SetConnSent();
1292 : iID(~0), iRemoteID(~0),
1405 if (pPos->
Number < iUntilID)
1424 if (!pPkt)
return false;
1435 pPkt->
Add(pEntry->Pkt);
1482 pLogEntry->
Pkt = rPkt;
1522 int inIRate, inORate, inLoss;
1529 inIRate = inIRate * 1000 / iInterval;
1530 inORate = inORate * 1000 / iInterval;
1534 if (pIRateSum) *pIRateSum +=
iIRate;
1535 if (pORateSum) *pORateSum +=
iORate;
1563 PacketLink *pDelete = pPackets;
1564 pPackets = pPackets->Next;
1573 if (!
Inside(iNumber, iPacketCounter - iPacketCount, iPacketCounter - 1))
1576 iNumber = iNumber + iPacketCount - iPacketCounter;
1578 PacketLink *pLink = pPackets;
1579 for (; pLink && iNumber; iNumber--)
1580 pLink = pLink->Next;
1582 return pLink ? &pLink->Pkt :
nullptr;
1587 iPacketCounter = inPacketCounter;
1593 PacketLink *pLink =
new PacketLink();
1595 pLink->Next = pPackets;
1613 for (uint32_t i = 0; i < iPacketCount; i++)
1616 PacketLink *pLink =
new PacketLink();
1617 pLink->Next = pPackets;
1623 PacketLink *pPackets2 = pPackets;
1628 PacketLink *pLink = pPackets2;
1629 pPackets2 = pLink->Next;
1631 pLink->Next = pPackets;
1638 for (PacketLink *pLink = pPackets; pLink; pLink = pLink->Next)
const int32_t C4ClientCoreDL_IDMatch
C4Application Application
bool Log(const char *szMessage)
bool LogSilentF(const char *strMessage,...)
bool LogF(const char *strMessage,...)
bool LogFatal(const char *szMessage)
#define GETPKT(type, name)
const int C4NetStatisticsFreq
const int C4NetPingTimeout
const int C4NetAcceptTimeout
const C4PktHandlingData PktHandlingData[]
C4NetIOPacket MkC4NetIOPacket(char cStatus, const class C4PacketBase &Pkt, const C4NetIO::addr_t &addr=C4NetIO::addr_t())
@ PH_C4Network2ClientList
@ PH_C4GameControlNetwork
bool Inside(T ival, U lbound, V rbound)
StdNamingAdapt< T > mkNamingAdapt(T &&rValue, const char *szName)
StdStrBuf FormatString(const char *szFmt,...)
C4InteractiveThread InteractiveThread
int32_t getDiffLevel(const C4ClientCore &CCore2) const
C4GameControlNetwork Network
void HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn)
C4PacketType getPktType() const
C4PacketBase * getPkt() const
void RemoveProc(StdSchedulerProc *pProc)
bool ThreadLog(const char *szMessage,...) GNUC_FORMAT_ATTRIBUTE_O
void ClearCallback(C4InteractiveEventType eEvent, Callback *pnNetworkCallback)
bool AddProc(StdSchedulerProc *pProc)
bool ThreadLogS(const char *szMessage,...) GNUC_FORMAT_ATTRIBUTE_O
bool PushEvent(C4InteractiveEventType eEventType, void *pData=nullptr)
void SetCallback(C4InteractiveEventType eEvent, Callback *pnNetworkCallback)
virtual void ClearStatistic()=0
virtual bool SetBroadcast(const addr_t &addr, bool fSet=true)=0
virtual void SetCallback(CBClass *pnCallback)=0
virtual const char * GetError() const
virtual bool Init(uint16_t iPort=addr_t::IPPORT_NONE)=0
virtual bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss)=0
virtual bool Send(const class C4NetIOPacket &rPacket)=0
virtual bool GetStatistic(int *pBroadcastRate)=0
virtual bool Connect(const addr_t &addr)=0
const C4NetIO::addr_t & getAddr() const
void SetAddr(const C4NetIO::addr_t &naddr)
C4NetIOPacket Duplicate() const
uint8_t getStatus() const
bool Init(uint16_t iPort=addr_t::IPPORT_NONE) override
bool Connect(const addr_t &addr, std::unique_ptr< Socket > socket)
C4NetIOPacket PackTo(const C4NetIO::addr_t &) const
static std::unique_ptr< C4NetpuncherPacket > Construct(const C4NetIOPacket &rpack)
void HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn)
C4Network2Players Players
void HandleLobbyPacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn)
C4Network2ResList ResList
void OnDisconn(C4Network2IOConnection *pConn)
void OnPuncherConnect(C4NetIO::addr_t addr)
bool HandlePuncherPacket(C4NetpuncherPacket::uptr, C4NetIO::HostAddress::AddressFamily family)
void HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn)
C4Network2ClientList Clients
void OnConn(C4Network2IOConnection *pConn)
void SetPeerAddr(const C4NetIO::addr_t &nPeerAddr)
uint32_t iInPacketCounter
void SetCCore(const C4ClientCore &nCCore)
C4Network2IOProtocol eProt
uint32_t getInPacketCounter() const
C4TimeMilliseconds tLastPong
const C4NetIO::addr_t & getPeerAddr() const
bool isHalfAccepted() const
bool Send(const C4NetIOPacket &rPkt)
void Set(C4NetIO *pnNetClass, C4Network2IOProtocol eProt, const C4NetIO::addr_t &nPeerAddr, const C4NetIO::addr_t &nConnectAddr, C4Network2IOConnStatus nStatus, const char *szPassword, uint32_t iID)
uint32_t iOutPacketCounter
void SetBroadcastTarget(bool fSet)
void SetRemoteID(uint32_t iRemoteID)
void ClearPacketLog(uint32_t iStartNumber=~0)
C4TimeMilliseconds tLastPing
C4NetIO::addr_t ConnectAddr
std::unique_ptr< C4NetIOTCP::Socket > TcpSimOpenSocket
C4Network2IOConnection * pNext
bool isAutoAccepted() const
C4Network2IOConnStatus Status
void SetSocket(std::unique_ptr< C4NetIOTCP::Socket > socket)
bool CreatePostMortem(class C4PacketPostMortem *pPkt)
void OnPacketReceived(uint8_t iPacketType)
void DoStatistics(int iInterval, int *pIRateSum, int *pORateSum)
bool isConnecting() const
~C4Network2IOConnection()
void SetStatus(C4Network2IOConnStatus nStatus)
void SetPingTime(int iPingTime)
PacketLogEntry * pPacketLog
class C4NetIO * pNetClass
void SetDiscoverable(bool fnEnabled)
bool Init(uint16_t iPort=C4NetIO::addr_t::IPPORT_NONE) override
void RemoveAutoAccept(const C4ClientCore &CCore)
bool SendMsgToClient(C4NetIOPacket &rPkt, int iClient)
class C4Network2RefServer * pRefServer
bool ConnectWithSocket(const C4NetIO::addr_t &addr, C4Network2IOProtocol eProt, const C4ClientCore &nCCore, std::unique_ptr< C4NetIOTCP::Socket > socket, const char *szPassword=nullptr)
void SetLocalCCore(const C4ClientCore &CCore)
void OnDisconn(const C4NetIO::addr_t &addr, C4NetIO *pNetIO, const char *szReason) override
void HandlePuncherPacket(const C4NetIOPacket &rPacket)
C4Network2IOConnection * pConnList
bool Execute(int iTimeout, pollfd *) override
void BeginBroadcast(bool fSelectAll=false)
bool doAutoAccept(const C4ClientCore &CCore, const C4Network2IOConnection &Conn)
void HandleFwdReq(const class C4PacketFwd &rFwd, C4Network2IOConnection *pBy)
void CallHandlers(int iHandlers, const class C4IDPacket *pPacket, C4Network2IOConnection *pConn, bool fThread)
C4TimeMilliseconds tLastExecute
C4TimeMilliseconds tLastPing
void RemoveConnection(C4Network2IOConnection *pConn)
C4Network2IOProtocol getNetIOProt(C4NetIO *pNetIO)
C4Network2IOConnection * GetConnectionByID(uint32_t iConnID)
C4Network2IOConnection * Conn
class C4Network2IODiscover * pNetIODiscover
bool BroadcastMsg(const C4NetIOPacket &rPkt)
void SendPuncherPacket(const C4NetpuncherPacket &, C4NetIO::HostAddress::AddressFamily family)
C4TimeMilliseconds GetNextTick(C4TimeMilliseconds tNow) override
class C4Network2UPnP * UPnPMgr
C4TimeMilliseconds tLastStatistic
bool IsPuncherAddr(const C4NetIO::addr_t &addr) const
virtual void OnError(const char *strError, C4NetIO *pNetIO)
bool HandlePacket(const C4NetIOPacket &rPacket, C4Network2IOConnection *pConn, bool fThread)
C4Network2IOConnection * GetMsgConnection(int iClientID)
C4NetIO::addr_t PuncherAddrIPv4
bool InitPuncher(C4NetIO::addr_t PuncherAddr)
void SetReference(class C4Network2Reference *pReference)
bool Connect(const C4NetIO::addr_t &addr, C4Network2IOProtocol eProt, const C4ClientCore &nCCore, const char *szPassword=nullptr)
void GenerateStatistics(int iInterval)
void SetAcceptMode(bool fAcceptAll)
bool Broadcast(const C4NetIOPacket &rPkt)
C4Network2IOConnection * GetConnection(const C4NetIO::addr_t &addr, C4NetIO *pNetIO)
C4NetIO::addr_t PuncherAddrIPv6
C4Network2IOConnection * GetDataConnection(int iClientID)
void Punch(const C4NetIO::addr_t &)
bool OnConn(const C4NetIO::addr_t &addr, const C4NetIO::addr_t &AddrConnect, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO) override
C4Network2IOConnection * GetConnectionByConnAddr(const C4NetIO::addr_t &addr, C4NetIO *pNetIO)
C4NetIO * getNetIO(C4Network2IOProtocol eProt)
void AddAutoAccept(const C4ClientCore &CCore)
void AddConnection(C4Network2IOConnection *pConn)
const char * getNetIOName(C4NetIO *pNetIO)
void OnThreadEvent(C4InteractiveEventType eEvent, void *pEventData) override
void SetExclusiveConnMode(bool fExclusiveConn)
bool Init(int16_t iPortTCP, int16_t iPortUDP, int16_t iPortDiscovery=-1, int16_t iPortRefServer=-1, bool fBroadcast=false, bool enable_upnp=true)
void OnPacket(const C4NetIOPacket &rPacket, C4NetIO *pNetIO) override
void HandlePacket(char cStatus, const C4PacketBase *pPacket, class C4Network2IOConnection *pConn)
void SetReference(C4Network2Reference *pReference)
void HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn)
void AddMapping(enum C4Network2IOProtocol protocol, uint16_t intport, uint16_t extport)
void unpack(const C4NetIOPacket &Pkt, char *pStatus=nullptr)
bool DoFwdTo(int32_t iClient) const
const StdCopyBuf & getData() const
int32_t getClientCnt() const
int32_t getClient(int32_t i) const
void SetData(const StdBuf &Pkt)
void AddClient(int32_t iClient)
void SetListType(bool fnNegativeList)
void CompileFunc(StdCompiler *pComp) override
void SetConnID(uint32_t inConnID)
void Add(const C4NetIOPacket &rPkt)
void SetPacketCounter(uint32_t iPacketCounter)
const C4NetIOPacket * getPacket(uint32_t iNumber) const
~C4PacketPostMortem() override
static C4TimeMilliseconds Now()
void Take(void *pnData, size_t inSize)
void Value(const T &rStruct)
virtual bool isDeserializer()
const char * getData() const
StdStrBuf ToString(int flags=0) const
HostAddress GetHost() const
AddressFamily GetFamily() const