void CNetTokenCache::AddToken(const NETADDR *pAddr, TOKEN Token) { if(Token == NET_TOKEN_NONE) return; CAddressInfo Info; Info.m_Addr = *pAddr; Info.m_Token = Token; Info.m_Expiry = time_get() + time_freq() * NET_TOKENCACHE_ADDRESSEXPIRY; (*m_TokenCache.Allocate(sizeof(Info))) = Info; // search the list of packets to be sent // for this address CConnlessPacketInfo *pPrevInfo = 0; CConnlessPacketInfo *pInfo = m_pConnlessPacketList; while(pInfo) { static NETADDR NullAddr = { 0 }; NullAddr.type = 7; // cover broadcasts 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); // todo: make sure if we got the result of a broadcast or not CNetBase::SendPacketConnless(m_Socket, &(pInfo->m_Addr), Token, m_pTokenManager->GenerateToken(pAddr), pInfo->m_aData, pInfo->m_DataSize); CConnlessPacketInfo *pNext = pInfo->m_pNext; if(pPrevInfo) pPrevInfo->m_pNext = pNext; if(pInfo == m_pConnlessPacketList) m_pConnlessPacketList = pNext; delete pInfo; pInfo = pNext; } else { if(pPrevInfo) pPrevInfo = pPrevInfo->m_pNext; else pPrevInfo = pInfo; pInfo = pInfo->m_pNext; } } }
bool CNetServer::Connlimit(NETADDR Addr) { int64 Now = time_get(); int Oldest = 0; for(int i = 0; i < NET_CONNLIMIT_IPS; ++i) { if(!net_addr_comp(&m_aSpamConns[i].m_Addr, &Addr)) { if(m_aSpamConns[i].m_Time > Now - time_freq() * g_Config.m_SvConnlimitTime) { if(m_aSpamConns[i].m_Conns >= g_Config.m_SvConnlimit) return true; } else { m_aSpamConns[i].m_Time = Now; m_aSpamConns[i].m_Conns = 0; } m_aSpamConns[i].m_Conns++; return false; } if(m_aSpamConns[i].m_Time < m_aSpamConns[Oldest].m_Time) Oldest = i; } m_aSpamConns[Oldest].m_Addr = Addr; m_aSpamConns[Oldest].m_Time = Now; m_aSpamConns[Oldest].m_Conns = 1; return false; }
void AddServer(NETADDR *pInfo) { // see if server already exists in list int i; for(i = 0; i < m_NumServers; i++) { if(net_addr_comp(&m_aServers[i].m_Address, pInfo) == 0) { dbg_msg("mastersrv", "updated: %d.%d.%d.%d:%d", pInfo->ip[0], pInfo->ip[1], pInfo->ip[2], pInfo->ip[3], pInfo->port); m_aServers[i].m_Expire = time_get()+time_freq()*EXPIRE_TIME; return; } } // add server if(m_NumServers == MAX_SERVERS) { dbg_msg("mastersrv", "error: mastersrv is full"); return; } dbg_msg("mastersrv", "added: %d.%d.%d.%d:%d", pInfo->ip[0], pInfo->ip[1], pInfo->ip[2], pInfo->ip[3], pInfo->port); m_aServers[m_NumServers].m_Address = *pInfo; m_aServers[m_NumServers].m_Expire = time_get()+time_freq()*EXPIRE_TIME; m_NumServers++; }
void CServerBrowser::AddFavorite(const NETADDR &Addr) { CServerEntry *pEntry; if(m_NumFavoriteServers == MAX_FAVORITES) return; // make sure that we don't already have the server in our list for(int i = 0; i < m_NumFavoriteServers; i++) { if(net_addr_comp(&Addr, &m_aFavoriteServers[i]) == 0) return; } // add the server to the list m_aFavoriteServers[m_NumFavoriteServers++] = Addr; pEntry = Find(Addr); if(pEntry) pEntry->m_Info.m_Favorite = 1; if(g_Config.m_Debug) { char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr), true); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "added fav, %s", aAddrStr); m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", aBuf); } }
int CNetServer::BanmasterCheck(NETADDR *pAddr) { for(int i = 0; i < m_NumBanmasters; i++) if(net_addr_comp(&m_aBanmasters[i], pAddr) == 0) return i; return -1; }
CServerEntry *CServerBrowser::Find(int ServerlistType, const NETADDR &Addr) { for(CServerEntry *pEntry = m_aServerlist[ServerlistType].m_aServerlistIp[AddrHash(&Addr)]; pEntry; pEntry = pEntry->m_pNextIp) { if(net_addr_comp(&pEntry->m_Addr, &Addr) == 0) return pEntry; } return (CServerEntry*)0; }
int CNetClient::Send(CNetChunk *pChunk, TOKEN Token, CSendCBData *pCallbackData) { if(pChunk->m_Flags&NETSENDFLAG_CONNLESS) { if(pChunk->m_DataSize >= NET_MAX_PAYLOAD) { dbg_msg("netserver", "packet payload too big. %d. dropping packet", pChunk->m_DataSize); return -1; } if(pChunk->m_ClientID == -1 && net_addr_comp(&pChunk->m_Address, m_Connection.PeerAddress()) == 0) { // upgrade the packet, now that we know its recipent pChunk->m_ClientID = 0; } if(Token != NET_TOKEN_NONE) { CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, Token, m_TokenManager.GenerateToken(&pChunk->m_Address), pChunk->m_pData, pChunk->m_DataSize); } else { if(pChunk->m_ClientID == -1) { m_TokenCache.SendPacketConnless(&pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize, pCallbackData); } else { dbg_assert(pChunk->m_ClientID == 0, "errornous client id"); m_Connection.SendPacketConnless((const char *)pChunk->m_pData, pChunk->m_DataSize); } } } else { if(pChunk->m_DataSize+NET_MAX_CHUNKHEADERSIZE >= NET_MAX_PAYLOAD) { dbg_msg("netclient", "chunk payload too big. %d. dropping chunk", pChunk->m_DataSize); return -1; } int Flags = 0; dbg_assert(pChunk->m_ClientID == 0, "errornous client id"); if(pChunk->m_Flags&NETSENDFLAG_VITAL) Flags = NET_CHUNKFLAG_VITAL; m_Connection.QueueChunk(Flags, pChunk->m_DataSize, pChunk->m_pData); if(pChunk->m_Flags&NETSENDFLAG_FLUSH) m_Connection.Flush(); } return 0; }
bool CServerBrowser::IsFavorite(const NETADDR &Addr) const { // search for the address int i; for(i = 0; i < m_NumFavoriteServers; i++) { if(net_addr_comp(&Addr, &m_aFavoriteServers[i]) == 0) return true; } return false; }
CServerBrowser::CServerEntry *CServerBrowser::Find(const NETADDR &Addr) { CServerEntry *pEntry = m_aServerlistIp[Addr.ip[0]]; for(; pEntry; pEntry = pEntry->m_pNextIp) { if(net_addr_comp(&pEntry->m_Addr, &Addr) == 0) return pEntry; } return (CServerEntry*)0; }
CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR &Addr) { int Hash = Addr.ip[0]; CServerEntry *pEntry = 0; int i; // create new pEntry pEntry = (CServerEntry *)m_ServerlistHeap.Allocate(sizeof(CServerEntry)); mem_zero(pEntry, sizeof(CServerEntry)); // set the info pEntry->m_Addr = Addr; pEntry->m_Info.m_NetAddr = Addr; pEntry->m_Info.m_Latency = 999; str_format(pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aAddress), "%d.%d.%d.%d:%d", Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], Addr.port); str_format(pEntry->m_Info.m_aName, sizeof(pEntry->m_Info.m_aName), "\255%d.%d.%d.%d:%d", // the \255 is to make sure that it's sorted last Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], Addr.port); /*if(serverlist_type == IServerBrowser::TYPE_LAN) pEntry->m_Info.latency = (time_get()-broadcast_time)*1000/time_freq();*/ // check if it's a favorite for(i = 0; i < m_NumFavoriteServers; i++) { if(net_addr_comp(&Addr, &m_aFavoriteServers[i]) == 0) pEntry->m_Info.m_Favorite = 1; } // add to the hash list pEntry->m_pNextIp = m_aServerlistIp[Hash]; m_aServerlistIp[Hash] = pEntry; if(m_NumServers == m_NumServerCapacity) { CServerEntry **ppNewlist; m_NumServerCapacity += 100; ppNewlist = (CServerEntry **)mem_alloc(m_NumServerCapacity*sizeof(CServerEntry*), 1); mem_copy(ppNewlist, m_ppServerlist, m_NumServers*sizeof(CServerEntry*)); mem_free(m_ppServerlist); m_ppServerlist = ppNewlist; } // add to list m_ppServerlist[m_NumServers] = pEntry; pEntry->m_Info.m_ServerIndex = m_NumServers; m_NumServers++; return pEntry; }
int CRegister::RegisterProcessPacket(CNetChunk *pPacket) { // check for masterserver address bool Valid = false; NETADDR Addr1 = pPacket->m_Address; Addr1.port = 0; for(int i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++) { NETADDR Addr2 = m_aMasterserverInfo[i].m_Addr; Addr2.port = 0; if(net_addr_comp(&Addr1, &Addr2) == 0) { Valid = true; break; } } if(!Valid) return 0; if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWCHECK) && mem_comp(pPacket->m_pData, SERVERBROWSE_FWCHECK, sizeof(SERVERBROWSE_FWCHECK)) == 0) { RegisterSendFwcheckresponse(&pPacket->m_Address); return 1; } else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWOK) && mem_comp(pPacket->m_pData, SERVERBROWSE_FWOK, sizeof(SERVERBROWSE_FWOK)) == 0) { if(m_RegisterFirst) m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", "no firewall/nat problems detected"); RegisterNewState(REGISTERSTATE_REGISTERED); return 1; } else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWERROR) && mem_comp(pPacket->m_pData, SERVERBROWSE_FWERROR, sizeof(SERVERBROWSE_FWERROR)) == 0) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", "ERROR: the master server reports that clients can not connect to this server."); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "ERROR: configure your firewall/nat to let through udp on port %d.", g_Config.m_SvPort); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", aBuf); RegisterNewState(REGISTERSTATE_ERROR); return 1; } else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_COUNT)+2 && mem_comp(pPacket->m_pData, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT)) == 0) { RegisterGotCount(pPacket); return 1; } return 0; }
TOKEN CNetTokenCache::GetToken(const NETADDR *pAddr) { // traverse the list in the reverse direction // newest caches are the best CAddressInfo *pInfo = m_TokenCache.Last(); while(pInfo) { if(net_addr_comp(&pInfo->m_Addr, pAddr) == 0) return pInfo->m_Token; pInfo = m_TokenCache.Prev(pInfo); } return NET_TOKEN_NONE; }
void CNetTokenCache::AddToken(const NETADDR *pAddr, TOKEN Token, int TokenFLag) { if(Token == NET_TOKEN_NONE) return; // search the list of packets to be sent // for this address CConnlessPacketInfo *pPrevInfo = 0; CConnlessPacketInfo *pInfo = m_pConnlessPacketList; bool Found = false; while(pInfo) { static NETADDR NullAddr = { 0 }; NullAddr.type = 7; // cover broadcasts NullAddr.port = pAddr->port; if(net_addr_comp(&pInfo->m_Addr, pAddr) == 0 || ((TokenFLag&NET_TOKENFLAG_ALLOWBROADCAST) && 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, &(pInfo->m_Addr), Token, m_pTokenManager->GenerateToken(pAddr), pInfo->m_aData, pInfo->m_DataSize); CConnlessPacketInfo *pNext = pInfo->m_pNext; if(pPrevInfo) pPrevInfo->m_pNext = pNext; if(pInfo == m_pConnlessPacketList) m_pConnlessPacketList = pNext; delete pInfo; pInfo = pNext; } else { if(pPrevInfo) pPrevInfo = pPrevInfo->m_pNext; else pPrevInfo = pInfo; pInfo = pInfo->m_pNext; } } // add the token if(Found || !(TokenFLag&NET_TOKENFLAG_RESPONSEONLY)) { CAddressInfo Info; Info.m_Addr = *pAddr; Info.m_Token = Token; Info.m_Expiry = time_get() + time_freq() * NET_TOKENCACHE_ADDRESSEXPIRY; (*m_TokenCache.Allocate(sizeof(Info))) = Info; } }
void CRegister::RegisterGotCount(CNetChunk *pChunk) { unsigned char *pData = (unsigned char *)pChunk->m_pData; int Count = (pData[sizeof(SERVERBROWSE_COUNT)]<<8) | pData[sizeof(SERVERBROWSE_COUNT)+1]; for(int i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++) { if(net_addr_comp(&m_aMasterserverInfo[i].m_Addr, &pChunk->m_Address) == 0) { m_aMasterserverInfo[i].m_Count = Count; break; } } }
CServerBrowserFavorites::CFavoriteServer *CServerBrowserFavorites::FindFavoriteByAddr(const NETADDR &Addr, int *Index) { for(int i = 0; i < m_NumFavoriteServers; i++) { if(m_aFavoriteServers[i].m_State >= FAVSTATE_ADDR && net_addr_comp(&Addr, &m_aFavoriteServers[i].m_Addr) == 0) { if(Index) *Index = i; return &m_aFavoriteServers[i]; } } return 0; }
int netserver_ban_remove(NETSERVER *s, NETADDR addr) { int iphash = (addr.ip[0]+addr.ip[1]+addr.ip[2]+addr.ip[3])&0xff; NETBAN *ban = s->bans[iphash]; MACRO_LIST_FIND(ban, hashnext, net_addr_comp(&ban->info.addr, &addr) == 0); if(ban) { netserver_ban_remove_by_object(s, ban); return 0; } return -1; }
static void register_got_count(NETCHUNK *p) { unsigned char *data = (unsigned char *)p->data; int count = (data[sizeof(SERVERBROWSE_COUNT)]<<8) | data[sizeof(SERVERBROWSE_COUNT)+1]; int i; for(i = 0; i < MAX_MASTERSERVERS; i++) { if(net_addr_comp(&masterserver_info[i].addr, &p->address) == 0) { masterserver_info[i].count = count; break; } } }
int CNetServer::BanRemove(NETADDR Addr) { int IpHash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3]+Addr.ip[4]+Addr.ip[5]+Addr.ip[6]+Addr.ip[7]+ Addr.ip[8]+Addr.ip[9]+Addr.ip[10]+Addr.ip[11]+Addr.ip[12]+Addr.ip[13]+Addr.ip[14]+Addr.ip[15])&0xff; CBan *pBan = m_aBans[IpHash]; MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0); if(pBan) { BanRemoveByObject(pBan); return 0; } return -1; }
int CNetServer::BanmasterCheck(NETADDR *pAddr, unsigned char *SequenceNumber) { int64 Timeout = time_freq(); int64 Now = time_get(); for(int i = 0; i < m_NumBanmasters; i++) { if(net_addr_comp(&m_aBanmasters[i], pAddr) == 0 && (mem_comp(m_aSequenceNumbers[i], SequenceNumber, NET_BANMASTER_NR_SIZE) == 0) && (m_aTimeouts[i] && m_aTimeouts[i]+Timeout > Now)) { return i; } } return -1; }
bool CServerBrowserFavorites::AddFavoriteEx(const char *pHostname, const NETADDR *pAddr, bool DoCheck) { if(m_NumFavoriteServers == MAX_FAVORITES || FindFavoriteByHostname(pHostname, 0)) return false; bool Result = false; // check if hostname is a net address string if(net_addr_from_str(&m_aFavoriteServers[m_NumFavoriteServers].m_Addr, pHostname) == 0) { // make sure that we don't already have the server in our list if(FindFavoriteByAddr(m_aFavoriteServers[m_NumFavoriteServers].m_Addr, 0) != 0) return false; // check if hostname does not match given address if(DoCheck && net_addr_comp(&m_aFavoriteServers[m_NumFavoriteServers].m_Addr, pAddr) != 0) return false; // add the server to the list m_aFavoriteServers[m_NumFavoriteServers].m_State = FAVSTATE_ADDR; Result = true; } else { // prepare for hostname lookup if(DoCheck) { m_aFavoriteServers[m_NumFavoriteServers].m_State = FAVSTATE_LOOKUPCHECK; m_aFavoriteServers[m_NumFavoriteServers].m_Addr = *pAddr; } else m_aFavoriteServers[m_NumFavoriteServers].m_State = FAVSTATE_LOOKUP; ++m_FavLookup.m_LookupCount; } str_copy(m_aFavoriteServers[m_NumFavoriteServers].m_aHostname, pHostname, sizeof(m_aFavoriteServers[m_NumFavoriteServers].m_aHostname)); ++m_NumFavoriteServers; if(g_Config.m_Debug) { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "added fav '%s' (%s)", pHostname); m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", aBuf); } return Result; }
CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR &Addr) { int Hash = Addr.ip[0]; CServerEntry *pEntry = 0; int i; // create new pEntry pEntry = (CServerEntry *)m_ServerlistHeap.Allocate(sizeof(CServerEntry)); mem_zero(pEntry, sizeof(CServerEntry)); // set the info pEntry->m_Addr = Addr; pEntry->m_Info.m_NetAddr = Addr; pEntry->m_Info.m_Latency = 999; net_addr_str(&Addr, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aAddress), true); str_copy(pEntry->m_Info.m_aName, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aName)); // check if it's a favorite for(i = 0; i < m_NumFavoriteServers; i++) { if(net_addr_comp(&Addr, &m_aFavoriteServers[i]) == 0) pEntry->m_Info.m_Favorite = 1; } // add to the hash list pEntry->m_pNextIp = m_aServerlistIp[Hash]; m_aServerlistIp[Hash] = pEntry; if(m_NumServers == m_NumServerCapacity) { CServerEntry **ppNewlist; m_NumServerCapacity += 100; ppNewlist = (CServerEntry **)mem_alloc(m_NumServerCapacity*sizeof(CServerEntry*), 1); mem_copy(ppNewlist, m_ppServerlist, m_NumServers*sizeof(CServerEntry*)); mem_free(m_ppServerlist); m_ppServerlist = ppNewlist; } // add to list m_ppServerlist[m_NumServers] = pEntry; pEntry->m_Info.m_ServerIndex = m_NumServers; m_NumServers++; return pEntry; }
void CServerBrowser::RemoveFavorite(const NETADDR &Addr) { int i; CServerEntry *pEntry; for(i = 0; i < m_NumFavoriteServers; i++) { if(net_addr_comp(&Addr, &m_aFavoriteServers[i]) == 0) { mem_move(&m_aFavoriteServers[i], &m_aFavoriteServers[i+1], sizeof(NETADDR)*(m_NumFavoriteServers-(i+1))); m_NumFavoriteServers--; pEntry = Find(Addr); if(pEntry) pEntry->m_Info.m_Favorite = 0; return; } } }
int CNetConsole::AcceptClient(NETSOCKET Socket, const NETADDR *pAddr) { char aError[256] = { 0 }; int FreeSlot = -1; // look for free slot or multiple client for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++) { if(FreeSlot == -1 && m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) FreeSlot = i; if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE) { if(net_addr_comp(pAddr, m_aSlots[i].m_Connection.PeerAddress()) == 0) { str_copy(aError, "only one client per IP allowed", sizeof(aError)); break; } } } // accept client if(!aError[0] && FreeSlot != -1) { m_aSlots[FreeSlot].m_Connection.Init(Socket, pAddr); if(m_pfnNewClient) m_pfnNewClient(FreeSlot, m_UserPtr); return 0; } // reject client if(!aError[0]) str_copy(aError, "no free slot available", sizeof(aError)); net_tcp_send(Socket, aError, str_length(aError)); net_tcp_close(Socket); return -1; }
int CNetServer::NumClientsWithAddr(NETADDR Addr) { NETADDR ThisAddr = Addr, OtherAddr; int FoundAddr = 0; ThisAddr.port = 0; for(int i = 0; i < MaxClients(); ++i) { if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE || (m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ERROR && (!m_aSlots[i].m_Connection.m_TimeoutProtected || !m_aSlots[i].m_Connection.m_TimeoutSituation))) continue; OtherAddr = *m_aSlots[i].m_Connection.PeerAddress(); OtherAddr.port = 0; if(!net_addr_comp(&ThisAddr, &OtherAddr)) FoundAddr++; } return FoundAddr; }
void CServerBrowser::AddFavorite(const NETADDR &Addr) { CServerEntry *pEntry; if(m_NumFavoriteServers == MAX_FAVORITES) return; // make sure that we don't already have the server in our list for(int i = 0; i < m_NumFavoriteServers; i++) { if(net_addr_comp(&Addr, &m_aFavoriteServers[i]) == 0) return; } // add the server to the list m_aFavoriteServers[m_NumFavoriteServers++] = Addr; pEntry = Find(Addr); if(pEntry) pEntry->m_Info.m_Favorite = 1; if(g_Config.m_Debug) dbg_msg("", "added fav, %d.%d.%d.%d:%d", Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], Addr.port); }
void CGameContext::Mute(IConsole::IResult *pResult, NETADDR *Addr, int Secs, const char *pDisplayName) { char aBuf[128]; int Found = 0; // find a matching mute for this ip, update expiration time if found for (int i = 0; i < m_NumMutes; i++) { if (net_addr_comp(&m_aMutes[i].m_Addr, Addr) == 0) { m_aMutes[i].m_Expire = Server()->Tick() + Secs * Server()->TickSpeed(); Found = 1; } } if (!Found) // nothing found so far, find a free slot.. { if (m_NumMutes < MAX_MUTES) { m_aMutes[m_NumMutes].m_Addr = *Addr; m_aMutes[m_NumMutes].m_Expire = Server()->Tick() + Secs * Server()->TickSpeed(); m_NumMutes++; Found = 1; } } if (Found) { str_format(aBuf, sizeof aBuf, "'%s' has been muted for %d seconds.", pDisplayName, Secs); SendChat(-1, CHAT_ALL, aBuf); } else // no free slot found Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "mutes", "mute array is full"); }
/* TODO: chopp up this function into smaller working parts */ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken) { while(1) { NETADDR Addr; // check for a chunk if(m_RecvUnpacker.FetchChunk(pChunk)) return 1; // TODO: empty the recvinfo int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE); // no more packets for now if(Bytes <= 0) break; if(CNetBase::UnpackPacket(m_RecvUnpacker.m_aBuffer, Bytes, &m_RecvUnpacker.m_Data) == 0) { // check for bans char aBuf[128]; if(NetBan() && NetBan()->IsBanned(&Addr, aBuf, sizeof(aBuf))) { // banned, reply with a message CNetBase::SendControlMsg(m_Socket, &Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf)+1); continue; } bool Found = false; // try to find matching slot for(int i = 0; i < MaxClients(); i++) { if(net_addr_comp(m_aSlots[i].m_Connection.PeerAddress(), &Addr) == 0) { if(m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr)) { if(m_RecvUnpacker.m_Data.m_DataSize) { if(!(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONNLESS)) m_RecvUnpacker.Start(&Addr, &m_aSlots[i].m_Connection, i); else { pChunk->m_Flags = NETSENDFLAG_CONNLESS; pChunk->m_Address = *m_aSlots[i].m_Connection.PeerAddress(); pChunk->m_ClientID = i; pChunk->m_DataSize = m_RecvUnpacker.m_Data.m_DataSize; pChunk->m_pData = m_RecvUnpacker.m_Data.m_aChunkData; if(pResponseToken) *pResponseToken = NET_TOKEN_NONE; return 1; } } } Found = true; } } if(Found) continue; int Accept = m_TokenManager.ProcessMessage(&Addr, &m_RecvUnpacker.m_Data); if(Accept <= 0) continue; if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONTROL) { if(m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_CONNECT) { bool Found = false; // only allow a specific number of players with the same ip NETADDR ThisAddr = Addr, OtherAddr; int FoundAddr = 1; ThisAddr.port = 0; for(int i = 0; i < MaxClients(); i++) { if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) continue; OtherAddr = *m_aSlots[i].m_Connection.PeerAddress(); OtherAddr.port = 0; if(!net_addr_comp(&ThisAddr, &OtherAddr)) { if(FoundAddr++ >= m_MaxClientsPerIP) { char aBuf[128]; str_format(aBuf, sizeof(aBuf), "Only %d players with the same IP are allowed", m_MaxClientsPerIP); CNetBase::SendControlMsg(m_Socket, &Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf) + 1); return 0; } } } for(int i = 0; i < MaxClients(); i++) { if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) { Found = true; m_aSlots[i].m_Connection.SetToken(m_RecvUnpacker.m_Data.m_Token); m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr); if(m_pfnNewClient) m_pfnNewClient(i, m_UserPtr); break; } } if(!Found) { const char FullMsg[] = "This server is full"; CNetBase::SendControlMsg(m_Socket, &Addr, m_RecvUnpacker.m_Data.m_ResponseToken, 0, NET_CTRLMSG_CLOSE, FullMsg, sizeof(FullMsg)); } } else if(m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_TOKEN) m_TokenCache.AddToken(&Addr, m_RecvUnpacker.m_Data.m_ResponseToken, NET_TOKENFLAG_RESPONSEONLY); } else if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONNLESS) { pChunk->m_Flags = NETSENDFLAG_CONNLESS; pChunk->m_ClientID = -1; pChunk->m_Address = Addr; pChunk->m_DataSize = m_RecvUnpacker.m_Data.m_DataSize; pChunk->m_pData = m_RecvUnpacker.m_Data.m_aChunkData; if(pResponseToken) *pResponseToken = m_RecvUnpacker.m_Data.m_ResponseToken; return 1; } } } return 0; }
/* TODO: chopp up this function into smaller working parts */ int CNetServer::Recv(CNetChunk *pChunk) { while(1) { NETADDR Addr; // check for a chunk if(m_RecvUnpacker.FetchChunk(pChunk)) return 1; // TODO: empty the recvinfo int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE); // no more packets for now if(Bytes <= 0) break; if(CNetBase::UnpackPacket(m_RecvUnpacker.m_aBuffer, Bytes, &m_RecvUnpacker.m_Data) == 0) { // check if we just should drop the packet char aBuf[128]; if(NetBan() && NetBan()->IsBanned(&Addr, aBuf, sizeof(aBuf))) { // banned, reply with a message CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf)+1); continue; } if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONNLESS) { pChunk->m_Flags = NETSENDFLAG_CONNLESS; pChunk->m_ClientID = -1; pChunk->m_Address = Addr; pChunk->m_DataSize = m_RecvUnpacker.m_Data.m_DataSize; pChunk->m_pData = m_RecvUnpacker.m_Data.m_aChunkData; return 1; } else { // TODO: check size here if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONTROL && m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_CONNECT) { bool Found = false; // check if we already got this client for(int i = 0; i < MaxClients(); i++) { if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE && net_addr_comp(m_aSlots[i].m_Connection.PeerAddress(), &Addr) == 0) { Found = true; // silent ignore.. we got this client already break; } } // client that wants to connect if(!Found) { // only allow a specific number of players with the same ip NETADDR ThisAddr = Addr, OtherAddr; int FoundAddr = 1; ThisAddr.port = 0; for(int i = 0; i < MaxClients(); ++i) { if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) continue; OtherAddr = *m_aSlots[i].m_Connection.PeerAddress(); OtherAddr.port = 0; if(!net_addr_comp(&ThisAddr, &OtherAddr)) { if(FoundAddr++ >= m_MaxClientsPerIP) { char aBuf[128]; str_format(aBuf, sizeof(aBuf), "Only %d players with the same IP are allowed", m_MaxClientsPerIP); CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, aBuf, sizeof(aBuf)); return 0; } } } for(int i = 0; i < MaxClients(); i++) { if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) { Found = true; m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr); if(m_pfnNewClient) m_pfnNewClient(i, m_UserPtr); break; } } if(!Found) { const char FullMsg[] = "This server is full"; CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, FullMsg, sizeof(FullMsg)); } } } else { // normal packet, find matching slot for(int i = 0; i < MaxClients(); i++) { if(net_addr_comp(m_aSlots[i].m_Connection.PeerAddress(), &Addr) == 0) { if(m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr)) { if(m_RecvUnpacker.m_Data.m_DataSize) m_RecvUnpacker.Start(&Addr, &m_aSlots[i].m_Connection, i); } } } } } } } return 0; }
int netserver_ban_add(NETSERVER *s, NETADDR addr, int seconds) { int iphash = (addr.ip[0]+addr.ip[1]+addr.ip[2]+addr.ip[3])&0xff; unsigned stamp = 0xffffffff; NETBAN *ban; /* remove the port */ addr.port = 0; if(seconds) stamp = time_timestamp() + seconds; /* search to see if it already exists */ ban = s->bans[iphash]; MACRO_LIST_FIND(ban, hashnext, net_addr_comp(&ban->info.addr, &addr) == 0); if(ban) { /* adjust the ban */ ban->info.expires = stamp; return 0; } if(!s->banpool_firstfree) return -1; /* fetch and clear the new ban */ ban = s->banpool_firstfree; MACRO_LIST_UNLINK(ban, s->banpool_firstfree, prev, next); /* setup the ban info */ ban->info.expires = stamp; ban->info.addr = addr; /* add it to the ban hash */ MACRO_LIST_LINK_FIRST(ban, s->bans[iphash], hashprev, hashnext); /* insert it into the used list */ { if(s->banpool_firstused) { NETBAN *insert_after = s->banpool_firstused; MACRO_LIST_FIND(insert_after, next, stamp < insert_after->info.expires); if(insert_after) insert_after = insert_after->prev; else { /* add to last */ insert_after = s->banpool_firstused; while(insert_after->next) insert_after = insert_after->next; } if(insert_after) { MACRO_LIST_LINK_AFTER(ban, insert_after, prev, next); } else { MACRO_LIST_LINK_FIRST(ban, s->banpool_firstused, prev, next); } } else { MACRO_LIST_LINK_FIRST(ban, s->banpool_firstused, prev, next); } } /* drop banned clients */ { char buf[128]; int i; NETADDR banaddr; if(seconds) str_format(buf, sizeof(buf), "you have been banned for %d minutes", seconds/60); else str_format(buf, sizeof(buf), "you have been banned for life"); for(i = 0; i < s->max_clients; i++) { banaddr = s->slots[i].conn.peeraddr; banaddr.port = 0; if(net_addr_comp(&addr, &banaddr) == 0) netserver_drop(s, i, buf); } } return 0; }
/* TODO: chopp up this function into smaller working parts */ int netserver_recv(NETSERVER *s, NETCHUNK *chunk) { unsigned now = time_timestamp(); while(1) { NETADDR addr; int i, bytes, found; /* check for a chunk */ if(recvinfo_fetch_chunk(&s->recv, chunk)) return 1; /* TODO: empty the recvinfo */ bytes = net_udp_recv(s->socket, &addr, s->recv.buffer, NET_MAX_PACKETSIZE); /* no more packets for now */ if(bytes <= 0) break; if(unpack_packet(s->recv.buffer, bytes, &s->recv.data) == 0) { NETBAN *ban = 0; NETADDR banaddr = addr; int iphash = (addr.ip[0]+addr.ip[1]+addr.ip[2]+addr.ip[3])&0xff; found = 0; banaddr.port = 0; /* search a ban */ for(ban = s->bans[iphash]; ban; ban = ban->hashnext) { if(net_addr_comp(&ban->info.addr, &banaddr) == 0) break; } /* check if we just should drop the packet */ if(ban) { // banned, reply with a message char banstr[128]; if(ban->info.expires) { int mins = ((ban->info.expires - now)+59)/60; if(mins == 1) str_format(banstr, sizeof(banstr), "banned for %d minute", mins); else str_format(banstr, sizeof(banstr), "banned for %d minutes", mins); } else str_format(banstr, sizeof(banstr), "banned for life"); send_controlmsg(s->socket, &addr, 0, NET_CTRLMSG_CLOSE, banstr, str_length(banstr)+1); continue; } if(s->recv.data.flags&NET_PACKETFLAG_CONNLESS) { chunk->flags = NETSENDFLAG_CONNLESS; chunk->client_id = -1; chunk->address = addr; chunk->data_size = s->recv.data.data_size; chunk->data = s->recv.data.chunk_data; return 1; } else { /* TODO: check size here */ if(s->recv.data.flags&NET_PACKETFLAG_CONTROL && s->recv.data.chunk_data[0] == NET_CTRLMSG_CONNECT) { found = 0; /* check if we already got this client */ for(i = 0; i < s->max_clients; i++) { if(s->slots[i].conn.state != NET_CONNSTATE_OFFLINE && net_addr_comp(&s->slots[i].conn.peeraddr, &addr) == 0) { found = 1; /* silent ignore.. we got this client already */ break; } } /* client that wants to connect */ if(!found) { for(i = 0; i < s->max_clients; i++) { if(s->slots[i].conn.state == NET_CONNSTATE_OFFLINE) { found = 1; conn_feed(&s->slots[i].conn, &s->recv.data, &addr); if(s->new_client) s->new_client(i, s->user_ptr); break; } } if(!found) { const char fullmsg[] = "server is full"; send_controlmsg(s->socket, &addr, 0, NET_CTRLMSG_CLOSE, fullmsg, sizeof(fullmsg)); } } } else { /* normal packet, find matching slot */ for(i = 0; i < s->max_clients; i++) { if(net_addr_comp(&s->slots[i].conn.peeraddr, &addr) == 0) { if(conn_feed(&s->slots[i].conn, &s->recv.data, &addr)) { if(s->recv.data.data_size) recvinfo_start(&s->recv, &addr, &s->slots[i].conn, i); } } } } } } } return 0; }