diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2007-05-22 15:03:32 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2007-05-22 15:03:32 +0000 |
| commit | 73aa9b71c1d8b5c5065d1e474f13601da3ca6b20 (patch) | |
| tree | 88b6a0a4a2ebdd33a88f4a25682581d329d33f6b /masterserver/src | |
| download | zcatch-73aa9b71c1d8b5c5065d1e474f13601da3ca6b20.tar.gz zcatch-73aa9b71c1d8b5c5065d1e474f13601da3ca6b20.zip | |
started the major restructure of svn
Diffstat (limited to 'masterserver/src')
| -rw-r--r-- | masterserver/src/main.cpp | 29 | ||||
| -rw-r--r-- | masterserver/src/masterserver.cpp | 176 | ||||
| -rw-r--r-- | masterserver/src/network.cpp | 39 |
3 files changed, 244 insertions, 0 deletions
diff --git a/masterserver/src/main.cpp b/masterserver/src/main.cpp new file mode 100644 index 00000000..380830ad --- /dev/null +++ b/masterserver/src/main.cpp @@ -0,0 +1,29 @@ +#include <cstdio> +#include <cstdlib> + +#include "masterserver.h" + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + puts("Usage: masterserver <port> (this will bind the server to the port specified (both udp and tcp)."); + return -1; + } + + int port = atoi(argv[1]); + + CMasterServer masterServer; + masterServer.Init(port); + + while (1) + { + masterServer.Tick(); + + thread_sleep(10); + } + + masterServer.Shutdown(); + + return 0; +} diff --git a/masterserver/src/masterserver.cpp b/masterserver/src/masterserver.cpp new file mode 100644 index 00000000..383c696e --- /dev/null +++ b/masterserver/src/masterserver.cpp @@ -0,0 +1,176 @@ +#include <ctime> + +#include "masterserver.h" + +void CMasterServer::Init(int port) +{ + netaddr4 addr(0, 0, 0, 0, port); + addr.port = port; + + net_init(); + m_UDPSocket.open(port); + m_TCPSocket.open(&addr); + m_TCPSocket.set_non_blocking(); + m_TCPSocket.listen(); +} + +void CMasterServer::Shutdown() +{ + m_UDPSocket.close(); +} + +void CMasterServer::Tick() +{ + m_CurrentTime = time(NULL); + + ListenForHeartBeats(); + ListenForServerListPolls(); + + CleanUpServerList(); +} + +void CMasterServer::ListenForHeartBeats() +{ + netaddr4 from; + char data[1024]; + int dataSize; + + // read udp data while there is data to read :) + while ((dataSize = m_UDPSocket.recv(&from, (char *)data, sizeof(data))) > 0) + { + // compare the received data size to the expected size + if (dataSize == HEARTBEAT_SIZE) + { + char *d = data; + int32 signature; + d = ReadInt32(d, &signature); + + // make sure the signature is correct + if (signature == HEARTBEAT_SIGNATURE) + { + CServerInfo info; + info.Deserialize(d); + + from.port = 8303; + info.SetAddress(&from); + + dbg_msg("got heartbeat", "IP: %i.%i.%i.%i:%i", (int)from.ip[0], (int)from.ip[1], (int)from.ip[2], (int)from.ip[3], from.port); + + dbg_msg("refresh", "okay. server count: %i", m_ServerCount); + + ProcessHeartBeat(info); + } + else + {} // unexpected signature + } + else + {} // unknown data received + } +} + +void CMasterServer::ProcessHeartBeat(CServerInfo info) +{ + // find the corresponding server info + CServerInfo *serverInfo = FindServerInfo(info.IP(), info.Port()); + + // if it isn't in the list already, try to get an unused slot + if (!serverInfo) + serverInfo = GetUnusedSlot(); + + // if we STILL don't have one, we're out of luck. + if (!serverInfo) + return; + + *serverInfo = info; + serverInfo->Refresh(m_CurrentTime); + + // mark the server list packet as old + m_ServerListPacketIsOld = true; +} + +CServerInfo *CMasterServer::FindServerInfo(int32 ip, int32 port) +{ + // for now, just loop over the array + for (int i = 0; i < m_ServerCount; i++) + { + CServerInfo *info = &m_Servers[i]; + if (info->IP() == ip && info->Port() == port) + return info; + } + + return 0x0; +} + +CServerInfo *CMasterServer::GetUnusedSlot() +{ + if (m_ServerCount == MAXSERVERS) + return 0x0; + else + return &m_Servers[m_ServerCount++]; +} + +void CMasterServer::CleanUpServerList() +{ + for (int i = 0; i < m_ServerCount; i++) + { + CServerInfo *serverInfo = &m_Servers[i]; + + // check if it's time to remove it from the list + if (serverInfo->LastRefresh() + HEARTBEAT_LIFETIME < m_CurrentTime) + { + if (i + 1 == m_ServerCount) + { + // if we're at the last one, just decrease m_ServerCount + --m_ServerCount; + } + else + { + // otherwise, copy the last slot here and then decrease i and m_ServerCount + *serverInfo = m_Servers[m_ServerCount - 1]; + --i; + --m_ServerCount; + } + + // mark the server list packet as old and outdated + m_ServerListPacketIsOld = true; + } + } +} + +void CMasterServer::ListenForServerListPolls() +{ + socket_tcp4 client; + + // accept clients while there are clients to be accepted + while (m_TCPSocket.accept(&client)) + { + // maybe we've prepared the packet already... it'd be silly to do it twice + if (m_ServerListPacketIsOld) + { + BuildServerListPacket(); + } + + // send the server list and then close the socket + client.send(m_ServerListPacket, m_ServerListPacketSize); + client.close(); + } +} + +void CMasterServer::BuildServerListPacket() +{ + char *d = m_ServerListPacket; + + d = WriteInt32(d, 'TWSL'); + d = WriteInt32(d, MASTERSERVER_VERSION); + + d = WriteInt32(d, m_ServerCount); + + for (int i = 0; i < m_ServerCount; i++) + { + CServerInfo *info = &m_Servers[i]; + d = info->Serialize(d); + } + + m_ServerListPacketSize = d - m_ServerListPacket; + m_ServerListPacketIsOld = false; +} diff --git a/masterserver/src/network.cpp b/masterserver/src/network.cpp new file mode 100644 index 00000000..7d557cdf --- /dev/null +++ b/masterserver/src/network.cpp @@ -0,0 +1,39 @@ +#include <cstring> +#include "common.h" +#include "network.h" + +char *WriteInt32(char *buffer, int32 value) +{ + buffer[0] = value >> 24; + buffer[1] = value >> 16; + buffer[2] = value >> 8; + buffer[3] = value; + + return buffer + sizeof(int32); +} + +char *WriteFixedString(char *buffer, const char *string, int strlen) +{ + memcpy(buffer, string, strlen); + + return buffer + strlen; +} + + + +char *ReadInt32(char *buffer, int32 *value) +{ + *value = buffer[0] << 24; + *value |= buffer[1] << 16; + *value |= buffer[2] << 8; + *value |= buffer[3]; + + return buffer + sizeof(int32); +} + +char *ReadFixedString(char *buffer, char *string, int strlen) +{ + memcpy(string, buffer, strlen); + + return buffer + strlen; +} |