ddnet/src/engine/shared/network_console.cpp

150 lines
3.4 KiB
C++
Raw Normal View History

2011-07-02 06:36:14 +00:00
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <base/system.h>
2011-12-29 22:36:53 +00:00
#include <engine/console.h>
#include "netban.h"
2011-07-02 06:36:14 +00:00
#include "network.h"
2011-12-29 22:36:53 +00:00
bool CNetConsole::Open(NETADDR BindAddr, CNetBan *pNetBan, int Flags)
2011-07-02 06:36:14 +00:00
{
// zero out the whole structure
mem_zero(this, sizeof(*this));
m_Socket.type = NETTYPE_INVALID;
m_Socket.ipv4sock = -1;
m_Socket.ipv6sock = -1;
2011-12-29 22:36:53 +00:00
m_pNetBan = pNetBan;
2011-07-02 06:36:14 +00:00
// open socket
2011-07-30 11:40:01 +00:00
m_Socket = net_tcp_create(BindAddr);
2011-07-02 06:36:14 +00:00
if(!m_Socket.type)
return false;
if(net_tcp_listen(m_Socket, NET_MAX_CONSOLE_CLIENTS))
return false;
2011-07-30 11:40:01 +00:00
net_set_non_blocking(m_Socket);
2011-07-02 06:36:14 +00:00
2020-10-26 14:14:07 +00:00
for(auto &Slot : m_aSlots)
Slot.m_Connection.Reset();
2011-07-02 06:36:14 +00:00
return true;
}
2020-03-29 02:36:38 +00:00
void CNetConsole::SetCallbacks(NETFUNC_NEWCLIENT_CON pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser)
2011-07-02 06:36:14 +00:00
{
m_pfnNewClient = pfnNewClient;
m_pfnDelClient = pfnDelClient;
2020-10-27 17:57:14 +00:00
m_pUser = pUser;
2011-07-02 06:36:14 +00:00
}
int CNetConsole::Close()
{
2020-10-26 14:14:07 +00:00
for(auto &Slot : m_aSlots)
Slot.m_Connection.Disconnect("closing console");
net_tcp_close(m_Socket);
2011-07-02 06:36:14 +00:00
return 0;
}
int CNetConsole::Drop(int ClientID, const char *pReason)
{
if(m_pfnDelClient)
2020-10-27 17:57:14 +00:00
m_pfnDelClient(ClientID, pReason, m_pUser);
2011-07-02 06:36:14 +00:00
m_aSlots[ClientID].m_Connection.Disconnect(pReason);
return 0;
}
int CNetConsole::AcceptClient(NETSOCKET Socket, const NETADDR *pAddr)
{
char aError[256] = {0};
2011-07-02 06:36:14 +00:00
int FreeSlot = -1;
2011-08-11 08:59:14 +00:00
2011-07-30 11:40:01 +00:00
// look for free slot or multiple client
2011-07-02 06:36:14 +00:00
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)
{
2011-12-29 22:36:53 +00:00
if(net_addr_comp(pAddr, m_aSlots[i].m_Connection.PeerAddress()) == 0)
2011-07-02 06:36:14 +00:00
{
2011-07-30 11:40:01 +00:00
str_copy(aError, "only one client per IP allowed", sizeof(aError));
2011-07-02 06:36:14 +00:00
break;
}
}
}
2011-07-30 11:40:01 +00:00
// accept client
2011-07-02 06:36:14 +00:00
if(!aError[0] && FreeSlot != -1)
{
m_aSlots[FreeSlot].m_Connection.Init(Socket, pAddr);
if(m_pfnNewClient)
2020-10-27 17:57:14 +00:00
m_pfnNewClient(FreeSlot, m_pUser);
2011-07-30 11:40:01 +00:00
return 0;
2011-07-02 06:36:14 +00:00
}
2011-07-30 11:40:01 +00:00
// reject client
2011-07-02 06:36:14 +00:00
if(!aError[0])
2011-07-30 11:40:01 +00:00
str_copy(aError, "no free slot available", sizeof(aError));
2011-07-02 06:36:14 +00:00
net_tcp_send(Socket, aError, str_length(aError));
net_tcp_close(Socket);
2011-07-30 11:40:01 +00:00
return -1;
2011-07-02 06:36:14 +00:00
}
int CNetConsole::Update()
{
NETSOCKET Socket;
NETADDR Addr;
if(net_tcp_accept(m_Socket, &Socket, &Addr) > 0)
2011-07-02 06:36:14 +00:00
{
2011-12-29 22:36:53 +00:00
// check if we just should drop the packet
char aBuf[128];
if(NetBan() && NetBan()->IsBanned(&Addr, aBuf, sizeof(aBuf)))
{
2011-12-29 22:36:53 +00:00
// banned, reply with a message and drop
net_tcp_send(Socket, aBuf, str_length(aBuf));
net_tcp_close(Socket);
}
2011-12-29 22:36:53 +00:00
else
AcceptClient(Socket, &Addr);
2011-07-02 06:36:14 +00:00
}
for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
{
if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ONLINE)
m_aSlots[i].m_Connection.Update();
if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ERROR)
Drop(i, m_aSlots[i].m_Connection.ErrorString());
}
return 0;
}
int CNetConsole::Recv(char *pLine, int MaxLength, int *pClientID)
{
for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
{
if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ONLINE && m_aSlots[i].m_Connection.Recv(pLine, MaxLength))
{
if(pClientID)
*pClientID = i;
return 1;
}
}
return 0;
}
int CNetConsole::Send(int ClientID, const char *pLine)
{
2011-07-30 11:40:01 +00:00
if(m_aSlots[ClientID].m_Connection.State() == NET_CONNSTATE_ONLINE)
return m_aSlots[ClientID].m_Connection.Send(pLine);
else
return -1;
2011-07-02 06:36:14 +00:00
}