src/network/network_udp.cpp
changeset 5870 86e55167c9e3
parent 5838 9c3129cb019b
child 5875 4a1391019791
--- 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 */