about summary refs log tree commit diff
path: root/src/engine/shared
diff options
context:
space:
mode:
authorheinrich5991 <heinrich5991@gmail.com>2011-07-02 08:36:14 +0200
committeroy <Tom_Adams@web.de>2011-07-29 17:51:14 +0200
commit2ba6fbd7314bfce9cedf93e6f2b1e7f8b5ac7a84 (patch)
tree138db6f4ee790703dd1689a6caf38f2b236cb9ea /src/engine/shared
parent65d312fd06ef7730cb6699923e17d8b05bd764d0 (diff)
downloadzcatch-2ba6fbd7314bfce9cedf93e6f2b1e7f8b5ac7a84.tar.gz
zcatch-2ba6fbd7314bfce9cedf93e6f2b1e7f8b5ac7a84.zip
added econ functionality
Diffstat (limited to 'src/engine/shared')
-rw-r--r--src/engine/shared/config_variables.h4
-rw-r--r--src/engine/shared/network.h78
-rw-r--r--src/engine/shared/network_console.cpp144
-rw-r--r--src/engine/shared/network_console_conn.cpp176
4 files changed, 402 insertions, 0 deletions
diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h
index 213ebf26..fd318a7d 100644
--- a/src/engine/shared/config_variables.h
+++ b/src/engine/shared/config_variables.h
@@ -86,6 +86,10 @@ MACRO_CONFIG_STR(SvRconPassword, sv_rcon_password, 32, "", CFGFLAG_SERVER, "Remo
 MACRO_CONFIG_STR(SvRconModPassword, sv_rcon_mod_password, 32, "", CFGFLAG_SERVER, "Remote console password for moderators (limited access)")
 MACRO_CONFIG_INT(SvRconMaxTries, sv_rcon_max_tries, 3, 0, 100, CFGFLAG_SERVER, "Maximum number of tries for remote console authentication")
 MACRO_CONFIG_INT(SvRconBantime, sv_rcon_bantime, 5, 0, 1440, CFGFLAG_SERVER, "The time a client gets banned if remote console authentication fails. 0 makes it just use kick")
+MACRO_CONFIG_STR(SvEconBindaddr, sv_econ_bindaddr, 128, "localhost", CFGFLAG_SERVER, "Address to bind the external console to. Anything but 'localhost' is dangerous")
+MACRO_CONFIG_INT(SvEconPort, sv_econ_port, 0, 0, 0, CFGFLAG_SERVER, "Port to use for the external console")
+MACRO_CONFIG_INT(SvEconAuthTimeout, sv_econ_auth_timeout, 30, 1, 120, CFGFLAG_SERVER, "Time in seconds before the the econ authentification times out")
+MACRO_CONFIG_INT(SvEconTimeout, sv_econ_timeout, 300, 1, 3600, CFGFLAG_SERVER, "Time in seconds before the econ connection times out")
 
 MACRO_CONFIG_INT(Debug, debug, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Debug mode")
 MACRO_CONFIG_INT(DbgStress, dbg_stress, 0, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Stress systems")
diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h
index 228ba6dd..d0b78d05 100644
--- a/src/engine/shared/network.h
+++ b/src/engine/shared/network.h
@@ -49,6 +49,7 @@ enum
 	NET_MAX_CHUNKHEADERSIZE = 5,
 	NET_PACKETHEADERSIZE = 3,
 	NET_MAX_CLIENTS = 16,
+	NET_MAX_CONSOLE_CLIENTS = 16,
 	NET_MAX_SEQUENCE = 1<<10,
 	NET_SEQUENCE_MASK = NET_MAX_SEQUENCE-1,
 
@@ -192,6 +193,41 @@ public:
 	int AckSequence() const { return m_Ack; }
 };
 
+class CConsoleNetConnection
+{
+private:
+	unsigned m_State;
+
+	NETADDR m_PeerAddr;
+	NETSOCKET m_Socket;
+
+	char m_aBuffer[NET_MAX_PACKETSIZE];
+	char *m_pBufferPos;
+
+	char m_aErrorString[256];
+
+	int m_Timeout;
+	int64 m_LastRecvTime;
+
+public:
+	void Init(NETSOCKET Socket);
+	void Init(NETSOCKET Socket, const NETADDR *pAddr);
+	int Connect(const NETADDR *pAddr);
+	void Disconnect(const char *pReason);
+
+	int State() const { return m_State; }
+	NETADDR PeerAddress() const { return m_PeerAddr; }
+	const char *ErrorString() const { return m_aErrorString; }
+
+	void SetTimeout(int Timeout) { m_Timeout = Timeout; }
+	int Timeout() const { return m_Timeout; }
+
+	void Reset();
+	int Update();
+	int Send(const char *pLine);
+	int Recv(char *pLine, int MaxLength);
+};
+
 class CNetRecvUnpacker
 {
 public:
@@ -292,6 +328,48 @@ public:
 	void SetMaxClientsPerIP(int Max);
 };
 
+class CNetConsole
+{
+private:
+	struct CSlot
+	{
+		CConsoleNetConnection m_Connection;
+	};
+
+	NETSOCKET m_Socket;
+	CSlot m_aSlots[NET_MAX_CLIENTS];
+
+	NETFUNC_NEWCLIENT m_pfnNewClient;
+	NETFUNC_DELCLIENT m_pfnDelClient;
+	void *m_UserPtr;
+
+	CNetRecvUnpacker m_RecvUnpacker;
+
+public:
+	int SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser);
+
+	//
+	bool Open(NETADDR BindAddr, int Flags);
+	int Close();
+
+	//
+	int Broadcast(const char *pLine);
+	int Recv(char *pLine, int MaxLength, int *pClientID = 0);
+	int Send(int ClientID, const char *pLine);
+	int Update();
+
+	//
+	int AcceptClient(NETSOCKET Socket, const NETADDR *pAddr);
+	int Drop(int ClientID, const char *pReason);
+
+	//
+	void SetTimeout(int ClientID, int Timeout) { m_aSlots[ClientID].m_Connection.SetTimeout(Timeout); }
+
+	// status requests
+	int Timeout(int ClientID) { return m_aSlots[ClientID].m_Connection.Timeout(); }
+	NETADDR ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); }
+};
+
 
 
 // client side
diff --git a/src/engine/shared/network_console.cpp b/src/engine/shared/network_console.cpp
new file mode 100644
index 00000000..3e50a1ac
--- /dev/null
+++ b/src/engine/shared/network_console.cpp
@@ -0,0 +1,144 @@
+/* (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>
+#include "network.h"
+
+bool CNetConsole::Open(NETADDR BindAddr, int Flags)
+{
+	// zero out the whole structure
+	mem_zero(this, sizeof(*this));
+
+	// open socket
+	m_Socket = net_tcp_create(&BindAddr);
+	if(!m_Socket.type)
+		return false;
+	if(net_tcp_listen(m_Socket, NET_MAX_CONSOLE_CLIENTS))
+		return false;
+	net_tcp_set_non_blocking(m_Socket);
+
+	for(int i = 0; i < NET_MAX_CLIENTS; i++)
+		m_aSlots[i].m_Connection.Init(m_Socket);
+
+	return true;
+}
+
+int CNetConsole::SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser)
+{
+	m_pfnNewClient = pfnNewClient;
+	m_pfnDelClient = pfnDelClient;
+	m_UserPtr = pUser;
+	return 0;
+}
+
+int CNetConsole::Close()
+{
+	// TODO: implement me
+	return 0;
+}
+
+int CNetConsole::Drop(int ClientID, const char *pReason)
+{
+	NETADDR Addr = ClientAddr(ClientID);
+
+	char aAddrStr[NETADDR_MAXSTRSIZE];
+	net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr));
+
+	if(m_pfnDelClient)
+		m_pfnDelClient(ClientID, pReason, m_UserPtr);
+
+	m_aSlots[ClientID].m_Connection.Disconnect(pReason);
+
+	return 0;
+}
+
+int CNetConsole::AcceptClient(NETSOCKET Socket, const NETADDR *pAddr)
+{
+	char aError[256] = { 0 };
+	int FreeSlot = -1;
+	
+	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)
+		{
+			NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress();;
+			if(net_addr_comp(pAddr, &PeerAddr) == 0)
+			{
+				str_copy(aError, "Only one client per IP allowed", sizeof(aError));
+				break;
+			}
+		}
+	}
+
+	if(!aError[0] && FreeSlot != -1)
+	{
+		m_aSlots[FreeSlot].m_Connection.Init(Socket, pAddr);
+		if(m_pfnNewClient)
+			m_pfnNewClient(FreeSlot, m_UserPtr);
+		return 1;
+	}
+
+	if(!aError[0])
+	{
+		str_copy(aError, "No free slot available", sizeof(aError));
+	}
+	
+	dbg_msg("netconsole", "refused client, reason=\"%s\"", aError);
+
+	net_tcp_send(Socket, aError, str_length(aError));
+	net_tcp_close(Socket);
+
+	return 0;
+}
+
+int CNetConsole::Update()
+{
+	NETSOCKET Socket;
+	NETADDR Addr;
+
+	while(net_tcp_accept(m_Socket, &Socket, &Addr) > 0)
+	{
+		AcceptClient(Socket, &Addr);
+	}
+
+	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::Broadcast(const char *pLine)
+{
+	for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++)
+	{
+		if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ONLINE)
+			Send(i, pLine);
+	}
+	return 0;
+}
+
+int CNetConsole::Send(int ClientID, const char *pLine)
+{
+	return m_aSlots[ClientID].m_Connection.Send(pLine);
+}
+
diff --git a/src/engine/shared/network_console_conn.cpp b/src/engine/shared/network_console_conn.cpp
new file mode 100644
index 00000000..4dd971a6
--- /dev/null
+++ b/src/engine/shared/network_console_conn.cpp
@@ -0,0 +1,176 @@
+/* (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>
+#include "config.h"
+#include "network.h"
+
+void CConsoleNetConnection::Reset()
+{
+	m_State = NET_CONNSTATE_OFFLINE;
+	mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
+	m_aErrorString[0] = 0;
+
+	m_aBuffer[0] = 0;
+	m_pBufferPos = 0;
+	m_Timeout = 0;
+}
+
+void CConsoleNetConnection::Init(NETSOCKET Socket, const NETADDR *pAddr)
+{
+	Reset();
+
+	m_Socket = Socket;
+	net_tcp_set_non_blocking(m_Socket);
+
+	m_LastRecvTime = time_get();
+
+	m_PeerAddr = *pAddr;
+	m_State = NET_CONNSTATE_ONLINE;
+}
+
+void CConsoleNetConnection::Init(NETSOCKET Socket)
+{
+	Reset();
+
+	m_Socket = Socket;
+	net_tcp_set_non_blocking(m_Socket);
+
+	m_LastRecvTime = time_get();
+}
+
+int CConsoleNetConnection::Connect(const NETADDR *pAddr)
+{
+	if(State() != NET_CONNSTATE_OFFLINE)
+		return -1;
+
+	// init connection
+	Reset();
+	m_PeerAddr = *pAddr;
+	net_tcp_connect(m_Socket, pAddr);
+	m_State = NET_CONNSTATE_ONLINE;
+	return 0;
+}
+
+void CConsoleNetConnection::Disconnect(const char *pReason)
+{
+	if(State() == NET_CONNSTATE_OFFLINE)
+		return;
+
+	if(pReason)
+	{
+		char aBuf[sizeof(pReason) + 4];
+		str_format(aBuf, sizeof(aBuf), "%s", pReason);
+		Send(aBuf);
+	}
+
+	net_tcp_close(m_Socket);
+
+	Reset();
+}
+
+int CConsoleNetConnection::Update()
+{
+	if(m_Timeout && time_get() > m_LastRecvTime + m_Timeout * time_freq())
+	{
+		m_State = NET_CONNSTATE_ERROR;
+		str_copy(m_aErrorString, "timeout", sizeof(m_aErrorString));
+		return -1;
+	}
+
+	if(State() == NET_CONNSTATE_ONLINE)
+	{
+		char aBuf[NET_MAX_PACKETSIZE];
+
+		int Bytes = net_tcp_recv(m_Socket, aBuf, sizeof(aBuf) - 1);
+
+		if(Bytes > 0)
+		{
+			aBuf[Bytes - 1] = 0;
+
+			if(!m_pBufferPos)
+				m_aBuffer[0] = 0;
+			else if(m_pBufferPos != m_aBuffer)
+				mem_move(m_pBufferPos, m_aBuffer, str_length(m_pBufferPos) + 1); // +1 for the \0
+			m_pBufferPos = m_aBuffer;
+
+			str_append(m_aBuffer, aBuf, sizeof(m_aBuffer));
+
+			m_LastRecvTime = time_get();
+		}
+		else if(Bytes < 0)
+		{
+			if(net_would_block()) // no data received
+				return 0;
+
+			m_State = NET_CONNSTATE_ERROR; // error
+			str_copy(m_aErrorString, "connection failure", sizeof(m_aErrorString));
+			return -1;
+		}
+		else
+		{
+			m_State = NET_CONNSTATE_ERROR;
+			str_copy(m_aErrorString, "remote end closed the connection", sizeof(m_aErrorString));
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int CConsoleNetConnection::Recv(char *pLine, int MaxLength)
+{
+	if(State() == NET_CONNSTATE_ONLINE)
+	{
+		if(m_pBufferPos && *m_pBufferPos)
+		{
+			char *pResult = m_pBufferPos;
+
+			while(*m_pBufferPos && *m_pBufferPos != '\r' && *m_pBufferPos != '\n')
+				m_pBufferPos++;
+
+			if(*m_pBufferPos) // haven't reached the end of the buffer?
+			{
+				if(*m_pBufferPos == '\r' && *(m_pBufferPos + 1) == '\n')
+				{
+					*m_pBufferPos = 0;
+					m_pBufferPos += 2;
+				}
+				else
+				{
+					*m_pBufferPos = 0;
+					m_pBufferPos++;
+				}
+			}
+			else
+			{
+				m_pBufferPos = 0;
+			}
+
+			str_copy(pLine, pResult, MaxLength);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+int CConsoleNetConnection::Send(const char *pLine)
+{
+	if(State() != NET_CONNSTATE_ONLINE)
+		return -1;
+
+	int Length = str_length(pLine);
+	char aBuf[1024];
+	str_copy(aBuf, pLine, sizeof(aBuf) - 2);
+	aBuf[Length + 1] = '\n';
+	aBuf[Length + 2] = '\0';
+
+	if(net_tcp_send(m_Socket, aBuf, Length + 2) < 0)
+	{
+		m_State = NET_CONNSTATE_ERROR;
+		str_copy(m_aErrorString, "Failed to send packet", sizeof(m_aErrorString));
+		return -1;
+	}
+	
+	return 0;
+}
+