src/network/network_udp.cpp
changeset 5619 9f5a7152403a
parent 5587 167d9a91ef02
child 5624 6afe9d27430a
equal deleted inserted replaced
5618:d3e2c2c13e17 5619:9f5a7152403a
    26 	ADVERTISE_NORMAL_INTERVAL = 30000, // interval between advertising in ticks (15 minutes)
    26 	ADVERTISE_NORMAL_INTERVAL = 30000, // interval between advertising in ticks (15 minutes)
    27 	ADVERTISE_RETRY_INTERVAL  =   300, // readvertise when no response after this many ticks (9 seconds)
    27 	ADVERTISE_RETRY_INTERVAL  =   300, // readvertise when no response after this many ticks (9 seconds)
    28 	ADVERTISE_RETRY_TIMES     =     3  // give up readvertising after this much failed retries
    28 	ADVERTISE_RETRY_TIMES     =     3  // give up readvertising after this much failed retries
    29 };
    29 };
    30 
    30 
    31 #define DEF_UDP_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(Packet *p, const struct sockaddr_in *client_addr)
    31 NetworkUDPSocketHandler *_udp_client_socket; ///< udp client socket
    32 
    32 NetworkUDPSocketHandler *_udp_server_socket; ///< udp server socket
    33 static NetworkClientState _udp_cs;
    33 NetworkUDPSocketHandler *_udp_master_socket; ///< udp master socket
    34 
    34 
    35 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER)
    35 #define DEF_UDP_RECEIVE_COMMAND(cls, type) void cls ##NetworkUDPSocketHandler::NetworkPacketReceive_ ## type ## _command(Packet *p, const struct sockaddr_in *client_addr)
       
    36 
       
    37 ///*** Communication with the masterserver ***/
       
    38 
       
    39 class MasterNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
       
    40 protected:
       
    41 	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER);
       
    42 public:
       
    43 	virtual ~MasterNetworkUDPSocketHandler() {}
       
    44 };
       
    45 
       
    46 DEF_UDP_RECEIVE_COMMAND(Master, PACKET_UDP_MASTER_ACK_REGISTER)
       
    47 {
       
    48 	_network_advertise_retries = 0;
       
    49 	DEBUG(net, 2, "[udp] advertising on master server successfull");
       
    50 
       
    51 	/* We are advertised, but we don't want to! */
       
    52 	if (!_network_advertise) NetworkUDPRemoveAdvertise();
       
    53 }
       
    54 
       
    55 ///*** Communication with clients (we are server) ***/
       
    56 
       
    57 class ServerNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
       
    58 protected:
       
    59 	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER);
       
    60 	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO);
       
    61 	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS);
       
    62 public:
       
    63 	virtual ~ServerNetworkUDPSocketHandler() {}
       
    64 };
       
    65 
       
    66 DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_FIND_SERVER)
    36 {
    67 {
    37 	Packet *packet;
    68 	Packet *packet;
    38 	// Just a fail-safe.. should never happen
    69 	// Just a fail-safe.. should never happen
    39 	if (!_network_udp_server)
    70 	if (!_network_udp_server)
    40 		return;
    71 		return;
    48 	_network_game_info.map_set       = _opt.landscape;
    79 	_network_game_info.map_set       = _opt.landscape;
    49 	_network_game_info.companies_on  = ActivePlayerCount();
    80 	_network_game_info.companies_on  = ActivePlayerCount();
    50 	_network_game_info.spectators_on = NetworkSpectatorCount();
    81 	_network_game_info.spectators_on = NetworkSpectatorCount();
    51 	_network_game_info.grfconfig     = _grfconfig;
    82 	_network_game_info.grfconfig     = _grfconfig;
    52 
    83 
    53 	NetworkSend_NetworkGameInfo(packet, &_network_game_info);
    84 	this->Send_NetworkGameInfo(packet, &_network_game_info);
    54 
    85 
    55 	// Let the client know that we are here
    86 	// Let the client know that we are here
    56 	NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
    87 	this->SendPacket(packet, client_addr);
    57 
    88 
    58 	free(packet);
    89 	free(packet);
    59 
    90 
    60 	DEBUG(net, 2, "[udp] queried from '%s'", inet_ntoa(client_addr->sin_addr));
    91 	DEBUG(net, 2, "[udp] queried from '%s'", inet_ntoa(client_addr->sin_addr));
    61 }
    92 }
    62 
    93 
    63 void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
    94 DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_DETAIL_INFO)
    64 {
    95 {
    65 	/* Find the matching GRF file */
    96 	NetworkClientState *cs;
    66 	const GRFConfig *f = FindGRFConfig(config->grfid, config->md5sum);
    97 	NetworkClientInfo *ci;
    67 	if (f == NULL) {
    98 	Packet *packet;
    68 		/* Don't know the GRF, so mark game incompatible and the (possibly)
    99 	Player *player;
    69 		 * already resolved name for this GRF (another server has sent the
   100 	byte current = 0;
    70 		 * name of the GRF already */
   101 	int i;
    71 		config->name     = FindUnknownGRFName(config->grfid, config->md5sum, true);
   102 
    72 		SETBIT(config->flags, GCF_NOT_FOUND);
   103 	// Just a fail-safe.. should never happen
    73 	} else {
   104 	if (!_network_udp_server) return;
    74 		config->filename = f->filename;
   105 
    75 		config->name     = f->name;
   106 	packet = NetworkSend_Init(PACKET_UDP_SERVER_DETAIL_INFO);
    76 		config->info     = f->info;
   107 
    77 	}
   108 	/* Send the amount of active companies */
    78 	SETBIT(config->flags, GCF_COPY);
   109 	NetworkSend_uint8 (packet, NETWORK_COMPANY_INFO_VERSION);
    79 }
   110 	NetworkSend_uint8 (packet, ActivePlayerCount());
    80 
   111 
    81 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE)
   112 	/* Fetch the latest version of everything */
       
   113 	NetworkPopulateCompanyInfo();
       
   114 
       
   115 	/* Go through all the players */
       
   116 	FOR_ALL_PLAYERS(player) {
       
   117 		/* Skip non-active players */
       
   118 		if (!player->is_active) continue;
       
   119 
       
   120 		current++;
       
   121 
       
   122 		/* Send the information */
       
   123 		NetworkSend_uint8(packet, current);
       
   124 
       
   125 		NetworkSend_string(packet, _network_player_info[player->index].company_name);
       
   126 		NetworkSend_uint32(packet, _network_player_info[player->index].inaugurated_year);
       
   127 		NetworkSend_uint64(packet, _network_player_info[player->index].company_value);
       
   128 		NetworkSend_uint64(packet, _network_player_info[player->index].money);
       
   129 		NetworkSend_uint64(packet, _network_player_info[player->index].income);
       
   130 		NetworkSend_uint16(packet, _network_player_info[player->index].performance);
       
   131 
       
   132 		/* Send 1 if there is a passord for the company else send 0 */
       
   133 		if (_network_player_info[player->index].password[0] != '\0') {
       
   134 			NetworkSend_uint8(packet, 1);
       
   135 		} else {
       
   136 			NetworkSend_uint8(packet, 0);
       
   137 		}
       
   138 
       
   139 		for (i = 0; i < NETWORK_VEHICLE_TYPES; i++)
       
   140 			NetworkSend_uint16(packet, _network_player_info[player->index].num_vehicle[i]);
       
   141 
       
   142 		for (i = 0; i < NETWORK_STATION_TYPES; i++)
       
   143 			NetworkSend_uint16(packet, _network_player_info[player->index].num_station[i]);
       
   144 
       
   145 		/* Find the clients that are connected to this player */
       
   146 		FOR_ALL_CLIENTS(cs) {
       
   147 			ci = DEREF_CLIENT_INFO(cs);
       
   148 			if (ci->client_playas == player->index) {
       
   149 				/* The uint8 == 1 indicates that a client is following */
       
   150 				NetworkSend_uint8(packet, 1);
       
   151 				NetworkSend_string(packet, ci->client_name);
       
   152 				NetworkSend_string(packet, ci->unique_id);
       
   153 				NetworkSend_uint32(packet, ci->join_date);
       
   154 			}
       
   155 		}
       
   156 		/* Also check for the server itself */
       
   157 		ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
       
   158 		if (ci->client_playas == player->index) {
       
   159 			/* The uint8 == 1 indicates that a client is following */
       
   160 			NetworkSend_uint8(packet, 1);
       
   161 			NetworkSend_string(packet, ci->client_name);
       
   162 			NetworkSend_string(packet, ci->unique_id);
       
   163 			NetworkSend_uint32(packet, ci->join_date);
       
   164 		}
       
   165 
       
   166 		/* Indicates end of client list */
       
   167 		NetworkSend_uint8(packet, 0);
       
   168 	}
       
   169 
       
   170 	/* And check if we have any spectators */
       
   171 	FOR_ALL_CLIENTS(cs) {
       
   172 		ci = DEREF_CLIENT_INFO(cs);
       
   173 		if (!IsValidPlayer(ci->client_playas)) {
       
   174 			/* The uint8 == 1 indicates that a client is following */
       
   175 			NetworkSend_uint8(packet, 1);
       
   176 			NetworkSend_string(packet, ci->client_name);
       
   177 			NetworkSend_string(packet, ci->unique_id);
       
   178 			NetworkSend_uint32(packet, ci->join_date);
       
   179 		}
       
   180 	}
       
   181 
       
   182 	/* Also check for the server itself */
       
   183 	ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
       
   184 	if (!IsValidPlayer(ci->client_playas)) {
       
   185 		/* The uint8 == 1 indicates that a client is following */
       
   186 		NetworkSend_uint8(packet, 1);
       
   187 		NetworkSend_string(packet, ci->client_name);
       
   188 		NetworkSend_string(packet, ci->unique_id);
       
   189 		NetworkSend_uint32(packet, ci->join_date);
       
   190 	}
       
   191 
       
   192 	/* Indicates end of client list */
       
   193 	NetworkSend_uint8(packet, 0);
       
   194 
       
   195 	this->SendPacket(packet, client_addr);
       
   196 	free(packet);
       
   197 }
       
   198 
       
   199 /**
       
   200  * A client has requested the names of some NewGRFs.
       
   201  *
       
   202  * Replying this can be tricky as we have a limit of SEND_MTU bytes
       
   203  * in the reply packet and we can send up to 100 bytes per NewGRF
       
   204  * (GRF ID, MD5sum and NETWORK_GRF_NAME_LENGTH bytes for the name).
       
   205  * As SEND_MTU is _much_ less than 100 * NETWORK_MAX_GRF_COUNT, it
       
   206  * could be that a packet overflows. To stop this we only reply
       
   207  * with the first N NewGRFs so that if the first N + 1 NewGRFs
       
   208  * would be sent, the packet overflows.
       
   209  * in_reply and in_reply_count are used to keep a list of GRFs to
       
   210  * send in the reply.
       
   211  */
       
   212 DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_GET_NEWGRFS)
       
   213 {
       
   214 	uint8 num_grfs;
       
   215 	uint i;
       
   216 
       
   217 	const GRFConfig *in_reply[NETWORK_MAX_GRF_COUNT];
       
   218 	Packet *packet;
       
   219 	uint8 in_reply_count = 0;
       
   220 	uint packet_len = 0;
       
   221 
       
   222 	DEBUG(net, 6, "[udp] newgrf data request from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
       
   223 
       
   224 	num_grfs = NetworkRecv_uint8 (&this->cs, p);
       
   225 	if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
       
   226 
       
   227 	for (i = 0; i < num_grfs; i++) {
       
   228 		GRFConfig c;
       
   229 		const GRFConfig *f;
       
   230 
       
   231 		this->Recv_GRFIdentifier(p, &c);
       
   232 
       
   233 		/* Find the matching GRF file */
       
   234 		f = FindGRFConfig(c.grfid, c.md5sum);
       
   235 		if (f == NULL) continue; // The GRF is unknown to this server
       
   236 
       
   237 		/* If the reply might exceed the size of the packet, only reply
       
   238 		 * the current list and do not send the other data.
       
   239 		 * The name could be an empty string, if so take the filename. */
       
   240 		packet_len += sizeof(c.grfid) + sizeof(c.md5sum) +
       
   241 				min(strlen((f->name != NULL && strlen(f->name) > 0) ? f->name : f->filename) + 1, (size_t)NETWORK_GRF_NAME_LENGTH);
       
   242 		if (packet_len > SEND_MTU - 4) { // 4 is 3 byte header + grf count in reply
       
   243 			break;
       
   244 		}
       
   245 		in_reply[in_reply_count] = f;
       
   246 		in_reply_count++;
       
   247 	}
       
   248 
       
   249 	if (in_reply_count == 0) return;
       
   250 
       
   251 	packet = NetworkSend_Init(PACKET_UDP_SERVER_NEWGRFS);
       
   252 	NetworkSend_uint8 (packet, in_reply_count);
       
   253 	for (i = 0; i < in_reply_count; i++) {
       
   254 		char name[NETWORK_GRF_NAME_LENGTH];
       
   255 
       
   256 		/* The name could be an empty string, if so take the filename */
       
   257 		ttd_strlcpy(name, (in_reply[i]->name != NULL && strlen(in_reply[i]->name) > 0) ?
       
   258 				in_reply[i]->name : in_reply[i]->filename, sizeof(name));
       
   259 	 	this->Send_GRFIdentifier(packet, in_reply[i]);
       
   260 		NetworkSend_string(packet, name);
       
   261 	}
       
   262 
       
   263 	this->SendPacket(packet, client_addr);
       
   264 	free(packet);
       
   265 }
       
   266 
       
   267 ///*** Communication with servers (we are client) ***/
       
   268 
       
   269 class ClientNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
       
   270 protected:
       
   271 	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE);
       
   272 	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST);
       
   273 	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS);
       
   274 	virtual void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config);
       
   275 public:
       
   276 	virtual ~ClientNetworkUDPSocketHandler() {}
       
   277 };
       
   278 
       
   279 DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_RESPONSE)
    82 {
   280 {
    83 	extern const char _openttd_revision[];
   281 	extern const char _openttd_revision[];
    84 	NetworkGameList *item;
   282 	NetworkGameList *item;
    85 
   283 
    86 	// Just a fail-safe.. should never happen
   284 	// Just a fail-safe.. should never happen
    87 	if (_network_udp_server || _udp_cs.has_quit) return;
   285 	if (_network_udp_server) return;
    88 
   286 
    89 	DEBUG(net, 4, "[udp] server response from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
   287 	DEBUG(net, 4, "[udp] server response from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
    90 
   288 
    91 	// Find next item
   289 	// Find next item
    92 	item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port));
   290 	item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port));
    93 
   291 
    94 	NetworkRecv_NetworkGameInfo(&_udp_cs, p, &item->info);
   292 	this->Recv_NetworkGameInfo(p, &item->info);
    95 
   293 
    96 	item->info.compatible = true;
   294 	item->info.compatible = true;
    97 	{
   295 	{
    98 		/* Checks whether there needs to be a request for names of GRFs and makes
   296 		/* Checks whether there needs to be a request for names of GRFs and makes
    99 		 * the request if necessary. GRFs that need to be requested are the GRFs
   297 		 * the request if necessary. GRFs that need to be requested are the GRFs
   119 			uint i;
   317 			uint i;
   120 			Packet *packet = NetworkSend_Init(PACKET_UDP_CLIENT_GET_NEWGRFS);
   318 			Packet *packet = NetworkSend_Init(PACKET_UDP_CLIENT_GET_NEWGRFS);
   121 
   319 
   122 			NetworkSend_uint8 (packet, in_request_count);
   320 			NetworkSend_uint8 (packet, in_request_count);
   123 			for (i = 0; i < in_request_count; i++) {
   321 			for (i = 0; i < in_request_count; i++) {
   124 				NetworkSend_GRFIdentifier(packet, in_request[i]);
   322 				this->Send_GRFIdentifier(packet, in_request[i]);
   125 			}
   323 			}
   126 
   324 
   127 			out_addr.sin_family      = AF_INET;
   325 			out_addr.sin_family      = AF_INET;
   128 			out_addr.sin_port        = htons(item->port);
   326 			out_addr.sin_port        = htons(item->port);
   129 			out_addr.sin_addr.s_addr = item->ip;
   327 			out_addr.sin_addr.s_addr = item->ip;
   130 			NetworkSendUDP_Packet(_udp_client_socket, packet, &out_addr);
   328 			this->SendPacket(packet, &out_addr);
   131 			free(packet);
   329 			free(packet);
   132 		}
   330 		}
   133 	}
   331 	}
   134 
   332 
   135 	if (item->info.server_lang >= NETWORK_NUM_LANGUAGES) item->info.server_lang = 0;
   333 	if (item->info.server_lang >= NETWORK_NUM_LANGUAGES) item->info.server_lang = 0;
   147 	item->online = true;
   345 	item->online = true;
   148 
   346 
   149 	UpdateNetworkGameWindow(false);
   347 	UpdateNetworkGameWindow(false);
   150 }
   348 }
   151 
   349 
   152 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO)
   350 DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_MASTER_RESPONSE_LIST)
   153 {
       
   154 	NetworkClientState *cs;
       
   155 	NetworkClientInfo *ci;
       
   156 	Packet *packet;
       
   157 	Player *player;
       
   158 	byte current = 0;
       
   159 	int i;
       
   160 
       
   161 	// Just a fail-safe.. should never happen
       
   162 	if (!_network_udp_server) return;
       
   163 
       
   164 	packet = NetworkSend_Init(PACKET_UDP_SERVER_DETAIL_INFO);
       
   165 
       
   166 	/* Send the amount of active companies */
       
   167 	NetworkSend_uint8 (packet, NETWORK_COMPANY_INFO_VERSION);
       
   168 	NetworkSend_uint8 (packet, ActivePlayerCount());
       
   169 
       
   170 	/* Fetch the latest version of everything */
       
   171 	NetworkPopulateCompanyInfo();
       
   172 
       
   173 	/* Go through all the players */
       
   174 	FOR_ALL_PLAYERS(player) {
       
   175 		/* Skip non-active players */
       
   176 		if (!player->is_active) continue;
       
   177 
       
   178 		current++;
       
   179 
       
   180 		/* Send the information */
       
   181 		NetworkSend_uint8(packet, current);
       
   182 
       
   183 		NetworkSend_string(packet, _network_player_info[player->index].company_name);
       
   184 		NetworkSend_uint32(packet, _network_player_info[player->index].inaugurated_year);
       
   185 		NetworkSend_uint64(packet, _network_player_info[player->index].company_value);
       
   186 		NetworkSend_uint64(packet, _network_player_info[player->index].money);
       
   187 		NetworkSend_uint64(packet, _network_player_info[player->index].income);
       
   188 		NetworkSend_uint16(packet, _network_player_info[player->index].performance);
       
   189 
       
   190 		/* Send 1 if there is a passord for the company else send 0 */
       
   191 		if (_network_player_info[player->index].password[0] != '\0') {
       
   192 			NetworkSend_uint8(packet, 1);
       
   193 		} else {
       
   194 			NetworkSend_uint8(packet, 0);
       
   195 		}
       
   196 
       
   197 		for (i = 0; i < NETWORK_VEHICLE_TYPES; i++)
       
   198 			NetworkSend_uint16(packet, _network_player_info[player->index].num_vehicle[i]);
       
   199 
       
   200 		for (i = 0; i < NETWORK_STATION_TYPES; i++)
       
   201 			NetworkSend_uint16(packet, _network_player_info[player->index].num_station[i]);
       
   202 
       
   203 		/* Find the clients that are connected to this player */
       
   204 		FOR_ALL_CLIENTS(cs) {
       
   205 			ci = DEREF_CLIENT_INFO(cs);
       
   206 			if (ci->client_playas == player->index) {
       
   207 				/* The uint8 == 1 indicates that a client is following */
       
   208 				NetworkSend_uint8(packet, 1);
       
   209 				NetworkSend_string(packet, ci->client_name);
       
   210 				NetworkSend_string(packet, ci->unique_id);
       
   211 				NetworkSend_uint32(packet, ci->join_date);
       
   212 			}
       
   213 		}
       
   214 		/* Also check for the server itself */
       
   215 		ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
       
   216 		if (ci->client_playas == player->index) {
       
   217 			/* The uint8 == 1 indicates that a client is following */
       
   218 			NetworkSend_uint8(packet, 1);
       
   219 			NetworkSend_string(packet, ci->client_name);
       
   220 			NetworkSend_string(packet, ci->unique_id);
       
   221 			NetworkSend_uint32(packet, ci->join_date);
       
   222 		}
       
   223 
       
   224 		/* Indicates end of client list */
       
   225 		NetworkSend_uint8(packet, 0);
       
   226 	}
       
   227 
       
   228 	/* And check if we have any spectators */
       
   229 	FOR_ALL_CLIENTS(cs) {
       
   230 		ci = DEREF_CLIENT_INFO(cs);
       
   231 		if (!IsValidPlayer(ci->client_playas)) {
       
   232 			/* The uint8 == 1 indicates that a client is following */
       
   233 			NetworkSend_uint8(packet, 1);
       
   234 			NetworkSend_string(packet, ci->client_name);
       
   235 			NetworkSend_string(packet, ci->unique_id);
       
   236 			NetworkSend_uint32(packet, ci->join_date);
       
   237 		}
       
   238 	}
       
   239 
       
   240 	/* Also check for the server itself */
       
   241 	ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
       
   242 	if (!IsValidPlayer(ci->client_playas)) {
       
   243 		/* The uint8 == 1 indicates that a client is following */
       
   244 		NetworkSend_uint8(packet, 1);
       
   245 		NetworkSend_string(packet, ci->client_name);
       
   246 		NetworkSend_string(packet, ci->unique_id);
       
   247 		NetworkSend_uint32(packet, ci->join_date);
       
   248 	}
       
   249 
       
   250 	/* Indicates end of client list */
       
   251 	NetworkSend_uint8(packet, 0);
       
   252 
       
   253 	NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
       
   254 
       
   255 	free(packet);
       
   256 }
       
   257 
       
   258 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST)
       
   259 {
   351 {
   260 	int i;
   352 	int i;
   261 	struct in_addr ip;
   353 	struct in_addr ip;
   262 	uint16 port;
   354 	uint16 port;
   263 	uint8 ver;
   355 	uint8 ver;
   266 	 * then an uint16 which indicates how many
   358 	 * then an uint16 which indicates how many
   267 	 * ip:port pairs are in this packet, after that
   359 	 * ip:port pairs are in this packet, after that
   268 	 * an uint32 (ip) and an uint16 (port) for each pair
   360 	 * an uint32 (ip) and an uint16 (port) for each pair
   269 	 */
   361 	 */
   270 
   362 
   271 	ver = NetworkRecv_uint8(&_udp_cs, p);
   363 	ver = NetworkRecv_uint8(&this->cs, p);
   272 
   364 
   273 	if (_udp_cs.has_quit) return;
   365 	if (this->cs.has_quit) return;
   274 
   366 
   275 	if (ver == 1) {
   367 	if (ver == 1) {
   276 		for (i = NetworkRecv_uint16(&_udp_cs, p); i != 0 ; i--) {
   368 		for (i = NetworkRecv_uint16(&this->cs, p); i != 0 ; i--) {
   277 			ip.s_addr = TO_LE32(NetworkRecv_uint32(&_udp_cs, p));
   369 			ip.s_addr = TO_LE32(NetworkRecv_uint32(&this->cs, p));
   278 			port = NetworkRecv_uint16(&_udp_cs, p);
   370 			port = NetworkRecv_uint16(&this->cs, p);
   279 			NetworkUDPQueryServer(inet_ntoa(ip), port);
   371 			NetworkUDPQueryServer(inet_ntoa(ip), port);
   280 		}
   372 		}
   281 	}
   373 	}
   282 }
   374 }
   283 
   375 
   284 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER)
   376 /** The return of the client's request of the names of some NewGRFs */
   285 {
   377 DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_NEWGRFS)
   286 	_network_advertise_retries = 0;
       
   287 	DEBUG(net, 2, "[udp] advertising on master server successfull");
       
   288 
       
   289 	/* We are advertised, but we don't want to! */
       
   290 	if (!_network_advertise) NetworkUDPRemoveAdvertise();
       
   291 }
       
   292 
       
   293 /**
       
   294  * A client has requested the names of some NewGRFs.
       
   295  *
       
   296  * Replying this can be tricky as we have a limit of SEND_MTU bytes
       
   297  * in the reply packet and we can send up to 100 bytes per NewGRF
       
   298  * (GRF ID, MD5sum and NETWORK_GRF_NAME_LENGTH bytes for the name).
       
   299  * As SEND_MTU is _much_ less than 100 * NETWORK_MAX_GRF_COUNT, it
       
   300  * could be that a packet overflows. To stop this we only reply
       
   301  * with the first N NewGRFs so that if the first N + 1 NewGRFs
       
   302  * would be sent, the packet overflows.
       
   303  * in_reply and in_reply_count are used to keep a list of GRFs to
       
   304  * send in the reply.
       
   305  */
       
   306 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS)
       
   307 {
   378 {
   308 	uint8 num_grfs;
   379 	uint8 num_grfs;
   309 	uint i;
   380 	uint i;
   310 
   381 
   311 	const GRFConfig *in_reply[NETWORK_MAX_GRF_COUNT];
   382 	DEBUG(net, 6, "[udp] newgrf data reply from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
   312 	Packet *packet;
   383 
   313 	uint8 in_reply_count = 0;
   384 	num_grfs = NetworkRecv_uint8 (&this->cs, p);
   314 	uint packet_len = 0;
       
   315 
       
   316 	/* Just a fail-safe.. should never happen */
       
   317 	if (_udp_cs.has_quit) return;
       
   318 
       
   319 	DEBUG(net, 6, "[udp] newgrf data request from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
       
   320 
       
   321 	num_grfs = NetworkRecv_uint8 (&_udp_cs, p);
       
   322 	if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
       
   323 
       
   324 	for (i = 0; i < num_grfs; i++) {
       
   325 		GRFConfig c;
       
   326 		const GRFConfig *f;
       
   327 
       
   328 		NetworkRecv_GRFIdentifier(&_udp_cs, p, &c);
       
   329 
       
   330 		/* Find the matching GRF file */
       
   331 		f = FindGRFConfig(c.grfid, c.md5sum);
       
   332 		if (f == NULL) continue; // The GRF is unknown to this server
       
   333 
       
   334 		/* If the reply might exceed the size of the packet, only reply
       
   335 		 * the current list and do not send the other data.
       
   336 		 * The name could be an empty string, if so take the filename. */
       
   337 		packet_len += sizeof(c.grfid) + sizeof(c.md5sum) +
       
   338 				min(strlen((f->name != NULL && strlen(f->name) > 0) ? f->name : f->filename) + 1, (size_t)NETWORK_GRF_NAME_LENGTH);
       
   339 		if (packet_len > SEND_MTU - 4) { // 4 is 3 byte header + grf count in reply
       
   340 			break;
       
   341 		}
       
   342 		in_reply[in_reply_count] = f;
       
   343 		in_reply_count++;
       
   344 	}
       
   345 
       
   346 	if (in_reply_count == 0) return;
       
   347 
       
   348 	packet = NetworkSend_Init(PACKET_UDP_SERVER_NEWGRFS);
       
   349 	NetworkSend_uint8 (packet, in_reply_count);
       
   350 	for (i = 0; i < in_reply_count; i++) {
       
   351 		char name[NETWORK_GRF_NAME_LENGTH];
       
   352 
       
   353 		/* The name could be an empty string, if so take the filename */
       
   354 		ttd_strlcpy(name, (in_reply[i]->name != NULL && strlen(in_reply[i]->name) > 0) ?
       
   355 				in_reply[i]->name : in_reply[i]->filename, sizeof(name));
       
   356 	 	NetworkSend_GRFIdentifier(packet, in_reply[i]);
       
   357 		NetworkSend_string(packet, name);
       
   358 	}
       
   359 
       
   360 	NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
       
   361 	free(packet);
       
   362 }
       
   363 
       
   364 /** The return of the client's request of the names of some NewGRFs */
       
   365 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS)
       
   366 {
       
   367 	uint8 num_grfs;
       
   368 	uint i;
       
   369 
       
   370 	/* Just a fail-safe.. should never happen */
       
   371 	if (_udp_cs.has_quit) return;
       
   372 
       
   373 	DEBUG(net, 6, "[udp] newgrf data reply from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
       
   374 
       
   375 	num_grfs = NetworkRecv_uint8 (&_udp_cs, p);
       
   376 	if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
   385 	if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
   377 
   386 
   378 	for (i = 0; i < num_grfs; i++) {
   387 	for (i = 0; i < num_grfs; i++) {
   379 		char *unknown_name;
   388 		char *unknown_name;
   380 		char name[NETWORK_GRF_NAME_LENGTH];
   389 		char name[NETWORK_GRF_NAME_LENGTH];
   381 		GRFConfig c;
   390 		GRFConfig c;
   382 
   391 
   383 		NetworkRecv_GRFIdentifier(&_udp_cs, p, &c);
   392 		this->Recv_GRFIdentifier(p, &c);
   384 		NetworkRecv_string(&_udp_cs, p, name, sizeof(name));
   393 		NetworkRecv_string(&this->cs, p, name, sizeof(name));
   385 
   394 
   386 		/* An empty name is not possible under normal circumstances
   395 		/* An empty name is not possible under normal circumstances
   387 		 * and causes problems when showing the NewGRF list. */
   396 		 * and causes problems when showing the NewGRF list. */
   388 		if (strlen(name) == 0) continue;
   397 		if (strlen(name) == 0) continue;
   389 
   398 
   395 			ttd_strlcpy(unknown_name, name, NETWORK_GRF_NAME_LENGTH);
   404 			ttd_strlcpy(unknown_name, name, NETWORK_GRF_NAME_LENGTH);
   396 		}
   405 		}
   397 	}
   406 	}
   398 }
   407 }
   399 
   408 
   400 /**
   409 void ClientNetworkUDPSocketHandler::HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
   401  * Every type of UDP packet should only be received by a single socket;
   410 {
   402  * The socket communicating with the masterserver should receive the
   411 	/* Find the matching GRF file */
   403  * game information of some 'random' host.
   412 	const GRFConfig *f = FindGRFConfig(config->grfid, config->md5sum);
   404  */
   413 	if (f == NULL) {
   405 typedef struct NetworkUDPPacketAndSocket {
   414 		/* Don't know the GRF, so mark game incompatible and the (possibly)
   406 	void (*callback)(Packet *p, const struct sockaddr_in *client_addr);
   415 		 * already resolved name for this GRF (another server has sent the
   407 	SOCKET *incoming_socket;
   416 		 * name of the GRF already */
   408 } NetworkUPDPacketAndSocket;
   417 		config->name     = FindUnknownGRFName(config->grfid, config->md5sum, true);
   409 
   418 		SETBIT(config->flags, GCF_NOT_FOUND);
   410 static const NetworkUPDPacketAndSocket _network_udp_packet[PACKET_UDP_END] = {
       
   411 	{ RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER),   &_udp_server_socket },
       
   412 	{ RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE),      &_udp_client_socket },
       
   413 	{ RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO),   &_udp_server_socket },
       
   414 	{ NULL,                                             NULL                },
       
   415 	{ NULL,                                             NULL                },
       
   416 	{ RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER),  &_udp_master_socket },
       
   417 	{ NULL,                                             NULL                },
       
   418 	{ RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST), &_udp_client_socket },
       
   419 	{ NULL,                                             NULL                },
       
   420 	{ RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS),   &_udp_server_socket },
       
   421 	{ RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS),       &_udp_client_socket },
       
   422 };
       
   423 
       
   424 void NetworkHandleUDPPacket(const SOCKET udp, Packet *p, const struct sockaddr_in *client_addr)
       
   425 {
       
   426 	byte type;
       
   427 
       
   428 	/* Fake a client, so we can see when there is an illegal packet */
       
   429 	_udp_cs.socket = INVALID_SOCKET;
       
   430 	_udp_cs.has_quit = false;
       
   431 
       
   432 	type = NetworkRecv_uint8(&_udp_cs, p);
       
   433 
       
   434 	if (type < PACKET_UDP_END && *_network_udp_packet[type].incoming_socket == udp && !_udp_cs.has_quit) {
       
   435 		_network_udp_packet[type].callback(p, client_addr);
       
   436 	} else {
   419 	} else {
   437 		if (*_network_udp_packet[type].incoming_socket != udp) {
   420 		config->filename = f->filename;
   438 			DEBUG(net, 0, "[udp] received packet on wrong port from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
   421 		config->name     = f->name;
   439 		} else if (!_udp_cs.has_quit) {
   422 		config->info     = f->info;
   440 			DEBUG(net, 0, "[udp] received invalid packet type %d from %s:%d", type,  inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
   423 	}
   441 		} else {
   424 	SETBIT(config->flags, GCF_COPY);
   442 			DEBUG(net, 0, "[udp] received illegal packet from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
   425 }
   443 		}
       
   444 	}
       
   445 }
       
   446 
       
   447 
   426 
   448 // Close UDP connection
   427 // Close UDP connection
   449 void NetworkUDPStop(void)
   428 void NetworkUDPCloseAll(void)
   450 {
   429 {
   451 	DEBUG(net, 1, "[udp] closed listeners");
   430 	DEBUG(net, 1, "[udp] closed listeners");
   452 
   431 
   453 	if (_network_udp_server) {
   432 	_udp_server_socket->Close();
   454 		NetworkUDPClose(&_udp_server_socket);
   433 	_udp_master_socket->Close();
   455 		NetworkUDPClose(&_udp_master_socket);
   434 	_udp_client_socket->Close();
   456 	} else {
       
   457 		NetworkUDPClose(&_udp_client_socket);
       
   458 	}
       
   459 
   435 
   460 	_network_udp_server = false;
   436 	_network_udp_server = false;
   461 	_network_udp_broadcast = 0;
   437 	_network_udp_broadcast = 0;
   462 }
   438 }
   463 
   439 
   464 // Broadcast to all ips
   440 // Broadcast to all ips
   465 static void NetworkUDPBroadCast(SOCKET udp)
   441 static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket)
   466 {
   442 {
   467 	Packet* p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER);
   443 	Packet* p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER);
   468 	uint i;
   444 	uint i;
   469 
   445 
   470 	for (i = 0; _broadcast_list[i] != 0; i++) {
   446 	for (i = 0; _broadcast_list[i] != 0; i++) {
   474 		out_addr.sin_port = htons(_network_server_port);
   450 		out_addr.sin_port = htons(_network_server_port);
   475 		out_addr.sin_addr.s_addr = _broadcast_list[i];
   451 		out_addr.sin_addr.s_addr = _broadcast_list[i];
   476 
   452 
   477 		DEBUG(net, 4, "[udp] broadcasting to %s", inet_ntoa(out_addr.sin_addr));
   453 		DEBUG(net, 4, "[udp] broadcasting to %s", inet_ntoa(out_addr.sin_addr));
   478 
   454 
   479 		NetworkSendUDP_Packet(udp, p, &out_addr);
   455 		socket->SendPacket(p, &out_addr);
   480 	}
   456 	}
   481 
   457 
   482 	free(p);
   458 	free(p);
   483 }
   459 }
   484 
   460 
   487 void NetworkUDPQueryMasterServer(void)
   463 void NetworkUDPQueryMasterServer(void)
   488 {
   464 {
   489 	struct sockaddr_in out_addr;
   465 	struct sockaddr_in out_addr;
   490 	Packet *p;
   466 	Packet *p;
   491 
   467 
   492 	if (_udp_client_socket == INVALID_SOCKET)
   468 	if (!_udp_client_socket->IsListening()) {
   493 		if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
   469 		if (!_udp_client_socket->Listen(0, 0, true)) return;
   494 			return;
   470 	}
   495 
   471 
   496 	p = NetworkSend_Init(PACKET_UDP_CLIENT_GET_LIST);
   472 	p = NetworkSend_Init(PACKET_UDP_CLIENT_GET_LIST);
   497 
   473 
   498 	out_addr.sin_family = AF_INET;
   474 	out_addr.sin_family = AF_INET;
   499 	out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
   475 	out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
   500 	out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
   476 	out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
   501 
   477 
   502 	// packet only contains protocol version
   478 	// packet only contains protocol version
   503 	NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
   479 	NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
   504 
   480 
   505 	NetworkSendUDP_Packet(_udp_client_socket, p, &out_addr);
   481 	_udp_client_socket->SendPacket(p, &out_addr);
   506 
   482 
   507 	DEBUG(net, 2, "[udp] master server queried at %s:%d", inet_ntoa(out_addr.sin_addr),ntohs(out_addr.sin_port));
   483 	DEBUG(net, 2, "[udp] master server queried at %s:%d", inet_ntoa(out_addr.sin_addr),ntohs(out_addr.sin_port));
   508 
   484 
   509 	free(p);
   485 	free(p);
   510 }
   486 }
   514 {
   490 {
   515 	// We are still searching..
   491 	// We are still searching..
   516 	if (_network_udp_broadcast > 0) return;
   492 	if (_network_udp_broadcast > 0) return;
   517 
   493 
   518 	// No UDP-socket yet..
   494 	// No UDP-socket yet..
   519 	if (_udp_client_socket == INVALID_SOCKET)
   495 	if (!_udp_client_socket->IsListening()) {
   520 		if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
   496 		if (!_udp_client_socket->Listen(0, 0, true)) return;
   521 			return;
   497 	}
   522 
   498 
   523 	DEBUG(net, 0, "[udp] searching server");
   499 	DEBUG(net, 0, "[udp] searching server");
   524 
   500 
   525 	NetworkUDPBroadCast(_udp_client_socket);
   501 	NetworkUDPBroadCast(_udp_client_socket);
   526 	_network_udp_broadcast = 300; // Stay searching for 300 ticks
   502 	_network_udp_broadcast = 300; // Stay searching for 300 ticks
   531 	struct sockaddr_in out_addr;
   507 	struct sockaddr_in out_addr;
   532 	Packet *p;
   508 	Packet *p;
   533 	NetworkGameList *item;
   509 	NetworkGameList *item;
   534 
   510 
   535 	// No UDP-socket yet..
   511 	// No UDP-socket yet..
   536 	if (_udp_client_socket == INVALID_SOCKET)
   512 	if (!_udp_client_socket->IsListening()) {
   537 		if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
   513 		if (!_udp_client_socket->Listen(0, 0, true)) return NULL;
   538 			return NULL;
   514 	}
   539 
   515 
   540 	out_addr.sin_family = AF_INET;
   516 	out_addr.sin_family = AF_INET;
   541 	out_addr.sin_port = htons(port);
   517 	out_addr.sin_port = htons(port);
   542 	out_addr.sin_addr.s_addr = NetworkResolveHost(host);
   518 	out_addr.sin_addr.s_addr = NetworkResolveHost(host);
   543 
   519 
   549 	item->online = false;
   525 	item->online = false;
   550 
   526 
   551 	// Init the packet
   527 	// Init the packet
   552 	p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER);
   528 	p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER);
   553 
   529 
   554 	NetworkSendUDP_Packet(_udp_client_socket, p, &out_addr);
   530 	_udp_client_socket->SendPacket(p, &out_addr);
   555 
   531 
   556 	free(p);
   532 	free(p);
   557 
   533 
   558 	UpdateNetworkGameWindow(false);
   534 	UpdateNetworkGameWindow(false);
   559 	return item;
   535 	return item;
   567 
   543 
   568 	/* Check if we are advertising */
   544 	/* Check if we are advertising */
   569 	if (!_networking || !_network_server || !_network_udp_server) return;
   545 	if (!_networking || !_network_server || !_network_udp_server) return;
   570 
   546 
   571 	/* check for socket */
   547 	/* check for socket */
   572 	if (_udp_master_socket == INVALID_SOCKET)
   548 	if (!_udp_master_socket->IsListening()) {
   573 		if (!NetworkUDPListen(&_udp_master_socket, _network_server_bind_ip, 0, false))
   549 		if (!_udp_master_socket->Listen(0, 0, false)) return;
   574 			return;
   550 	}
   575 
   551 
   576 	DEBUG(net, 1, "[udp] removing advertise from master server");
   552 	DEBUG(net, 1, "[udp] removing advertise from master server");
   577 
   553 
   578 	/* Find somewhere to send */
   554 	/* Find somewhere to send */
   579 	out_addr.sin_family = AF_INET;
   555 	out_addr.sin_family = AF_INET;
   583 	/* Send the packet */
   559 	/* Send the packet */
   584 	p = NetworkSend_Init(PACKET_UDP_SERVER_UNREGISTER);
   560 	p = NetworkSend_Init(PACKET_UDP_SERVER_UNREGISTER);
   585 	/* Packet is: Version, server_port */
   561 	/* Packet is: Version, server_port */
   586 	NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
   562 	NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
   587 	NetworkSend_uint16(p, _network_server_port);
   563 	NetworkSend_uint16(p, _network_server_port);
   588 	NetworkSendUDP_Packet(_udp_master_socket, p, &out_addr);
   564 	_udp_master_socket->SendPacket(p, &out_addr);
   589 
   565 
   590 	free(p);
   566 	free(p);
   591 }
   567 }
   592 
   568 
   593 /* Register us to the master server
   569 /* Register us to the master server
   600 	/* Check if we should send an advertise */
   576 	/* Check if we should send an advertise */
   601 	if (!_networking || !_network_server || !_network_udp_server || !_network_advertise)
   577 	if (!_networking || !_network_server || !_network_udp_server || !_network_advertise)
   602 		return;
   578 		return;
   603 
   579 
   604 	/* check for socket */
   580 	/* check for socket */
   605 	if (_udp_master_socket == INVALID_SOCKET)
   581 	if (!_udp_master_socket->IsListening()) {
   606 		if (!NetworkUDPListen(&_udp_master_socket, _network_server_bind_ip, 0, false))
   582 		if (!_udp_master_socket->Listen(0, 0, false)) return;
   607 			return;
   583 	}
   608 
   584 
   609 	if (_network_need_advertise) {
   585 	if (_network_need_advertise) {
   610 		_network_need_advertise = false;
   586 		_network_need_advertise = false;
   611 		_network_advertise_retries = ADVERTISE_RETRY_TIMES;
   587 		_network_advertise_retries = ADVERTISE_RETRY_TIMES;
   612 	} else {
   588 	} else {
   635 	p = NetworkSend_Init(PACKET_UDP_SERVER_REGISTER);
   611 	p = NetworkSend_Init(PACKET_UDP_SERVER_REGISTER);
   636 	/* Packet is: WELCOME_MESSAGE, Version, server_port */
   612 	/* Packet is: WELCOME_MESSAGE, Version, server_port */
   637 	NetworkSend_string(p, NETWORK_MASTER_SERVER_WELCOME_MESSAGE);
   613 	NetworkSend_string(p, NETWORK_MASTER_SERVER_WELCOME_MESSAGE);
   638 	NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
   614 	NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
   639 	NetworkSend_uint16(p, _network_server_port);
   615 	NetworkSend_uint16(p, _network_server_port);
   640 	NetworkSendUDP_Packet(_udp_master_socket, p, &out_addr);
   616 	_udp_master_socket->SendPacket(p, &out_addr);
   641 
   617 
   642 	free(p);
   618 	free(p);
   643 }
   619 }
   644 
   620 
   645 void NetworkUDPInitialize(void)
   621 void NetworkUDPInitialize(void)
   646 {
   622 {
   647 	_udp_client_socket = INVALID_SOCKET;
   623 	_udp_client_socket = new ClientNetworkUDPSocketHandler();
   648 	_udp_server_socket = INVALID_SOCKET;
   624 	_udp_server_socket = new ServerNetworkUDPSocketHandler();
   649 	_udp_master_socket = INVALID_SOCKET;
   625 	_udp_master_socket = new MasterNetworkUDPSocketHandler();
   650 
   626 
   651 	_network_udp_server = false;
   627 	_network_udp_server = false;
   652 	_network_udp_broadcast = 0;
   628 	_network_udp_broadcast = 0;
   653 }
   629 }
   654 
   630 
       
   631 void NetworkUDPShutdown(void)
       
   632 {
       
   633 	NetworkUDPCloseAll();
       
   634 
       
   635 	delete _udp_client_socket;
       
   636 	delete _udp_server_socket;
       
   637 	delete _udp_master_socket;
       
   638 }
       
   639 
   655 #endif /* ENABLE_NETWORK */
   640 #endif /* ENABLE_NETWORK */