summaryrefslogtreecommitdiff
path: root/src/network/core
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2007-01-12 14:30:01 +0000
committerrubidium <rubidium@openttd.org>2007-01-12 14:30:01 +0000
commitc48aa5db45e99981eff70be5f8406959dcba2237 (patch)
tree5b04486a0d687db7bc0de87c249ab1904e51c568 /src/network/core
parentbccef9f9485628982c78423e4791b04aea33227f (diff)
downloadopenttd-c48aa5db45e99981eff70be5f8406959dcba2237.tar.xz
(svn r8078) -Codechange: rewrite UDP part of the network code to make use classes. This is only one of the many steps to really cleanup the network code.
Diffstat (limited to 'src/network/core')
-rw-r--r--src/network/core/udp.cpp170
-rw-r--r--src/network/core/udp.h86
2 files changed, 172 insertions, 84 deletions
diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp
index 0776a2c50..ddc4cadfb 100644
--- a/src/network/core/udp.cpp
+++ b/src/network/core/udp.cpp
@@ -13,6 +13,12 @@
* @file udp.c Basic functions to receive and send UDP packets.
*/
+/** Initialize the sockets with an INVALID_SOCKET */
+NetworkUDPSocketHandler::NetworkUDPSocketHandler()
+{
+ this->udp = INVALID_SOCKET;
+}
+
/**
* Start listening on the given host and port.
* @param udp the place where the (references to the) UDP are stored
@@ -21,15 +27,15 @@
* @param broadcast whether to allow broadcast sending/receiving
* @return true if the listening succeeded
*/
-bool NetworkUDPListen(SOCKET *udp, const uint32 host, const uint16 port, const bool broadcast)
+bool NetworkUDPSocketHandler::Listen(const uint32 host, const uint16 port, const bool broadcast)
{
struct sockaddr_in sin;
/* Make sure socket is closed */
- NetworkUDPClose(udp);
+ this->Close();
- *udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (*udp == INVALID_SOCKET) {
+ this->udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (this->udp == INVALID_SOCKET) {
DEBUG(net, 0, "[udp] failed to start UDP listener");
return false;
}
@@ -38,9 +44,9 @@ bool NetworkUDPListen(SOCKET *udp, const uint32 host, const uint16 port, const b
{
unsigned long blocking = 1;
#ifndef BEOS_NET_SERVER
- ioctlsocket(*udp, FIONBIO, &blocking);
+ ioctlsocket(this->udp, FIONBIO, &blocking);
#else
- setsockopt(*udp, SOL_SOCKET, SO_NONBLOCK, &blocking, NULL);
+ setsockopt(this->udp, SOL_SOCKET, SO_NONBLOCK, &blocking, NULL);
#endif
}
@@ -49,7 +55,7 @@ bool NetworkUDPListen(SOCKET *udp, const uint32 host, const uint16 port, const b
sin.sin_addr.s_addr = host;
sin.sin_port = htons(port);
- if (bind(*udp, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
+ if (bind(this->udp, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
DEBUG(net, 0, "[udp] bind failed on %s:%i", inet_ntoa(*(struct in_addr *)&host), port);
return false;
}
@@ -58,7 +64,7 @@ bool NetworkUDPListen(SOCKET *udp, const uint32 host, const uint16 port, const b
/* Enable broadcast */
unsigned long val = 1;
#ifndef BEOS_NET_SERVER // will work around this, some day; maybe.
- setsockopt(*udp, SOL_SOCKET, SO_BROADCAST, (char *) &val , sizeof(val));
+ setsockopt(this->udp, SOL_SOCKET, SO_BROADCAST, (char *) &val , sizeof(val));
#endif
}
@@ -71,12 +77,12 @@ bool NetworkUDPListen(SOCKET *udp, const uint32 host, const uint16 port, const b
* Close the given UDP socket
* @param udp the socket to close
*/
-void NetworkUDPClose(SOCKET *udp)
+void NetworkUDPSocketHandler::Close()
{
- if (*udp == INVALID_SOCKET) return;
+ if (this->udp == INVALID_SOCKET) return;
- closesocket(*udp);
- *udp = INVALID_SOCKET;
+ closesocket(this->udp);
+ this->udp = INVALID_SOCKET;
}
@@ -86,14 +92,14 @@ void NetworkUDPClose(SOCKET *udp)
* @param p the packet to send
* @param recv the receiver (target) of the packet
*/
-void NetworkSendUDP_Packet(const SOCKET udp, Packet *p, const struct sockaddr_in *recv)
+void NetworkUDPSocketHandler::SendPacket(Packet *p, const struct sockaddr_in *recv)
{
int res;
NetworkSend_FillPacketSize(p);
/* Send the buffer */
- res = sendto(udp, (const char*)p->buffer, p->size, 0, (struct sockaddr *)recv, sizeof(*recv));
+ res = sendto(this->udp, (const char*)p->buffer, p->size, 0, (struct sockaddr *)recv, sizeof(*recv));
/* Check for any errors, but ignore it otherwise */
if (res == -1) DEBUG(net, 1, "[udp] sendto failed with: %i", GET_LAST_ERROR());
@@ -103,7 +109,7 @@ void NetworkSendUDP_Packet(const SOCKET udp, Packet *p, const struct sockaddr_in
* Receive a packet at UDP level
* @param udp the socket to receive the packet on
*/
-void NetworkUDPReceive(const SOCKET udp)
+void NetworkUDPSocketHandler::ReceivePackets()
{
struct sockaddr_in client_addr;
socklen_t client_len;
@@ -111,11 +117,13 @@ void NetworkUDPReceive(const SOCKET udp)
Packet p;
int packet_len;
+ if (this->udp == INVALID_SOCKET) return;
+
packet_len = sizeof(p.buffer);
client_len = sizeof(client_addr);
/* Try to receive anything */
- nbytes = recvfrom(udp, (char*)p.buffer, packet_len, 0, (struct sockaddr *)&client_addr, &client_len);
+ nbytes = recvfrom(this->udp, (char*)p.buffer, packet_len, 0, (struct sockaddr *)&client_addr, &client_len);
/* We got some bytes for the base header of the packet. */
if (nbytes > 2) {
@@ -135,7 +143,7 @@ void NetworkUDPReceive(const SOCKET udp)
p.next = NULL;
/* Handle the packet */
- NetworkHandleUDPPacket(udp, &p, &client_addr);
+ this->HandleUDPPacket(&p, &client_addr);
}
}
@@ -145,7 +153,7 @@ void NetworkUDPReceive(const SOCKET udp)
* @param p the packet to write the data to
* @param c the configuration to write the GRF ID and MD5 checksum from
*/
-void NetworkSend_GRFIdentifier(Packet *p, const GRFConfig *c)
+void NetworkUDPSocketHandler::Send_GRFIdentifier(Packet *p, const GRFConfig *c)
{
uint j;
NetworkSend_uint32(p, c->grfid);
@@ -156,16 +164,15 @@ void NetworkSend_GRFIdentifier(Packet *p, const GRFConfig *c)
/**
* Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet
- * @param cs the client state (for closing connect on out-of-bounds reading etc)
* @param p the packet to read the data from
* @param c the configuration to write the GRF ID and MD5 checksum to
*/
-void NetworkRecv_GRFIdentifier(NetworkClientState *cs, Packet *p, GRFConfig *c)
+void NetworkUDPSocketHandler::Recv_GRFIdentifier(Packet *p, GRFConfig *c)
{
uint j;
- c->grfid = NetworkRecv_uint32(cs, p);
+ c->grfid = NetworkRecv_uint32(&this->cs, p);
for (j = 0; j < sizeof(c->md5sum); j++) {
- c->md5sum[j] = NetworkRecv_uint8(cs, p);
+ c->md5sum[j] = NetworkRecv_uint8(&this->cs, p);
}
}
@@ -175,7 +182,7 @@ void NetworkRecv_GRFIdentifier(NetworkClientState *cs, Packet *p, GRFConfig *c)
* @param p the packet to write the data to
* @param info the NetworkGameInfo struct to serialize
*/
-void NetworkSend_NetworkGameInfo(Packet *p, const NetworkGameInfo *info)
+void NetworkUDPSocketHandler::Send_NetworkGameInfo(Packet *p, const NetworkGameInfo *info)
{
NetworkSend_uint8 (p, NETWORK_GAME_INFO_VERSION);
@@ -204,7 +211,7 @@ void NetworkSend_NetworkGameInfo(Packet *p, const NetworkGameInfo *info)
/* Send actual GRF Identifications */
for (c = info->grfconfig; c != NULL; c = c->next) {
- if (!HASBIT(c->flags, GCF_STATIC)) NetworkSend_GRFIdentifier(p, c);
+ if (!HASBIT(c->flags, GCF_STATIC)) this->Send_GRFIdentifier(p, c);
}
}
@@ -234,13 +241,12 @@ void NetworkSend_NetworkGameInfo(Packet *p, const NetworkGameInfo *info)
/**
* Deserializes the NetworkGameInfo struct from the packet
- * @param cs the client state (for closing connect on out-of-bounds reading etc)
* @param p the packet to read the data from
* @param info the NetworkGameInfo to deserialize into
*/
-void NetworkRecv_NetworkGameInfo(NetworkClientState *cs, Packet *p, NetworkGameInfo *info)
+void NetworkUDPSocketHandler::Recv_NetworkGameInfo(Packet *p, NetworkGameInfo *info)
{
- info->game_info_version = NetworkRecv_uint8(cs, p);
+ info->game_info_version = NetworkRecv_uint8(&this->cs, p);
/*
* Please observe the order.
@@ -254,12 +260,12 @@ void NetworkRecv_NetworkGameInfo(NetworkClientState *cs, Packet *p, NetworkGameI
case 4: {
GRFConfig **dst = &info->grfconfig;
uint i;
- uint num_grfs = NetworkRecv_uint8(cs, p);
+ uint num_grfs = NetworkRecv_uint8(&this->cs, p);
for (i = 0; i < num_grfs; i++) {
GRFConfig *c = CallocT<GRFConfig>(1);
- NetworkRecv_GRFIdentifier(cs, p, c);
- HandleIncomingNetworkGameInfoGRFConfig(c);
+ this->Recv_GRFIdentifier(p, c);
+ this->HandleIncomingNetworkGameInfoGRFConfig(c);
/* Append GRFConfig to the list */
*dst = c;
@@ -267,32 +273,98 @@ void NetworkRecv_NetworkGameInfo(NetworkClientState *cs, Packet *p, NetworkGameI
}
} /* Fallthrough */
case 3:
- info->game_date = NetworkRecv_uint32(cs, p);
- info->start_date = NetworkRecv_uint32(cs, p);
+ info->game_date = NetworkRecv_uint32(&this->cs, p);
+ info->start_date = NetworkRecv_uint32(&this->cs, p);
/* Fallthrough */
case 2:
- info->companies_max = NetworkRecv_uint8 (cs, p);
- info->companies_on = NetworkRecv_uint8 (cs, p);
- info->spectators_max = NetworkRecv_uint8 (cs, p);
+ info->companies_max = NetworkRecv_uint8 (&this->cs, p);
+ info->companies_on = NetworkRecv_uint8 (&this->cs, p);
+ info->spectators_max = NetworkRecv_uint8 (&this->cs, p);
/* Fallthrough */
case 1:
- NetworkRecv_string(cs, p, info->server_name, sizeof(info->server_name));
- NetworkRecv_string(cs, p, info->server_revision, sizeof(info->server_revision));
- info->server_lang = NetworkRecv_uint8 (cs, p);
- info->use_password = NetworkRecv_uint8 (cs, p);
- info->clients_max = NetworkRecv_uint8 (cs, p);
- info->clients_on = NetworkRecv_uint8 (cs, p);
- info->spectators_on = NetworkRecv_uint8 (cs, p);
+ NetworkRecv_string(&this->cs, p, info->server_name, sizeof(info->server_name));
+ NetworkRecv_string(&this->cs, p, info->server_revision, sizeof(info->server_revision));
+ info->server_lang = NetworkRecv_uint8 (&this->cs, p);
+ info->use_password = NetworkRecv_uint8 (&this->cs, p);
+ info->clients_max = NetworkRecv_uint8 (&this->cs, p);
+ info->clients_on = NetworkRecv_uint8 (&this->cs, p);
+ info->spectators_on = NetworkRecv_uint8 (&this->cs, p);
if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
- info->game_date = NetworkRecv_uint16(cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR;
- info->start_date = NetworkRecv_uint16(cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR;
+ info->game_date = NetworkRecv_uint16(&this->cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR;
+ info->start_date = NetworkRecv_uint16(&this->cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR;
}
- NetworkRecv_string(cs, p, info->map_name, sizeof(info->map_name));
- info->map_width = NetworkRecv_uint16(cs, p);
- info->map_height = NetworkRecv_uint16(cs, p);
- info->map_set = NetworkRecv_uint8 (cs, p);
- info->dedicated = (NetworkRecv_uint8 (cs, p) != 0);
+ NetworkRecv_string(&this->cs, p, info->map_name, sizeof(info->map_name));
+ info->map_width = NetworkRecv_uint16(&this->cs, p);
+ info->map_height = NetworkRecv_uint16(&this->cs, p);
+ info->map_set = NetworkRecv_uint8 (&this->cs, p);
+ info->dedicated = (NetworkRecv_uint8(&this->cs, p) != 0);
}
}
+/* Defines a simple (switch) case for each network packet */
+#define UDP_COMMAND(type) case type: this->NetworkPacketReceive_ ## type ## _command(p, client_addr); break;
+
+/**
+ * Handle an incoming packets by sending it to the correct function.
+ * @param p the received packet
+ * @param client_addr the sender of the packet
+ */
+void NetworkUDPSocketHandler::HandleUDPPacket(Packet *p, const struct sockaddr_in *client_addr)
+{
+ PacketUDPType type;
+
+ /* Fake a client, so we can see when there is an illegal packet */
+ this->cs.socket = INVALID_SOCKET;
+ this->cs.has_quit = false;
+
+ type = (PacketUDPType)NetworkRecv_uint8(&this->cs, p);
+
+ switch (this->cs.has_quit ? PACKET_UDP_END : type) {
+ UDP_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER);
+ UDP_COMMAND(PACKET_UDP_SERVER_RESPONSE);
+ UDP_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO);
+ UDP_COMMAND(PACKET_UDP_SERVER_DETAIL_INFO);
+ UDP_COMMAND(PACKET_UDP_SERVER_REGISTER);
+ UDP_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER);
+ UDP_COMMAND(PACKET_UDP_CLIENT_GET_LIST);
+ UDP_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST);
+ UDP_COMMAND(PACKET_UDP_SERVER_UNREGISTER);
+ UDP_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS);
+ UDP_COMMAND(PACKET_UDP_SERVER_NEWGRFS);
+
+ default:
+ if (!this->cs.has_quit) {
+ DEBUG(net, 0, "[udp] received invalid packet type %d from %s:%d", type, inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
+ } else {
+ DEBUG(net, 0, "[udp] received illegal packet from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
+ }
+ break;
+ }
+}
+
+/*
+ * Create stub implementations for all receive commands that only
+ * show a warning that the given command is not available for the
+ * socket where the packet came from.
+ */
+
+#define DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(type) \
+void NetworkUDPSocketHandler::NetworkPacketReceive_## type ##_command(\
+ Packet *p, const struct sockaddr_in *client_addr) { \
+ DEBUG(net, 0, "[udp] received packet on wrong port from %s:%d", \
+ inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); \
+}
+
+DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER);
+DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE);
+DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO);
+DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_DETAIL_INFO);
+DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_REGISTER);
+DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER);
+DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_LIST);
+DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST);
+DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_UNREGISTER);
+DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS);
+DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS);
+
#endif /* ENABLE_NETWORK */
diff --git a/src/network/core/udp.h b/src/network/core/udp.h
index 04bf198f9..755829600 100644
--- a/src/network/core/udp.h
+++ b/src/network/core/udp.h
@@ -9,6 +9,8 @@
#include "game.h"
#include "packet.h"
#include "../../newgrf_config.h"
+#include "../../debug.h"
+#include "../network_data.h"
/**
* @file udp.h Basic functions to receive and send UDP packets.
@@ -71,28 +73,8 @@
* 1+ 1 whether the server is dedicated (0 = no, 1 = yes)
*/
-///** Sending/receiving of UDP packets **////
-
-bool NetworkUDPListen(SOCKET *udp, const uint32 host, const uint16 port, const bool broadcast);
-void NetworkUDPClose(SOCKET *udp);
-
-void NetworkSendUDP_Packet(const SOCKET udp, Packet *p, const struct sockaddr_in *recv);
-void NetworkUDPReceive(const SOCKET udp);
-
-/**
- * Function that is called for every received UDP packet.
- * @param udp the socket the packet is received on
- * @param packet the received packet
- * @param client_addr the address of the sender of the packet
- */
-void NetworkHandleUDPPacket(const SOCKET udp, Packet *p, const struct sockaddr_in *client_addr);
-
-
-///** Sending/receiving of (large) chuncks of UDP packets **////
-
-
/** Enum with all types of UDP packets. The order MUST not be changed **/
-enum {
+enum PacketUDPType {
PACKET_UDP_CLIENT_FIND_SERVER, ///< Queries a game server for game information
PACKET_UDP_SERVER_RESPONSE, ///< Reply of the game server with game information
PACKET_UDP_CLIENT_DETAIL_INFO, ///< Queries a game server about details of the game, such as companies
@@ -107,20 +89,54 @@ enum {
PACKET_UDP_END ///< Must ALWAYS be on the end of this list!! (period)
};
-void NetworkSend_GRFIdentifier(Packet *p, const GRFConfig *c);
-void NetworkSend_NetworkGameInfo(Packet *p, const NetworkGameInfo *info);
-
-void NetworkRecv_GRFIdentifier(NetworkClientState *cs, Packet *p, GRFConfig *c);
-void NetworkRecv_NetworkGameInfo(NetworkClientState *cs, Packet *p, NetworkGameInfo *info);
-
-/**
- * Function that is called for every GRFConfig that is read when receiving
- * a NetworkGameInfo. Only grfid and md5sum are set, the rest is zero. This
- * function must set all appropriate fields. This GRF is later appended to
- * the grfconfig list of the NetworkGameInfo.
- * @param config the GRF to handle
- */
-void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config);
+#define DECLARE_UDP_RECEIVE_COMMAND(type) virtual void NetworkPacketReceive_## type ##_command(Packet *p, const struct sockaddr_in *)
+
+class NetworkUDPSocketHandler {
+private:
+ SOCKET udp;
+protected:
+ NetworkClientState cs;
+ /* Declare all possible packets here. If it can be received by the
+ * a specific handler, it has to be implemented. */
+ DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER);
+ DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE);
+ DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO);
+ DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_DETAIL_INFO);
+ DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_REGISTER);
+ DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER);
+ DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_LIST);
+ DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST);
+ DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_UNREGISTER);
+ DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS);
+ DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS);
+
+ void HandleUDPPacket(Packet *p, const struct sockaddr_in *client_addr);
+
+ /**
+ * Function that is called for every GRFConfig that is read when receiving
+ * a NetworkGameInfo. Only grfid and md5sum are set, the rest is zero. This
+ * function must set all appropriate fields. This GRF is later appended to
+ * the grfconfig list of the NetworkGameInfo.
+ * @param config the GRF to handle
+ */
+ virtual void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) { NOT_REACHED(); }
+public:
+ NetworkUDPSocketHandler();
+ virtual ~NetworkUDPSocketHandler() { this->Close(); }
+
+ bool IsListening() { return this->udp != INVALID_SOCKET; }
+ bool Listen(uint32 host, uint16 port, bool broadcast);
+ void Close();
+
+ void SendPacket(Packet *p, const struct sockaddr_in *recv);
+ void ReceivePackets();
+
+ void Send_GRFIdentifier(Packet *p, const GRFConfig *c);
+ void Send_NetworkGameInfo(Packet *p, const NetworkGameInfo *info);
+
+ void Recv_GRFIdentifier(Packet *p, GRFConfig *c);
+ void Recv_NetworkGameInfo(Packet *p, NetworkGameInfo *info);
+};
#endif /* ENABLE_NETWORK */