(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.
authorrubidium
Fri, 12 Jan 2007 14:30:01 +0000
changeset 5870 86e55167c9e3
parent 5869 33d51b7f639d
child 5871 52a265080dab
(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.
src/network/core/udp.cpp
src/network/core/udp.h
src/network/network.cpp
src/network/network.h
src/network/network_data.h
src/network/network_udp.cpp
src/network/network_udp.h
src/openttd.cpp
--- a/src/network/core/udp.cpp	Fri Jan 12 14:28:00 2007 +0000
+++ b/src/network/core/udp.cpp	Fri Jan 12 14:30:01 2007 +0000
@@ -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 @@
 	{
 		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 @@
 	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 @@
 		/* 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 @@
  * 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 @@
  * @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 @@
  * 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 @@
 	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 @@
 		p.next = NULL;
 
 		/* Handle the packet */
-		NetworkHandleUDPPacket(udp, &p, &client_addr);
+		this->HandleUDPPacket(&p, &client_addr);
 	}
 }
 
@@ -145,7 +153,7 @@
  * @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 @@
 
 /**
  * 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 @@
  * @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 @@
 
 		/* 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 @@
 
 /**
  * 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 @@
 		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 @@
 			}
 		} /* 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 */
--- a/src/network/core/udp.h	Fri Jan 12 14:28:00 2007 +0000
+++ b/src/network/core/udp.h	Fri Jan 12 14:30:01 2007 +0000
@@ -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 @@
 	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);
+#define DECLARE_UDP_RECEIVE_COMMAND(type) virtual void NetworkPacketReceive_## type ##_command(Packet *p, const struct sockaddr_in *)
 
-/**
- * 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);
+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 */
 
--- a/src/network/network.cpp	Fri Jan 12 14:28:00 2007 +0000
+++ b/src/network/network.cpp	Fri Jan 12 14:30:01 2007 +0000
@@ -41,9 +41,9 @@
 // global variables (declared in network_data.h)
 CommandPacket *_local_command_queue;
 
-SOCKET _udp_client_socket; // udp client socket
-SOCKET _udp_server_socket; // udp server socket
-SOCKET _udp_master_socket; // udp master socket
+extern NetworkUDPSocketHandler *_udp_client_socket; ///< udp client socket
+extern NetworkUDPSocketHandler *_udp_server_socket; ///< udp server socket
+extern NetworkUDPSocketHandler *_udp_master_socket; ///< udp master socket
 
 // Here we keep track of the clients
 //  (and the client uses [0] for his own communication)
@@ -842,7 +842,7 @@
 		closesocket(_listensocket);
 		_listensocket = INVALID_SOCKET;
 		DEBUG(net, 1, "Closed listener");
-		NetworkUDPStop();
+		NetworkUDPCloseAll();
 	}
 }
 
@@ -958,7 +958,7 @@
 	_network_last_port = port;
 
 	NetworkDisconnect();
-	NetworkUDPStop();
+	NetworkUDPCloseAll();
 	NetworkInitialize();
 
 	// Try to connect
@@ -1034,7 +1034,7 @@
 
 	// Try to start UDP-server
 	_network_udp_server = true;
-	_network_udp_server = NetworkUDPListen(&_udp_server_socket, _network_server_bind_ip, _network_server_port, false);
+	_network_udp_server = _udp_server_socket->Listen(_network_server_bind_ip, _network_server_port, false);
 
 	_network_server = true;
 	_networking = true;
@@ -1270,12 +1270,10 @@
 void NetworkUDPGameLoop(void)
 {
 	if (_network_udp_server) {
-		NetworkUDPReceive(_udp_server_socket);
-		if (_udp_master_socket != INVALID_SOCKET) {
-			NetworkUDPReceive(_udp_master_socket);
-		}
-	} else if (_udp_client_socket != INVALID_SOCKET) {
-		NetworkUDPReceive(_udp_client_socket);
+		_udp_server_socket->ReceivePackets();
+		_udp_master_socket->ReceivePackets();
+	} else {
+		_udp_client_socket->ReceivePackets();
 		if (_network_udp_broadcast > 0) _network_udp_broadcast--;
 	}
 }
@@ -1390,7 +1388,7 @@
 void NetworkShutDown(void)
 {
 	NetworkDisconnect();
-	NetworkUDPStop();
+	NetworkUDPShutdown();
 
 	DEBUG(net, 3, "[core] shutting down network");
 
--- a/src/network/network.h	Fri Jan 12 14:28:00 2007 +0000
+++ b/src/network/network.h	Fri Jan 12 14:30:01 2007 +0000
@@ -179,7 +179,7 @@
 void CheckMinPlayers(void);
 
 void NetworkStartUp(void);
-void NetworkUDPStop(void);
+void NetworkUDPCloseAll();
 void NetworkShutDown(void);
 void NetworkGameLoop(void);
 void NetworkUDPGameLoop(void);
--- a/src/network/network_data.h	Fri Jan 12 14:28:00 2007 +0000
+++ b/src/network/network_data.h	Fri Jan 12 14:30:01 2007 +0000
@@ -123,10 +123,6 @@
 // following externs are instantiated at network.cpp
 extern CommandPacket *_local_command_queue;
 
-extern SOCKET _udp_client_socket; // udp client socket
-extern SOCKET _udp_server_socket; // udp server socket
-extern SOCKET _udp_master_socket; // udp master socket
-
 // Here we keep track of the clients
 //  (and the client uses [0] for his own communication)
 extern NetworkClientState _clients[MAX_CLIENTS];
--- a/src/network/network_udp.cpp	Fri Jan 12 14:28:00 2007 +0000
+++ b/src/network/network_udp.cpp	Fri Jan 12 14:30:01 2007 +0000
@@ -28,11 +28,42 @@
 	ADVERTISE_RETRY_TIMES     =     3  // give up readvertising after this much failed retries
 };
 
-#define DEF_UDP_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(Packet *p, const struct sockaddr_in *client_addr)
+NetworkUDPSocketHandler *_udp_client_socket; ///< udp client socket
+NetworkUDPSocketHandler *_udp_server_socket; ///< udp server socket
+NetworkUDPSocketHandler *_udp_master_socket; ///< udp master socket
 
-static NetworkClientState _udp_cs;
+#define DEF_UDP_RECEIVE_COMMAND(cls, type) void cls ##NetworkUDPSocketHandler::NetworkPacketReceive_ ## type ## _command(Packet *p, const struct sockaddr_in *client_addr)
 
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER)
+///*** Communication with the masterserver ***/
+
+class MasterNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
+protected:
+	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER);
+public:
+	virtual ~MasterNetworkUDPSocketHandler() {}
+};
+
+DEF_UDP_RECEIVE_COMMAND(Master, PACKET_UDP_MASTER_ACK_REGISTER)
+{
+	_network_advertise_retries = 0;
+	DEBUG(net, 2, "[udp] advertising on master server successfull");
+
+	/* We are advertised, but we don't want to! */
+	if (!_network_advertise) NetworkUDPRemoveAdvertise();
+}
+
+///*** Communication with clients (we are server) ***/
+
+class ServerNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
+protected:
+	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER);
+	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO);
+	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS);
+public:
+	virtual ~ServerNetworkUDPSocketHandler() {}
+};
+
+DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_FIND_SERVER)
 {
 	Packet *packet;
 	// Just a fail-safe.. should never happen
@@ -50,106 +81,17 @@
 	_network_game_info.spectators_on = NetworkSpectatorCount();
 	_network_game_info.grfconfig     = _grfconfig;
 
-	NetworkSend_NetworkGameInfo(packet, &_network_game_info);
+	this->Send_NetworkGameInfo(packet, &_network_game_info);
 
 	// Let the client know that we are here
-	NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
+	this->SendPacket(packet, client_addr);
 
 	free(packet);
 
 	DEBUG(net, 2, "[udp] queried from '%s'", inet_ntoa(client_addr->sin_addr));
 }
 
-void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
-{
-	/* Find the matching GRF file */
-	const GRFConfig *f = FindGRFConfig(config->grfid, config->md5sum);
-	if (f == NULL) {
-		/* Don't know the GRF, so mark game incompatible and the (possibly)
-		 * already resolved name for this GRF (another server has sent the
-		 * name of the GRF already */
-		config->name     = FindUnknownGRFName(config->grfid, config->md5sum, true);
-		SETBIT(config->flags, GCF_NOT_FOUND);
-	} else {
-		config->filename = f->filename;
-		config->name     = f->name;
-		config->info     = f->info;
-	}
-	SETBIT(config->flags, GCF_COPY);
-}
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE)
-{
-	extern const char _openttd_revision[];
-	NetworkGameList *item;
-
-	// Just a fail-safe.. should never happen
-	if (_network_udp_server || _udp_cs.has_quit) return;
-
-	DEBUG(net, 4, "[udp] server response from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
-
-	// Find next item
-	item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port));
-
-	NetworkRecv_NetworkGameInfo(&_udp_cs, p, &item->info);
-
-	item->info.compatible = true;
-	{
-		/* Checks whether there needs to be a request for names of GRFs and makes
-		 * the request if necessary. GRFs that need to be requested are the GRFs
-		 * that do not exist on the clients system and we do not have the name
-		 * resolved of, i.e. the name is still UNKNOWN_GRF_NAME_PLACEHOLDER.
-		 * The in_request array and in_request_count are used so there is no need
-		 * to do a second loop over the GRF list, which can be relatively expensive
-		 * due to the string comparisons. */
-		const GRFConfig *in_request[NETWORK_MAX_GRF_COUNT];
-		const GRFConfig *c;
-		uint in_request_count = 0;
-		struct sockaddr_in out_addr;
-
-		for (c = item->info.grfconfig; c != NULL; c = c->next) {
-			if (HASBIT(c->flags, GCF_NOT_FOUND)) item->info.compatible = false;
-			if (!HASBIT(c->flags, GCF_NOT_FOUND) || strcmp(c->name, UNKNOWN_GRF_NAME_PLACEHOLDER) != 0) continue;
-			in_request[in_request_count] = c;
-			in_request_count++;
-		}
-
-		if (in_request_count > 0) {
-			/* There are 'unknown' GRFs, now send a request for them */
-			uint i;
-			Packet *packet = NetworkSend_Init(PACKET_UDP_CLIENT_GET_NEWGRFS);
-
-			NetworkSend_uint8 (packet, in_request_count);
-			for (i = 0; i < in_request_count; i++) {
-				NetworkSend_GRFIdentifier(packet, in_request[i]);
-			}
-
-			out_addr.sin_family      = AF_INET;
-			out_addr.sin_port        = htons(item->port);
-			out_addr.sin_addr.s_addr = item->ip;
-			NetworkSendUDP_Packet(_udp_client_socket, packet, &out_addr);
-			free(packet);
-		}
-	}
-
-	if (item->info.server_lang >= NETWORK_NUM_LANGUAGES) item->info.server_lang = 0;
-	if (item->info.map_set >= NUM_LANDSCAPE ) item->info.map_set = 0;
-
-	if (item->info.hostname[0] == '\0')
-		snprintf(item->info.hostname, sizeof(item->info.hostname), "%s", inet_ntoa(client_addr->sin_addr));
-
-	/* Check if we are allowed on this server based on the revision-match */
-	item->info.version_compatible =
-		strcmp(item->info.server_revision, _openttd_revision) == 0 ||
-		strcmp(item->info.server_revision, NOREV_STRING) == 0;
-	item->info.compatible &= item->info.version_compatible; // Already contains match for GRFs
-
-	item->online = true;
-
-	UpdateNetworkGameWindow(false);
-}
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO)
+DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_DETAIL_INFO)
 {
 	NetworkClientState *cs;
 	NetworkClientInfo *ci;
@@ -250,46 +192,10 @@
 	/* Indicates end of client list */
 	NetworkSend_uint8(packet, 0);
 
-	NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
-
+	this->SendPacket(packet, client_addr);
 	free(packet);
 }
 
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST)
-{
-	int i;
-	struct in_addr ip;
-	uint16 port;
-	uint8 ver;
-
-	/* packet begins with the protocol version (uint8)
-	 * then an uint16 which indicates how many
-	 * ip:port pairs are in this packet, after that
-	 * an uint32 (ip) and an uint16 (port) for each pair
-	 */
-
-	ver = NetworkRecv_uint8(&_udp_cs, p);
-
-	if (_udp_cs.has_quit) return;
-
-	if (ver == 1) {
-		for (i = NetworkRecv_uint16(&_udp_cs, p); i != 0 ; i--) {
-			ip.s_addr = TO_LE32(NetworkRecv_uint32(&_udp_cs, p));
-			port = NetworkRecv_uint16(&_udp_cs, p);
-			NetworkUDPQueryServer(inet_ntoa(ip), port);
-		}
-	}
-}
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER)
-{
-	_network_advertise_retries = 0;
-	DEBUG(net, 2, "[udp] advertising on master server successfull");
-
-	/* We are advertised, but we don't want to! */
-	if (!_network_advertise) NetworkUDPRemoveAdvertise();
-}
-
 /**
  * A client has requested the names of some NewGRFs.
  *
@@ -303,7 +209,7 @@
  * in_reply and in_reply_count are used to keep a list of GRFs to
  * send in the reply.
  */
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS)
+DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_GET_NEWGRFS)
 {
 	uint8 num_grfs;
 	uint i;
@@ -313,19 +219,16 @@
 	uint8 in_reply_count = 0;
 	uint packet_len = 0;
 
-	/* Just a fail-safe.. should never happen */
-	if (_udp_cs.has_quit) return;
-
 	DEBUG(net, 6, "[udp] newgrf data request from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
 
-	num_grfs = NetworkRecv_uint8 (&_udp_cs, p);
+	num_grfs = NetworkRecv_uint8 (&this->cs, p);
 	if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
 
 	for (i = 0; i < num_grfs; i++) {
 		GRFConfig c;
 		const GRFConfig *f;
 
-		NetworkRecv_GRFIdentifier(&_udp_cs, p, &c);
+		this->Recv_GRFIdentifier(p, &c);
 
 		/* Find the matching GRF file */
 		f = FindGRFConfig(c.grfid, c.md5sum);
@@ -353,26 +256,132 @@
 		/* The name could be an empty string, if so take the filename */
 		ttd_strlcpy(name, (in_reply[i]->name != NULL && strlen(in_reply[i]->name) > 0) ?
 				in_reply[i]->name : in_reply[i]->filename, sizeof(name));
-	 	NetworkSend_GRFIdentifier(packet, in_reply[i]);
+	 	this->Send_GRFIdentifier(packet, in_reply[i]);
 		NetworkSend_string(packet, name);
 	}
 
-	NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
+	this->SendPacket(packet, client_addr);
 	free(packet);
 }
 
+///*** Communication with servers (we are client) ***/
+
+class ClientNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
+protected:
+	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE);
+	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST);
+	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS);
+	virtual void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config);
+public:
+	virtual ~ClientNetworkUDPSocketHandler() {}
+};
+
+DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_RESPONSE)
+{
+	extern const char _openttd_revision[];
+	NetworkGameList *item;
+
+	// Just a fail-safe.. should never happen
+	if (_network_udp_server) return;
+
+	DEBUG(net, 4, "[udp] server response from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
+
+	// Find next item
+	item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port));
+
+	this->Recv_NetworkGameInfo(p, &item->info);
+
+	item->info.compatible = true;
+	{
+		/* Checks whether there needs to be a request for names of GRFs and makes
+		 * the request if necessary. GRFs that need to be requested are the GRFs
+		 * that do not exist on the clients system and we do not have the name
+		 * resolved of, i.e. the name is still UNKNOWN_GRF_NAME_PLACEHOLDER.
+		 * The in_request array and in_request_count are used so there is no need
+		 * to do a second loop over the GRF list, which can be relatively expensive
+		 * due to the string comparisons. */
+		const GRFConfig *in_request[NETWORK_MAX_GRF_COUNT];
+		const GRFConfig *c;
+		uint in_request_count = 0;
+		struct sockaddr_in out_addr;
+
+		for (c = item->info.grfconfig; c != NULL; c = c->next) {
+			if (HASBIT(c->flags, GCF_NOT_FOUND)) item->info.compatible = false;
+			if (!HASBIT(c->flags, GCF_NOT_FOUND) || strcmp(c->name, UNKNOWN_GRF_NAME_PLACEHOLDER) != 0) continue;
+			in_request[in_request_count] = c;
+			in_request_count++;
+		}
+
+		if (in_request_count > 0) {
+			/* There are 'unknown' GRFs, now send a request for them */
+			uint i;
+			Packet *packet = NetworkSend_Init(PACKET_UDP_CLIENT_GET_NEWGRFS);
+
+			NetworkSend_uint8 (packet, in_request_count);
+			for (i = 0; i < in_request_count; i++) {
+				this->Send_GRFIdentifier(packet, in_request[i]);
+			}
+
+			out_addr.sin_family      = AF_INET;
+			out_addr.sin_port        = htons(item->port);
+			out_addr.sin_addr.s_addr = item->ip;
+			this->SendPacket(packet, &out_addr);
+			free(packet);
+		}
+	}
+
+	if (item->info.server_lang >= NETWORK_NUM_LANGUAGES) item->info.server_lang = 0;
+	if (item->info.map_set >= NUM_LANDSCAPE ) item->info.map_set = 0;
+
+	if (item->info.hostname[0] == '\0')
+		snprintf(item->info.hostname, sizeof(item->info.hostname), "%s", inet_ntoa(client_addr->sin_addr));
+
+	/* Check if we are allowed on this server based on the revision-match */
+	item->info.version_compatible =
+		strcmp(item->info.server_revision, _openttd_revision) == 0 ||
+		strcmp(item->info.server_revision, NOREV_STRING) == 0;
+	item->info.compatible &= item->info.version_compatible; // Already contains match for GRFs
+
+	item->online = true;
+
+	UpdateNetworkGameWindow(false);
+}
+
+DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_MASTER_RESPONSE_LIST)
+{
+	int i;
+	struct in_addr ip;
+	uint16 port;
+	uint8 ver;
+
+	/* packet begins with the protocol version (uint8)
+	 * then an uint16 which indicates how many
+	 * ip:port pairs are in this packet, after that
+	 * an uint32 (ip) and an uint16 (port) for each pair
+	 */
+
+	ver = NetworkRecv_uint8(&this->cs, p);
+
+	if (this->cs.has_quit) return;
+
+	if (ver == 1) {
+		for (i = NetworkRecv_uint16(&this->cs, p); i != 0 ; i--) {
+			ip.s_addr = TO_LE32(NetworkRecv_uint32(&this->cs, p));
+			port = NetworkRecv_uint16(&this->cs, p);
+			NetworkUDPQueryServer(inet_ntoa(ip), port);
+		}
+	}
+}
+
 /** The return of the client's request of the names of some NewGRFs */
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS)
+DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_NEWGRFS)
 {
 	uint8 num_grfs;
 	uint i;
 
-	/* Just a fail-safe.. should never happen */
-	if (_udp_cs.has_quit) return;
+	DEBUG(net, 6, "[udp] newgrf data reply from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
 
-	DEBUG(net, 6, "[udp] newgrf data reply from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
-
-	num_grfs = NetworkRecv_uint8 (&_udp_cs, p);
+	num_grfs = NetworkRecv_uint8 (&this->cs, p);
 	if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
 
 	for (i = 0; i < num_grfs; i++) {
@@ -380,8 +389,8 @@
 		char name[NETWORK_GRF_NAME_LENGTH];
 		GRFConfig c;
 
-		NetworkRecv_GRFIdentifier(&_udp_cs, p, &c);
-		NetworkRecv_string(&_udp_cs, p, name, sizeof(name));
+		this->Recv_GRFIdentifier(p, &c);
+		NetworkRecv_string(&this->cs, p, name, sizeof(name));
 
 		/* An empty name is not possible under normal circumstances
 		 * and causes problems when showing the NewGRF list. */
@@ -397,72 +406,39 @@
 	}
 }
 
-/**
- * Every type of UDP packet should only be received by a single socket;
- * The socket communicating with the masterserver should receive the
- * game information of some 'random' host.
- */
-typedef struct NetworkUDPPacketAndSocket {
-	void (*callback)(Packet *p, const struct sockaddr_in *client_addr);
-	SOCKET *incoming_socket;
-} NetworkUPDPacketAndSocket;
-
-static const NetworkUPDPacketAndSocket _network_udp_packet[PACKET_UDP_END] = {
-	{ RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER),   &_udp_server_socket },
-	{ RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE),      &_udp_client_socket },
-	{ RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO),   &_udp_server_socket },
-	{ NULL,                                             NULL                },
-	{ NULL,                                             NULL                },
-	{ RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER),  &_udp_master_socket },
-	{ NULL,                                             NULL                },
-	{ RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST), &_udp_client_socket },
-	{ NULL,                                             NULL                },
-	{ RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS),   &_udp_server_socket },
-	{ RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS),       &_udp_client_socket },
-};
-
-void NetworkHandleUDPPacket(const SOCKET udp, Packet *p, const struct sockaddr_in *client_addr)
+void ClientNetworkUDPSocketHandler::HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
 {
-	byte type;
-
-	/* Fake a client, so we can see when there is an illegal packet */
-	_udp_cs.socket = INVALID_SOCKET;
-	_udp_cs.has_quit = false;
-
-	type = NetworkRecv_uint8(&_udp_cs, p);
-
-	if (type < PACKET_UDP_END && *_network_udp_packet[type].incoming_socket == udp && !_udp_cs.has_quit) {
-		_network_udp_packet[type].callback(p, client_addr);
+	/* Find the matching GRF file */
+	const GRFConfig *f = FindGRFConfig(config->grfid, config->md5sum);
+	if (f == NULL) {
+		/* Don't know the GRF, so mark game incompatible and the (possibly)
+		 * already resolved name for this GRF (another server has sent the
+		 * name of the GRF already */
+		config->name     = FindUnknownGRFName(config->grfid, config->md5sum, true);
+		SETBIT(config->flags, GCF_NOT_FOUND);
 	} else {
-		if (*_network_udp_packet[type].incoming_socket != udp) {
-			DEBUG(net, 0, "[udp] received packet on wrong port from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
-		} else if (!_udp_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));
-		}
+		config->filename = f->filename;
+		config->name     = f->name;
+		config->info     = f->info;
 	}
+	SETBIT(config->flags, GCF_COPY);
 }
 
-
 // Close UDP connection
-void NetworkUDPStop(void)
+void NetworkUDPCloseAll(void)
 {
 	DEBUG(net, 1, "[udp] closed listeners");
 
-	if (_network_udp_server) {
-		NetworkUDPClose(&_udp_server_socket);
-		NetworkUDPClose(&_udp_master_socket);
-	} else {
-		NetworkUDPClose(&_udp_client_socket);
-	}
+	_udp_server_socket->Close();
+	_udp_master_socket->Close();
+	_udp_client_socket->Close();
 
 	_network_udp_server = false;
 	_network_udp_broadcast = 0;
 }
 
 // Broadcast to all ips
-static void NetworkUDPBroadCast(SOCKET udp)
+static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket)
 {
 	Packet* p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER);
 	uint i;
@@ -476,7 +452,7 @@
 
 		DEBUG(net, 4, "[udp] broadcasting to %s", inet_ntoa(out_addr.sin_addr));
 
-		NetworkSendUDP_Packet(udp, p, &out_addr);
+		socket->SendPacket(p, &out_addr);
 	}
 
 	free(p);
@@ -489,9 +465,9 @@
 	struct sockaddr_in out_addr;
 	Packet *p;
 
-	if (_udp_client_socket == INVALID_SOCKET)
-		if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
-			return;
+	if (!_udp_client_socket->IsListening()) {
+		if (!_udp_client_socket->Listen(0, 0, true)) return;
+	}
 
 	p = NetworkSend_Init(PACKET_UDP_CLIENT_GET_LIST);
 
@@ -502,7 +478,7 @@
 	// packet only contains protocol version
 	NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
 
-	NetworkSendUDP_Packet(_udp_client_socket, p, &out_addr);
+	_udp_client_socket->SendPacket(p, &out_addr);
 
 	DEBUG(net, 2, "[udp] master server queried at %s:%d", inet_ntoa(out_addr.sin_addr),ntohs(out_addr.sin_port));
 
@@ -516,9 +492,9 @@
 	if (_network_udp_broadcast > 0) return;
 
 	// No UDP-socket yet..
-	if (_udp_client_socket == INVALID_SOCKET)
-		if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
-			return;
+	if (!_udp_client_socket->IsListening()) {
+		if (!_udp_client_socket->Listen(0, 0, true)) return;
+	}
 
 	DEBUG(net, 0, "[udp] searching server");
 
@@ -533,9 +509,9 @@
 	NetworkGameList *item;
 
 	// No UDP-socket yet..
-	if (_udp_client_socket == INVALID_SOCKET)
-		if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
-			return NULL;
+	if (!_udp_client_socket->IsListening()) {
+		if (!_udp_client_socket->Listen(0, 0, true)) return NULL;
+	}
 
 	out_addr.sin_family = AF_INET;
 	out_addr.sin_port = htons(port);
@@ -551,7 +527,7 @@
 	// Init the packet
 	p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER);
 
-	NetworkSendUDP_Packet(_udp_client_socket, p, &out_addr);
+	_udp_client_socket->SendPacket(p, &out_addr);
 
 	free(p);
 
@@ -569,9 +545,9 @@
 	if (!_networking || !_network_server || !_network_udp_server) return;
 
 	/* check for socket */
-	if (_udp_master_socket == INVALID_SOCKET)
-		if (!NetworkUDPListen(&_udp_master_socket, _network_server_bind_ip, 0, false))
-			return;
+	if (!_udp_master_socket->IsListening()) {
+		if (!_udp_master_socket->Listen(0, 0, false)) return;
+	}
 
 	DEBUG(net, 1, "[udp] removing advertise from master server");
 
@@ -585,7 +561,7 @@
 	/* Packet is: Version, server_port */
 	NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
 	NetworkSend_uint16(p, _network_server_port);
-	NetworkSendUDP_Packet(_udp_master_socket, p, &out_addr);
+	_udp_master_socket->SendPacket(p, &out_addr);
 
 	free(p);
 }
@@ -602,9 +578,9 @@
 		return;
 
 	/* check for socket */
-	if (_udp_master_socket == INVALID_SOCKET)
-		if (!NetworkUDPListen(&_udp_master_socket, _network_server_bind_ip, 0, false))
-			return;
+	if (!_udp_master_socket->IsListening()) {
+		if (!_udp_master_socket->Listen(0, 0, false)) return;
+	}
 
 	if (_network_need_advertise) {
 		_network_need_advertise = false;
@@ -637,19 +613,28 @@
 	NetworkSend_string(p, NETWORK_MASTER_SERVER_WELCOME_MESSAGE);
 	NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
 	NetworkSend_uint16(p, _network_server_port);
-	NetworkSendUDP_Packet(_udp_master_socket, p, &out_addr);
+	_udp_master_socket->SendPacket(p, &out_addr);
 
 	free(p);
 }
 
 void NetworkUDPInitialize(void)
 {
-	_udp_client_socket = INVALID_SOCKET;
-	_udp_server_socket = INVALID_SOCKET;
-	_udp_master_socket = INVALID_SOCKET;
+	_udp_client_socket = new ClientNetworkUDPSocketHandler();
+	_udp_server_socket = new ServerNetworkUDPSocketHandler();
+	_udp_master_socket = new MasterNetworkUDPSocketHandler();
 
 	_network_udp_server = false;
 	_network_udp_broadcast = 0;
 }
 
+void NetworkUDPShutdown(void)
+{
+	NetworkUDPCloseAll();
+
+	delete _udp_client_socket;
+	delete _udp_server_socket;
+	delete _udp_master_socket;
+}
+
 #endif /* ENABLE_NETWORK */
--- a/src/network/network_udp.h	Fri Jan 12 14:28:00 2007 +0000
+++ b/src/network/network_udp.h	Fri Jan 12 14:30:01 2007 +0000
@@ -11,6 +11,7 @@
 NetworkGameList *NetworkUDPQueryServer(const char* host, unsigned short port);
 void NetworkUDPAdvertise(void);
 void NetworkUDPRemoveAdvertise(void);
+void NetworkUDPShutdown(void);
 
 #endif /* ENABLE_NETWORK */
 
--- a/src/openttd.cpp	Fri Jan 12 14:28:00 2007 +0000
+++ b/src/openttd.cpp	Fri Jan 12 14:30:01 2007 +0000
@@ -748,10 +748,10 @@
 		if (_networking) {
 			if (_network_server && (new_mode == SM_LOAD || new_mode == SM_NEWGAME)) {
 				NetworkReboot();
-				NetworkUDPStop();
+				NetworkUDPCloseAll();
 			} else {
 				NetworkDisconnect();
-				NetworkUDPStop();
+				NetworkUDPCloseAll();
 			}
 		}