diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index b83a68639..b8e16c804 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -445,7 +445,29 @@ void CServerBrowser::RemoveRequest(CServerEntry *pEntry) } } -void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) const +void CServerBrowser::CBFTrackPacket(int TrackID, void *pCallbackUser) +{ + if(!pCallbackUser) + return; + + CServerBrowser *pSelf = (CServerBrowser *)pCallbackUser; + CServerEntry *pEntry = pSelf->m_pFirstReqServer; + while(1) + { + if(!pEntry) // no more entries + break; + + if(pEntry->m_TrackID == TrackID) // got it -> update + { + pEntry->m_RequestTime = time_get(); + break; + } + + pEntry = pEntry->m_pNextReq; + } +} + +void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) { if(g_Config.m_Debug) { @@ -467,8 +489,11 @@ void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) cons Packet.m_Flags = NETSENDFLAG_CONNLESS; Packet.m_DataSize = Packer.Size(); Packet.m_pData = Packer.Data(); - - m_pNetClient->Send(&Packet); + CSendCBData Data; + Data.m_pfnCallback = CBFTrackPacket; + Data.m_pCallbackUser = this; + m_pNetClient->Send(&Packet, NET_TOKEN_NONE, &Data); + pEntry->m_TrackID = Data.m_TrackID; if(pEntry) { diff --git a/src/engine/client/serverbrowser.h b/src/engine/client/serverbrowser.h index e8860206b..7e7bb94b0 100644 --- a/src/engine/client/serverbrowser.h +++ b/src/engine/client/serverbrowser.h @@ -47,6 +47,8 @@ public: void GetFilter(int Index, CServerFilterInfo *pFilterInfo) { m_ServerBrowserFilter.GetFilter(Index, pFilterInfo); }; void RemoveFilter(int Index) { m_ServerBrowserFilter.RemoveFilter(Index); }; + static void CBFTrackPacket(int TrackID, void *pUser); + private: class CNetClient *m_pNetClient; class IConsole *m_pConsole; @@ -88,7 +90,7 @@ private: CServerEntry *Find(int ServerlistType, const NETADDR &Addr); void QueueRequest(CServerEntry *pEntry); void RemoveRequest(CServerEntry *pEntry); - void RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) const; + void RequestImpl(const NETADDR &Addr, CServerEntry *pEntry); void SetInfo(int ServerlistType, CServerEntry *pEntry, const CServerInfo &Info); }; diff --git a/src/engine/client/serverbrowser_entry.h b/src/engine/client/serverbrowser_entry.h index 169b3f27e..5fe82f90d 100644 --- a/src/engine/client/serverbrowser_entry.h +++ b/src/engine/client/serverbrowser_entry.h @@ -17,6 +17,7 @@ public: int64 m_RequestTime; int m_InfoState; int m_CurrentToken; // the token is to keep server refresh separated from each other + int m_TrackID; class CServerInfo m_Info; CServerEntry *m_pNextIp; // ip hashed list diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 18519d850..a89f74e58 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -201,6 +201,13 @@ private: int64 m_NextSeedTime; }; +typedef void(*FSendCallback)(int TrackID, void *pUser); +struct CSendCBData +{ + FSendCallback m_pfnCallback; + void *m_pCallbackUser; + int m_TrackID; +}; class CNetTokenCache { @@ -208,20 +215,28 @@ public: CNetTokenCache(); ~CNetTokenCache(); void Init(NETSOCKET Socket, const CNetTokenManager *pTokenManager); - void SendPacketConnless(const NETADDR *pAddr, const void *pData, int DataSize); + void SendPacketConnless(const NETADDR *pAddr, const void *pData, int DataSize, CSendCBData *pCallbackData = 0); void FetchToken(const NETADDR *pAddr); void AddToken(const NETADDR *pAddr, TOKEN PeerToken); TOKEN GetToken(const NETADDR *pAddr); void Update(); private: - struct CConnlessPacketInfo + class CConnlessPacketInfo { + private: + static int m_UniqueID; + + public: + CConnlessPacketInfo() : m_TrackID(CConnlessPacketInfo::m_UniqueID++) {} + NETADDR m_Addr; int m_DataSize; char m_aData[NET_MAX_PAYLOAD]; int64 m_Expiry; - + const int m_TrackID; + FSendCallback m_pfnCallback; + void *m_pCallbackUser; CConnlessPacketInfo *m_pNext; }; @@ -483,7 +498,7 @@ public: // communication int Recv(CNetChunk *pChunk, TOKEN *pResponseToken = 0); - int Send(CNetChunk *pChunk, TOKEN Token = NET_TOKEN_NONE); + int Send(CNetChunk *pChunk, TOKEN Token = NET_TOKEN_NONE, CSendCBData *pCallbackData = 0); // pumping int Update(); diff --git a/src/engine/shared/network_client.cpp b/src/engine/shared/network_client.cpp index 9d9911df2..5ebf0fb94 100644 --- a/src/engine/shared/network_client.cpp +++ b/src/engine/shared/network_client.cpp @@ -117,7 +117,7 @@ int CNetClient::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) return 0; } -int CNetClient::Send(CNetChunk *pChunk, TOKEN Token) +int CNetClient::Send(CNetChunk *pChunk, TOKEN Token, CSendCBData *pCallbackData) { if(pChunk->m_Flags&NETSENDFLAG_CONNLESS) { @@ -142,7 +142,7 @@ int CNetClient::Send(CNetChunk *pChunk, TOKEN Token) { if(pChunk->m_ClientID == -1) { - m_TokenCache.SendPacketConnless(&pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize); + m_TokenCache.SendPacketConnless(&pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize, pCallbackData); } else { diff --git a/src/engine/shared/network_token.cpp b/src/engine/shared/network_token.cpp index 8366cd22a..19cc9b5cd 100644 --- a/src/engine/shared/network_token.cpp +++ b/src/engine/shared/network_token.cpp @@ -20,6 +20,8 @@ static unsigned int Hash(char *pData, int Size) return (aDigest[0] ^ aDigest[1] ^ aDigest[2] ^ aDigest[3]); } +int CNetTokenCache::CConnlessPacketInfo::m_UniqueID = 0; + void CNetTokenManager::Init(NETSOCKET Socket, int SeedTime) { m_Socket = Socket; @@ -167,7 +169,7 @@ void CNetTokenCache::Init(NETSOCKET Socket, const CNetTokenManager *pTokenManage m_pTokenManager = pTokenManager; } -void CNetTokenCache::SendPacketConnless(const NETADDR *pAddr, const void *pData, int DataSize) +void CNetTokenCache::SendPacketConnless(const NETADDR *pAddr, const void *pData, int DataSize, CSendCBData *pCallbackData) { TOKEN Token = GetToken(pAddr); if(Token != NET_TOKEN_NONE) @@ -189,6 +191,17 @@ void CNetTokenCache::SendPacketConnless(const NETADDR *pAddr, const void *pData, (*ppInfo)->m_DataSize = DataSize; (*ppInfo)->m_Expiry = time_get() + time_freq() * NET_TOKENCACHE_PACKETEXPIRY; (*ppInfo)->m_pNext = 0; + if(pCallbackData) + { + (*ppInfo)->m_pfnCallback = pCallbackData->m_pfnCallback; + (*ppInfo)->m_pCallbackUser = pCallbackData->m_pCallbackUser; + pCallbackData->m_TrackID = (*ppInfo)->m_TrackID; + } + else + { + (*ppInfo)->m_pfnCallback = 0; + (*ppInfo)->m_pCallbackUser = 0; + } } } @@ -235,6 +248,10 @@ void CNetTokenCache::AddToken(const NETADDR *pAddr, TOKEN Token) NullAddr.port = pAddr->port; if(net_addr_comp(&pInfo->m_Addr, pAddr) == 0 || net_addr_comp(&pInfo->m_Addr, &NullAddr) == 0) { + // notify the user that the packet gets delivered + if(pInfo->m_pfnCallback) + pInfo->m_pfnCallback(pInfo->m_TrackID, pInfo->m_pCallbackUser); + CNetBase::SendPacketConnless(m_Socket, pAddr, Token, m_pTokenManager->GenerateToken(pAddr), pInfo->m_aData, pInfo->m_DataSize);