35 ADVERTISE_RETRY_TIMES = 3 // give up readvertising after this much failed retries |
35 ADVERTISE_RETRY_TIMES = 3 // give up readvertising after this much failed retries |
36 }; |
36 }; |
37 |
37 |
38 #define DEF_UDP_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(Packet *p, struct sockaddr_in *client_addr) |
38 #define DEF_UDP_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(Packet *p, struct sockaddr_in *client_addr) |
39 void NetworkSendUDP_Packet(SOCKET udp, Packet *p, struct sockaddr_in *recv); |
39 void NetworkSendUDP_Packet(SOCKET udp, Packet *p, struct sockaddr_in *recv); |
|
40 |
|
41 NetworkClientState _udp_cs; |
40 |
42 |
41 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER) |
43 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER) |
42 { |
44 { |
43 Packet *packet; |
45 Packet *packet; |
44 // Just a fail-safe.. should never happen |
46 // Just a fail-safe.. should never happen |
84 |
86 |
85 // Just a fail-safe.. should never happen |
87 // Just a fail-safe.. should never happen |
86 if (_network_udp_server) |
88 if (_network_udp_server) |
87 return; |
89 return; |
88 |
90 |
89 game_info_version = NetworkRecv_uint8(p); |
91 game_info_version = NetworkRecv_uint8(&_udp_cs, p); |
90 |
92 |
|
93 if (_udp_cs.quited) |
|
94 return; |
91 |
95 |
92 DEBUG(net, 6)("[NET][UDP] Server response from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port)); |
96 DEBUG(net, 6)("[NET][UDP] Server response from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port)); |
93 |
97 |
94 // Find next item |
98 // Find next item |
95 item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port)); |
99 item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port)); |
96 |
100 |
97 if (game_info_version == 1) { |
101 if (game_info_version == 1) { |
98 NetworkRecv_string(p, item->info.server_name, sizeof(item->info.server_name)); |
102 NetworkRecv_string(&_udp_cs, p, item->info.server_name, sizeof(item->info.server_name)); |
99 NetworkRecv_string(p, item->info.server_revision, sizeof(item->info.server_revision)); |
103 NetworkRecv_string(&_udp_cs, p, item->info.server_revision, sizeof(item->info.server_revision)); |
100 item->info.server_lang = NetworkRecv_uint8(p); |
104 item->info.server_lang = NetworkRecv_uint8(&_udp_cs, p); |
101 item->info.use_password = NetworkRecv_uint8(p); |
105 item->info.use_password = NetworkRecv_uint8(&_udp_cs, p); |
102 item->info.clients_max = NetworkRecv_uint8(p); |
106 item->info.clients_max = NetworkRecv_uint8(&_udp_cs, p); |
103 item->info.clients_on = NetworkRecv_uint8(p); |
107 item->info.clients_on = NetworkRecv_uint8(&_udp_cs, p); |
104 item->info.spectators_on = NetworkRecv_uint8(p); |
108 item->info.spectators_on = NetworkRecv_uint8(&_udp_cs, p); |
105 item->info.game_date = NetworkRecv_uint16(p); |
109 item->info.game_date = NetworkRecv_uint16(&_udp_cs, p); |
106 item->info.start_date = NetworkRecv_uint16(p); |
110 item->info.start_date = NetworkRecv_uint16(&_udp_cs, p); |
107 NetworkRecv_string(p, item->info.map_name, sizeof(item->info.map_name)); |
111 NetworkRecv_string(&_udp_cs, p, item->info.map_name, sizeof(item->info.map_name)); |
108 item->info.map_width = NetworkRecv_uint16(p); |
112 item->info.map_width = NetworkRecv_uint16(&_udp_cs, p); |
109 item->info.map_height = NetworkRecv_uint16(p); |
113 item->info.map_height = NetworkRecv_uint16(&_udp_cs, p); |
110 item->info.map_set = NetworkRecv_uint8(p); |
114 item->info.map_set = NetworkRecv_uint8(&_udp_cs, p); |
111 item->info.dedicated = NetworkRecv_uint8(p); |
115 item->info.dedicated = NetworkRecv_uint8(&_udp_cs, p); |
112 |
116 |
113 if (item->info.hostname[0] == '\0') |
117 if (item->info.hostname[0] == '\0') |
114 snprintf(item->info.hostname, sizeof(item->info.hostname), "%s", inet_ntoa(client_addr->sin_addr)); |
118 snprintf(item->info.hostname, sizeof(item->info.hostname), "%s", inet_ntoa(client_addr->sin_addr)); |
115 } |
119 } |
116 |
120 |
235 * then an uint16 which indicates how many |
239 * then an uint16 which indicates how many |
236 * ip:port pairs are in this packet, after that |
240 * ip:port pairs are in this packet, after that |
237 * an uint32 (ip) and an uint16 (port) for each pair |
241 * an uint32 (ip) and an uint16 (port) for each pair |
238 */ |
242 */ |
239 |
243 |
240 ver = NetworkRecv_uint8(p); |
244 ver = NetworkRecv_uint8(&_udp_cs, p); |
|
245 |
|
246 if (_udp_cs.quited) |
|
247 return; |
241 |
248 |
242 if (ver == 1) { |
249 if (ver == 1) { |
243 for (i = NetworkRecv_uint16(p); i != 0 ; i--) { |
250 for (i = NetworkRecv_uint16(&_udp_cs, p); i != 0 ; i--) { |
244 ip.s_addr = TO_LE32(NetworkRecv_uint32(p)); |
251 ip.s_addr = TO_LE32(NetworkRecv_uint32(&_udp_cs, p)); |
245 port = NetworkRecv_uint16(p); |
252 port = NetworkRecv_uint16(&_udp_cs, p); |
246 NetworkUDPQueryServer(inet_ntoa(ip), port); |
253 NetworkUDPQueryServer(inet_ntoa(ip), port); |
247 } |
254 } |
248 } |
255 } |
249 } |
256 } |
250 |
257 |
280 |
287 |
281 void NetworkHandleUDPPacket(Packet *p, struct sockaddr_in *client_addr) |
288 void NetworkHandleUDPPacket(Packet *p, struct sockaddr_in *client_addr) |
282 { |
289 { |
283 byte type; |
290 byte type; |
284 |
291 |
285 type = NetworkRecv_uint8(p); |
292 /* Fake a client, so we can see when there is an illegal packet */ |
286 |
293 _udp_cs.socket = INVALID_SOCKET; |
287 if (type < PACKET_UDP_END && _network_udp_packet[type] != NULL) { |
294 _udp_cs.quited = false; |
|
295 |
|
296 type = NetworkRecv_uint8(&_udp_cs, p); |
|
297 |
|
298 if (type < PACKET_UDP_END && _network_udp_packet[type] != NULL && !_udp_cs.quited) { |
288 _network_udp_packet[type](p, client_addr); |
299 _network_udp_packet[type](p, client_addr); |
289 } else { |
300 } else { |
290 DEBUG(net, 0)("[NET][UDP] Received invalid packet type %d", type); |
301 DEBUG(net, 0)("[NET][UDP] Received invalid packet type %d", type); |
291 } |
302 } |
292 } |
303 } |