18 PACKET_UDP_CLIENT_FIND_SERVER, |
19 PACKET_UDP_CLIENT_FIND_SERVER, |
19 PACKET_UDP_SERVER_RESPONSE, |
20 PACKET_UDP_SERVER_RESPONSE, |
20 PACKET_UDP_CLIENT_DETAIL_INFO, |
21 PACKET_UDP_CLIENT_DETAIL_INFO, |
21 PACKET_UDP_SERVER_DETAIL_INFO, // Is not used in OpenTTD itself, only for external querying |
22 PACKET_UDP_SERVER_DETAIL_INFO, // Is not used in OpenTTD itself, only for external querying |
22 PACKET_UDP_SERVER_REGISTER, // Packet to register itself to the master server |
23 PACKET_UDP_SERVER_REGISTER, // Packet to register itself to the master server |
|
24 PACKET_UDP_MASTER_ACK_REGISTER, // Packet indicating registration has succedeed |
|
25 PACKET_UDP_CLIENT_GET_LIST, // Request for serverlist from master server |
|
26 PACKET_UDP_MASTER_RESPONSE_LIST, // Response from master server with server ip's + port's |
23 PACKET_UDP_END |
27 PACKET_UDP_END |
24 } PacketUDPType; |
28 } PacketUDPType; |
25 |
29 |
26 static SOCKET _udp_server_socket; // udp server socket |
30 enum { |
|
31 ADVERTISE_NORMAL_INTERVAL = 450, // interval between advertising in days |
|
32 ADVERTISE_RETRY_INTERVAL = 5, // readvertise when no response after this amount of days |
|
33 ADVERTISE_RETRY_TIMES = 3 // give up readvertising after this much failed retries |
|
34 }; |
27 |
35 |
28 #define DEF_UDP_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(Packet *p, struct sockaddr_in *client_addr) |
36 #define DEF_UDP_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(Packet *p, struct sockaddr_in *client_addr) |
29 void NetworkSendUDP_Packet(Packet *p, struct sockaddr_in *recv); |
37 void NetworkSendUDP_Packet(SOCKET udp, Packet *p, struct sockaddr_in *recv); |
30 |
38 |
31 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER) |
39 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER) |
32 { |
40 { |
33 Packet *packet; |
41 Packet *packet; |
34 // Just a fail-safe.. should never happen |
42 // Just a fail-safe.. should never happen |
203 } |
214 } |
204 |
215 |
205 /* Indicates end of client list */ |
216 /* Indicates end of client list */ |
206 NetworkSend_uint8(packet, 0); |
217 NetworkSend_uint8(packet, 0); |
207 |
218 |
208 NetworkSendUDP_Packet(packet, client_addr); |
219 NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr); |
209 |
220 |
210 free(packet); |
221 free(packet); |
|
222 } |
|
223 |
|
224 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST) { |
|
225 int i; |
|
226 struct in_addr ip; |
|
227 uint16 port; |
|
228 uint8 ver; |
|
229 |
|
230 /* packet begins with the protocol version (uint8) |
|
231 * then an uint16 which indicates how many |
|
232 * ip:port pairs are in this packet, after that |
|
233 * an uint32 (ip) and an uint16 (port) for each pair |
|
234 */ |
|
235 |
|
236 ver = NetworkRecv_uint8(p); |
|
237 |
|
238 if (ver == 1) { |
|
239 for (i = NetworkRecv_uint16(p); i != 0 ; i--) { |
|
240 ip.s_addr = TO_LE32(NetworkRecv_uint32(p)); |
|
241 port = NetworkRecv_uint16(p); |
|
242 NetworkUDPQueryServer(inet_ntoa(ip), port); |
|
243 } |
|
244 } |
|
245 } |
|
246 |
|
247 DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER) { |
|
248 _network_advertise_retries = 0; |
|
249 DEBUG(net, 2)("[NET] We are advertised on the master-server!"); |
211 } |
250 } |
212 |
251 |
213 |
252 |
214 // The layout for the receive-functions by UDP |
253 // The layout for the receive-functions by UDP |
215 typedef void NetworkUDPPacket(Packet *p, struct sockaddr_in *client_addr); |
254 typedef void NetworkUDPPacket(Packet *p, struct sockaddr_in *client_addr); |
264 DEBUG(net, 1)("[NET][UDP] Send error: %i", GET_LAST_ERROR()); |
300 DEBUG(net, 1)("[NET][UDP] Send error: %i", GET_LAST_ERROR()); |
265 } |
301 } |
266 } |
302 } |
267 |
303 |
268 // Start UDP listener |
304 // Start UDP listener |
269 bool NetworkUDPListen(uint32 host, uint16 port) |
305 bool NetworkUDPListen(SOCKET *udp, uint32 host, uint16 port, bool broadcast) |
270 { |
306 { |
271 struct sockaddr_in sin; |
307 struct sockaddr_in sin; |
272 SOCKET udp; |
308 |
273 |
309 // Make sure socket is closed |
274 // Make sure sockets are closed |
310 closesocket(*udp); |
275 if (_network_udp_server) |
311 |
276 closesocket(_udp_server_socket); |
312 *udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
277 else |
313 if (*udp == INVALID_SOCKET) { |
278 closesocket(_udp_client_socket); |
|
279 |
|
280 udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
|
281 if (udp == INVALID_SOCKET) { |
|
282 DEBUG(net, 1)("[NET][UDP] Failed to start UDP support"); |
314 DEBUG(net, 1)("[NET][UDP] Failed to start UDP support"); |
283 return false; |
315 return false; |
284 } |
316 } |
285 |
317 |
286 // set nonblocking mode for socket |
318 // set nonblocking mode for socket |
287 { |
319 { |
288 unsigned long blocking = 1; |
320 unsigned long blocking = 1; |
289 ioctlsocket(udp, FIONBIO, &blocking); |
321 ioctlsocket(*udp, FIONBIO, &blocking); |
290 } |
322 } |
291 |
323 |
292 sin.sin_family = AF_INET; |
324 sin.sin_family = AF_INET; |
293 // Listen on all IPs |
325 // Listen on all IPs |
294 sin.sin_addr.s_addr = host; |
326 sin.sin_addr.s_addr = host; |
295 sin.sin_port = htons(port); |
327 sin.sin_port = htons(port); |
296 |
328 |
297 if (bind(udp, (struct sockaddr*)&sin, sizeof(sin)) != 0) { |
329 if (bind(*udp, (struct sockaddr*)&sin, sizeof(sin)) != 0) { |
298 DEBUG(net, 1) ("[NET][UDP] error: bind failed on %s:%i", inet_ntoa(*(struct in_addr *)&host), port); |
330 DEBUG(net, 1) ("[NET][UDP] error: bind failed on %s:%i", inet_ntoa(*(struct in_addr *)&host), port); |
299 return false; |
331 return false; |
300 } |
332 } |
301 |
333 |
302 // enable broadcasting |
334 if (broadcast) { |
303 // allow reusing |
335 /* Enable broadcast */ |
304 { |
|
305 unsigned long val = 1; |
336 unsigned long val = 1; |
306 setsockopt(udp, SOL_SOCKET, SO_BROADCAST, (char *) &val , sizeof(val)); |
337 setsockopt(*udp, SOL_SOCKET, SO_BROADCAST, (char *) &val , sizeof(val)); |
307 val = 1; |
338 } |
308 setsockopt(udp, SOL_SOCKET, SO_REUSEADDR, (char *) &val , sizeof(val)); |
|
309 } |
|
310 |
|
311 if (_network_udp_server) |
|
312 _udp_server_socket = udp; |
|
313 else |
|
314 _udp_client_socket = udp; |
|
315 |
339 |
316 DEBUG(net, 1)("[NET][UDP] Listening on port %s:%d", inet_ntoa(*(struct in_addr *)&host), port); |
340 DEBUG(net, 1)("[NET][UDP] Listening on port %s:%d", inet_ntoa(*(struct in_addr *)&host), port); |
317 |
341 |
318 return true; |
342 return true; |
319 } |
343 } |
320 |
344 |
321 // Close UDP connection |
345 // Close UDP connection |
322 void NetworkUDPClose(void) |
346 void NetworkUDPClose(void) |
323 { |
347 { |
324 DEBUG(net, 1) ("[NET][UDP] Closed listener"); |
348 DEBUG(net, 1) ("[NET][UDP] Closed listeners"); |
325 |
349 |
326 if (_network_udp_server) { |
350 if (_network_udp_server) { |
327 closesocket(_udp_server_socket); |
351 closesocket(_udp_server_socket); |
328 _udp_server_socket = INVALID_SOCKET; |
352 _udp_server_socket = INVALID_SOCKET; |
|
353 |
|
354 closesocket(_udp_master_socket); |
|
355 _udp_master_socket = INVALID_SOCKET; |
|
356 |
329 _network_udp_server = false; |
357 _network_udp_server = false; |
330 _network_udp_broadcast = 0; |
358 _network_udp_broadcast = 0; |
331 } else { |
359 } else { |
332 closesocket(_udp_client_socket); |
360 closesocket(_udp_client_socket); |
333 _udp_client_socket = INVALID_SOCKET; |
361 _udp_client_socket = INVALID_SOCKET; |
334 _network_udp_broadcast = 0; |
362 _network_udp_broadcast = 0; |
335 } |
363 } |
336 } |
364 } |
337 |
365 |
338 // Receive something on UDP level |
366 // Receive something on UDP level |
339 void NetworkUDPReceive(void) |
367 void NetworkUDPReceive(SOCKET udp) |
340 { |
368 { |
341 struct sockaddr_in client_addr; |
369 struct sockaddr_in client_addr; |
342 #ifndef __MORPHOS__ |
370 #ifndef __MORPHOS__ |
343 int client_len; |
371 int client_len; |
344 #else |
372 #else |
345 LONG client_len; // for some reason we need a 'LONG' under MorphOS |
373 LONG client_len; // for some reason we need a 'LONG' under MorphOS |
346 #endif |
374 #endif |
347 int nbytes; |
375 int nbytes; |
348 static Packet *p = NULL; |
376 static Packet *p = NULL; |
349 int packet_len; |
377 int packet_len; |
350 SOCKET udp; |
|
351 |
|
352 if (_network_udp_server) |
|
353 udp = _udp_server_socket; |
|
354 else |
|
355 udp = _udp_client_socket; |
|
356 |
378 |
357 // If p is NULL, malloc him.. this prevents unneeded mallocs |
379 // If p is NULL, malloc him.. this prevents unneeded mallocs |
358 if (p == NULL) |
380 if (p == NULL) |
359 p = malloc(sizeof(Packet)); |
381 p = malloc(sizeof(Packet)); |
360 |
382 |
406 |
428 |
407 out_addr.sin_family = AF_INET; |
429 out_addr.sin_family = AF_INET; |
408 out_addr.sin_port = htons(_network_server_port); |
430 out_addr.sin_port = htons(_network_server_port); |
409 out_addr.sin_addr.s_addr = bcaddr; |
431 out_addr.sin_addr.s_addr = bcaddr; |
410 |
432 |
411 NetworkSendUDP_Packet(p, &out_addr); |
433 NetworkSendUDP_Packet(udp, p, &out_addr); |
412 |
434 |
413 i++; |
435 i++; |
414 } |
436 } |
|
437 } |
|
438 |
|
439 |
|
440 // Request the the server-list from the master server |
|
441 void NetworkUDPQueryMasterServer(void) |
|
442 { |
|
443 struct sockaddr_in out_addr; |
|
444 Packet *p; |
|
445 |
|
446 if (_udp_client_socket == INVALID_SOCKET) |
|
447 if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true)) |
|
448 return; |
|
449 |
|
450 p = NetworkSend_Init(PACKET_UDP_CLIENT_GET_LIST); |
|
451 |
|
452 out_addr.sin_family = AF_INET; |
|
453 out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT); |
|
454 out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST); |
|
455 |
|
456 // packet only contains protocol version |
|
457 NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION); |
|
458 |
|
459 NetworkSendUDP_Packet(_udp_client_socket, p, &out_addr); |
|
460 |
|
461 DEBUG(net, 2)("[NET][UDP] Queried Master Server at %s:%d", inet_ntoa(out_addr.sin_addr),ntohs(out_addr.sin_port)); |
415 |
462 |
416 free(p); |
463 free(p); |
417 } |
464 } |
418 |
465 |
419 // Find all servers |
466 // Find all servers |
479 |
526 |
480 /* Check if we should send an advertise */ |
527 /* Check if we should send an advertise */ |
481 if (!_networking || !_network_server || !_network_udp_server || !_network_advertise) |
528 if (!_networking || !_network_server || !_network_udp_server || !_network_advertise) |
482 return; |
529 return; |
483 |
530 |
|
531 /* check for socket */ |
|
532 if (_udp_master_socket == INVALID_SOCKET) |
|
533 if (!NetworkUDPListen(&_udp_master_socket, 0, 0, false)) |
|
534 return; |
|
535 |
484 /* Only send once in the 450 game-days (about 15 minutes) */ |
536 /* Only send once in the 450 game-days (about 15 minutes) */ |
485 if (_network_last_advertise_date + 450 > _date) |
537 if (_network_advertise_retries == 0) { |
|
538 if ( (_network_last_advertise_date + ADVERTISE_NORMAL_INTERVAL) > _date) |
|
539 return; |
|
540 _network_advertise_retries = ADVERTISE_RETRY_TIMES; |
|
541 } |
|
542 |
|
543 if ( (_network_last_advertise_date + ADVERTISE_RETRY_INTERVAL) > _date) |
486 return; |
544 return; |
|
545 |
|
546 _network_advertise_retries--; |
487 _network_last_advertise_date = _date; |
547 _network_last_advertise_date = _date; |
488 |
548 |
489 /* Find somewhere to send */ |
549 /* Find somewhere to send */ |
490 out_addr.sin_family = AF_INET; |
550 out_addr.sin_family = AF_INET; |
491 out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT); |
551 out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT); |
497 p = NetworkSend_Init(PACKET_UDP_SERVER_REGISTER); |
557 p = NetworkSend_Init(PACKET_UDP_SERVER_REGISTER); |
498 /* Packet is: WELCOME_MESSAGE, Version, server_port */ |
558 /* Packet is: WELCOME_MESSAGE, Version, server_port */ |
499 NetworkSend_string(p, NETWORK_MASTER_SERVER_WELCOME_MESSAGE); |
559 NetworkSend_string(p, NETWORK_MASTER_SERVER_WELCOME_MESSAGE); |
500 NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION); |
560 NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION); |
501 NetworkSend_uint16(p, _network_server_port); |
561 NetworkSend_uint16(p, _network_server_port); |
502 NetworkSendUDP_Packet(p, &out_addr); |
562 NetworkSendUDP_Packet(_udp_master_socket, p, &out_addr); |
|
563 |
503 free(p); |
564 free(p); |
504 } |
565 } |
505 |
566 |
506 void NetworkUDPInitialize(void) |
567 void NetworkUDPInitialize(void) |
507 { |
568 { |
508 _udp_client_socket = INVALID_SOCKET; |
569 _udp_client_socket = INVALID_SOCKET; |
509 _udp_server_socket = INVALID_SOCKET; |
570 _udp_server_socket = INVALID_SOCKET; |
|
571 _udp_master_socket = INVALID_SOCKET; |
510 |
572 |
511 _network_udp_server = false; |
573 _network_udp_server = false; |
512 _network_udp_broadcast = 0; |
574 _network_udp_broadcast = 0; |
513 } |
575 } |
514 |
576 |