diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2010-05-29 07:25:38 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2010-05-29 07:25:38 +0000 |
| commit | 72c06a258940696093f255fb1061beb58e1cdd0b (patch) | |
| tree | 36b9a7712eec2d4f07837eab9c38ef1c5af85319 /src/engine/e_network_server.cpp | |
| parent | e56feb597bc743677633432f77513b02907fd169 (diff) | |
| download | zcatch-72c06a258940696093f255fb1061beb58e1cdd0b.tar.gz zcatch-72c06a258940696093f255fb1061beb58e1cdd0b.zip | |
copied refactor to trunk
Diffstat (limited to 'src/engine/e_network_server.cpp')
| -rw-r--r-- | src/engine/e_network_server.cpp | 408 |
1 files changed, 0 insertions, 408 deletions
diff --git a/src/engine/e_network_server.cpp b/src/engine/e_network_server.cpp deleted file mode 100644 index 995290ef..00000000 --- a/src/engine/e_network_server.cpp +++ /dev/null @@ -1,408 +0,0 @@ -#include <base/system.h> -#include "e_network.h" - -#define MACRO_LIST_LINK_FIRST(object, first, prev, next) \ - { if(first) first->prev = object; \ - object->prev = (struct CBan *)0; \ - object->next = first; \ - first = object; } - -#define MACRO_LIST_LINK_AFTER(object, after, prev, next) \ - { object->prev = after; \ - object->next = after->next; \ - after->next = object; \ - if(object->next) \ - object->next->prev = object; \ - } - -#define MACRO_LIST_UNLINK(object, first, prev, next) \ - { if(object->next) object->next->prev = object->prev; \ - if(object->prev) object->prev->next = object->next; \ - else first = object->next; \ - object->next = 0; object->prev = 0; } - -#define MACRO_LIST_FIND(start, next, expression) \ - { while(start && !(expression)) start = start->next; } - -bool CNetServer::Open(NETADDR BindAddr, int MaxClients, int Flags) -{ - // zero out the whole structure - mem_zero(this, sizeof(*this)); - - // open socket - m_Socket = net_udp_create(BindAddr); - if(m_Socket == NETSOCKET_INVALID) - return false; - - // clamp clients - m_MaxClients = MaxClients; - if(m_MaxClients > NET_MAX_CLIENTS) - m_MaxClients = NET_MAX_CLIENTS; - if(m_MaxClients < 1) - m_MaxClients = 1; - - for(int i = 0; i < NET_MAX_CLIENTS; i++) - m_aSlots[i].m_Connection.Init(m_Socket); - - /* setup all pointers for bans */ - for(int i = 1; i < NET_SERVER_MAXBANS-1; i++) - { - m_BanPool[i].m_pNext = &m_BanPool[i+1]; - m_BanPool[i].m_pPrev = &m_BanPool[i-1]; - } - - m_BanPool[0].m_pNext = &m_BanPool[1]; - m_BanPool[NET_SERVER_MAXBANS-1].m_pPrev = &m_BanPool[NET_SERVER_MAXBANS-2]; - m_BanPool_FirstFree = &m_BanPool[0]; - - return true; -} - -int CNetServer::SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser) -{ - m_pfnNewClient = pfnNewClient; - m_pfnDelClient = pfnDelClient; - m_UserPtr = pUser; - return 0; -} - -int CNetServer::Close() -{ - /* TODO: implement me */ - return 0; -} - -int CNetServer::Drop(int ClientID, const char *pReason) -{ - /* TODO: insert lots of checks here */ - NETADDR Addr = ClientAddr(ClientID); - - dbg_msg("net_server", "client dropped. cid=%d ip=%d.%d.%d.%d reason=\"%s\"", - ClientID, - Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3], - pReason - ); - - m_aSlots[ClientID].m_Connection.Disconnect(pReason); - - if(m_pfnDelClient) - m_pfnDelClient(ClientID, m_UserPtr); - - return 0; -} - -int CNetServer::BanGet(int Index, CBanInfo *pInfo) -{ - CBan *pBan; - for(pBan = m_BanPool_FirstUsed; pBan && Index; pBan = pBan->m_pNext, Index--) - {} - - if(!pBan) - return 0; - *pInfo = pBan->m_Info; - return 1; -} - -int CNetServer::BanNum() -{ - int Count = 0; - CBan *pBan; - for(pBan = m_BanPool_FirstUsed; pBan; pBan = pBan->m_pNext) - Count++; - return Count; -} - -void CNetServer::BanRemoveByObject(CBan *pBan) -{ - int iphash = (pBan->m_Info.m_Addr.ip[0]+pBan->m_Info.m_Addr.ip[1]+pBan->m_Info.m_Addr.ip[2]+pBan->m_Info.m_Addr.ip[3])&0xff; - dbg_msg("netserver", "removing ban on %d.%d.%d.%d", - pBan->m_Info.m_Addr.ip[0], pBan->m_Info.m_Addr.ip[1], pBan->m_Info.m_Addr.ip[2], pBan->m_Info.m_Addr.ip[3]); - MACRO_LIST_UNLINK(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext); - MACRO_LIST_UNLINK(pBan, m_aBans[iphash], m_pHashPrev, m_pHashNext); - MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstFree, m_pPrev, m_pNext); -} - -int CNetServer::BanRemove(NETADDR Addr) -{ - int iphash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3])&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::BanAdd(NETADDR Addr, int Seconds) -{ - int iphash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3])&0xff; - int Stamp = -1; - CBan *pBan; - - /* remove the port */ - Addr.port = 0; - - if(Seconds) - Stamp = time_timestamp() + Seconds; - - /* search to see if it already exists */ - pBan = m_aBans[iphash]; - MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0); - if(pBan) - { - /* adjust the ban */ - pBan->m_Info.m_Expires = Stamp; - return 0; - } - - if(!m_BanPool_FirstFree) - return -1; - - /* fetch and clear the new ban */ - pBan = m_BanPool_FirstFree; - MACRO_LIST_UNLINK(pBan, m_BanPool_FirstFree, m_pPrev, m_pNext); - - /* setup the ban info */ - pBan->m_Info.m_Expires = Stamp; - pBan->m_Info.m_Addr = Addr; - - /* add it to the ban hash */ - MACRO_LIST_LINK_FIRST(pBan, m_aBans[iphash], m_pHashPrev, m_pHashNext); - - /* insert it into the used list */ - { - if(m_BanPool_FirstUsed) - { - CBan *pInsertAfter = m_BanPool_FirstUsed; - MACRO_LIST_FIND(pInsertAfter, m_pNext, Stamp < pInsertAfter->m_Info.m_Expires); - - if(pInsertAfter) - pInsertAfter = pInsertAfter->m_pPrev; - else - { - /* add to last */ - pInsertAfter = m_BanPool_FirstUsed; - while(pInsertAfter->m_pNext) - pInsertAfter = pInsertAfter->m_pNext; - } - - if(pInsertAfter) - { - MACRO_LIST_LINK_AFTER(pBan, pInsertAfter, m_pPrev, m_pNext); - } - else - { - MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext); - } - } - else - { - MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext); - } - } - - /* drop banned clients */ - { - char Buf[128]; - 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(int i = 0; i < MaxClients(); i++) - { - BanAddr = m_aSlots[i].m_Connection.PeerAddress(); - BanAddr.port = 0; - - if(net_addr_comp(&Addr, &BanAddr) == 0) - Drop(i, Buf); - } - } - return 0; -} - -int CNetServer::Update() -{ - int Now = time_timestamp(); - for(int i = 0; i < MaxClients(); i++) - { - m_aSlots[i].m_Connection.Update(); - if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ERROR) - Drop(i, m_aSlots[i].m_Connection.ErrorString()); - } - - /* remove expired bans */ - while(m_BanPool_FirstUsed && m_BanPool_FirstUsed->m_Info.m_Expires < Now) - { - CBan *pBan = m_BanPool_FirstUsed; - BanRemoveByObject(pBan); - } - - return 0; -} - -/* - TODO: chopp up this function into smaller working parts -*/ -int CNetServer::Recv(CNetChunk *pChunk) -{ - unsigned now = time_timestamp(); - - 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) - { - CBan *pBan = 0; - NETADDR BanAddr = Addr; - int iphash = (BanAddr.ip[0]+BanAddr.ip[1]+BanAddr.ip[2]+BanAddr.ip[3])&0xff; - int Found = 0; - BanAddr.port = 0; - - /* search a ban */ - for(pBan = m_aBans[iphash]; pBan; pBan = pBan->m_pHashNext) - { - if(net_addr_comp(&pBan->m_Info.m_Addr, &BanAddr) == 0) - break; - } - - /* check if we just should drop the packet */ - if(pBan) - { - // banned, reply with a message - char BanStr[128]; - if(pBan->m_Info.m_Expires) - { - int Mins = ((pBan->m_Info.m_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"); - CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, BanStr, str_length(BanStr)+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) - { - Found = 0; - - /* check if we already got this client */ - for(int i = 0; i < MaxClients(); i++) - { - NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress(); - if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE && - net_addr_comp(&PeerAddr, &Addr) == 0) - { - Found = 1; /* silent ignore.. we got this client already */ - break; - } - } - - /* client that wants to connect */ - if(!Found) - { - for(int i = 0; i < MaxClients(); i++) - { - if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) - { - Found = 1; - 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[] = "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++) - { - NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress(); - if(net_addr_comp(&PeerAddr, &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 CNetServer::Send(CNetChunk *pChunk) -{ - 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_Flags&NETSENDFLAG_CONNLESS) - { - /* send connectionless packet */ - CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize); - } - else - { - int Flags = 0; - dbg_assert(pChunk->m_ClientID >= 0, "errornous client id"); - dbg_assert(pChunk->m_ClientID < MaxClients(), "errornous client id"); - - if(pChunk->m_Flags&NETSENDFLAG_VITAL) - Flags = NET_CHUNKFLAG_VITAL; - - m_aSlots[pChunk->m_ClientID].m_Connection.QueueChunk(Flags, pChunk->m_DataSize, pChunk->m_pData); - - if(pChunk->m_Flags&NETSENDFLAG_FLUSH) - m_aSlots[pChunk->m_ClientID].m_Connection.Flush(); - } - return 0; -} - |