@ -20,14 +20,18 @@
# include "../variables.h"
# include "../newgrf_config.h"
# include "../core/endian_func.hpp"
# include "../core/alloc_func.hpp"
# include "../string_func.h"
# include "../company_base.h"
# include "../company_func.h"
# include "../settings_type.h"
# include "../thread.h"
# include "../rev.h"
# include "core/udp.h"
ThreadMutex * _network_udp_mutex = ThreadMutex : : New ( ) ;
enum {
ADVERTISE_NORMAL_INTERVAL = 30000 , // interval between advertising in ticks (15 minutes)
ADVERTISE_RETRY_INTERVAL = 300 , // readvertise when no response after this many ticks (9 seconds)
@ -352,9 +356,11 @@ void NetworkUDPCloseAll()
{
DEBUG ( net , 1 , " [udp] closed listeners " ) ;
_network_udp_mutex - > BeginCritical ( ) ;
_udp_server_socket - > Close ( ) ;
_udp_master_socket - > Close ( ) ;
_udp_client_socket - > Close ( ) ;
_network_udp_mutex - > EndCritical ( ) ;
_network_udp_server = false ;
_network_udp_broadcast = 0 ;
@ -420,44 +426,84 @@ void NetworkUDPSearchGame()
_network_udp_broadcast = 300 ; // Stay searching for 300 ticks
}
void NetworkUDPQueryServer ( NetworkAddress address , bool manually )
/** Simpler wrapper struct for NetworkUDPQueryServerThread */
struct NetworkUDPQueryServerInfo : NetworkAddress {
bool manually ; ///< Did we connect manually or not?
NetworkUDPQueryServerInfo ( const NetworkAddress & address , bool manually ) :
NetworkAddress ( address ) ,
manually ( manually )
{
}
} ;
/**
* Threaded part for resolving the IP of a server and querying it .
* @ param pntr the NetworkUDPQueryServerInfo .
*/
void NetworkUDPQueryServerThread ( void * pntr )
{
NetworkUDPQueryServerInfo * info = ( NetworkUDPQueryServerInfo * ) pntr ;
struct sockaddr_in out_addr ;
NetworkGameList * item ;
out_addr . sin_family = AF_INET ;
out_addr . sin_port = htons ( info - > GetPort ( ) ) ;
out_addr . sin_addr . s_addr = info - > GetIP ( ) ;
/* Clear item in gamelist */
NetworkGameList * item = CallocT < NetworkGameList > ( 1 ) ;
item - > ip = info - > GetIP ( ) ;
item - > port = info - > GetPort ( ) ;
strecpy ( item - > info . server_name , info - > GetHostname ( ) , lastof ( item - > info . server_name ) ) ;
strecpy ( item - > info . hostname , info - > GetHostname ( ) , lastof ( item - > info . hostname ) ) ;
item - > manually = info - > manually ;
NetworkGameListAddItemDelayed ( item ) ;
_network_udp_mutex - > BeginCritical ( ) ;
/* Init the packet */
Packet p ( PACKET_UDP_CLIENT_FIND_SERVER ) ;
if ( _udp_client_socket ! = NULL ) _udp_client_socket - > SendPacket ( & p , & out_addr ) ;
_network_udp_mutex - > EndCritical ( ) ;
delete info ;
}
void NetworkUDPQueryServer ( NetworkAddress address , bool manually )
{
// No UDP-socket yet..
if ( ! _udp_client_socket - > IsConnected ( ) ) {
if ( ! _udp_client_socket - > Listen ( 0 , 0 , true ) ) return ;
}
out_addr . sin_family = AF_INET ;
out_addr . sin_port = htons ( address . GetPort ( ) ) ;
out_addr . sin_addr . s_addr = address . GetIP ( ) ;
// Clear item in gamelist
item = NetworkGameListAddItem ( address . GetIP ( ) , address . GetPort ( ) ) ;
if ( item = = NULL ) return ;
if ( StrEmpty ( item - > info . server_name ) ) {
memset ( & item - > info , 0 , sizeof ( item - > info ) ) ;
strecpy ( item - > info . server_name , address . GetHostname ( ) , lastof ( item - > info . server_name ) ) ;
strecpy ( item - > info . hostname , address . GetHostname ( ) , lastof ( item - > info . hostname ) ) ;
item - > online = false ;
NetworkUDPQueryServerInfo * info = new NetworkUDPQueryServerInfo ( address , manually ) ;
if ( address . IsResolved ( ) | | ! ThreadObject : : New ( NetworkUDPQueryServerThread , info ) ) {
NetworkUDPQueryServerThread ( info ) ;
}
item - > manually = manually ;
}
// Init the packet
Packet p ( PACKET_UDP_CLIENT_FIND_SERVER ) ;
_udp_client_socket- > SendPacket ( & p , & out_addr ) ;
void NetworkUDPRemoveAdvertiseThread ( void * pntr )
{
DEBUG ( net , 1 , " [udp] removing advertise from master server " ) ;
UpdateNetworkGameWindow ( false ) ;
/* Find somewhere to send */
struct sockaddr_in out_addr ;
out_addr . sin_family = AF_INET ;
out_addr . sin_port = htons ( NETWORK_MASTER_SERVER_PORT ) ;
out_addr . sin_addr . s_addr = NetworkResolveHost ( NETWORK_MASTER_SERVER_HOST ) ;
/* Send the packet */
Packet p ( PACKET_UDP_SERVER_UNREGISTER ) ;
/* Packet is: Version, server_port */
p . Send_uint8 ( NETWORK_MASTER_SERVER_VERSION ) ;
p . Send_uint16 ( _settings_client . network . server_port ) ;
_network_udp_mutex - > BeginCritical ( ) ;
if ( _udp_master_socket ! = NULL ) _udp_master_socket - > SendPacket ( & p , & out_addr ) ;
_network_udp_mutex - > EndCritical ( ) ;
}
/* Remove our advertise from the master-server */
void NetworkUDPRemoveAdvertise ( )
{
struct sockaddr_in out_addr ;
/* Check if we are advertising */
if ( ! _networking | | ! _network_server | | ! _network_udp_server ) return ;
@ -466,27 +512,37 @@ void NetworkUDPRemoveAdvertise()
if ( ! _udp_master_socket - > Listen ( _network_server_bind_ip , 0 , false ) ) return ;
}
DEBUG ( net , 1 , " [udp] removing advertise from master server " ) ;
if ( ! ThreadObject : : New ( NetworkUDPRemoveAdvertiseThread , NULL ) ) {
NetworkUDPRemoveAdvertiseThread ( NULL ) ;
}
}
void NetworkUDPAdvertiseThread ( void * pntr )
{
/* Find somewhere to send */
struct sockaddr_in out_addr ;
out_addr . sin_family = AF_INET ;
out_addr . sin_port = htons ( NETWORK_MASTER_SERVER_PORT ) ;
out_addr . sin_addr . s_addr = NetworkResolveHost ( NETWORK_MASTER_SERVER_HOST ) ;
DEBUG ( net , 1 , " [udp] advertising to master server " ) ;
/* Send the packet */
Packet p ( PACKET_UDP_SERVER_UNREGISTER ) ;
/* Packet is: Version, server_port */
Packet p ( PACKET_UDP_SERVER_REGISTER ) ;
/* Packet is: WELCOME_MESSAGE, Version, server_port */
p . Send_string ( NETWORK_MASTER_SERVER_WELCOME_MESSAGE ) ;
p . Send_uint8 ( NETWORK_MASTER_SERVER_VERSION ) ;
p . Send_uint16 ( _settings_client . network . server_port ) ;
_udp_master_socket - > SendPacket ( & p , & out_addr ) ;
_network_udp_mutex - > BeginCritical ( ) ;
if ( _udp_master_socket ! = NULL ) _udp_master_socket - > SendPacket ( & p , & out_addr ) ;
_network_udp_mutex - > EndCritical ( ) ;
}
/* Register us to the master server
This function checks if it needs to send an advertise */
void NetworkUDPAdvertise ( )
{
struct sockaddr_in out_addr ;
/* Check if we should send an advertise */
if ( ! _networking | | ! _network_server | | ! _network_udp_server | | ! _settings_client . network . server_advertise )
return ;
@ -514,44 +570,37 @@ void NetworkUDPAdvertise()
_network_advertise_retries - - ;
_network_last_advertise_frame = _frame_counter ;
/* Find somewhere to send */
out_addr . sin_family = AF_INET ;
out_addr . sin_port = htons ( NETWORK_MASTER_SERVER_PORT ) ;
out_addr . sin_addr . s_addr = NetworkResolveHost ( NETWORK_MASTER_SERVER_HOST ) ;
DEBUG ( net , 1 , " [udp] advertising to master server " ) ;
/* Send the packet */
Packet p ( PACKET_UDP_SERVER_REGISTER ) ;
/* Packet is: WELCOME_MESSAGE, Version, server_port */
p . Send_string ( NETWORK_MASTER_SERVER_WELCOME_MESSAGE ) ;
p . Send_uint8 ( NETWORK_MASTER_SERVER_VERSION ) ;
p . Send_uint16 ( _settings_client . network . server_port ) ;
_udp_master_socket - > SendPacket ( & p , & out_addr ) ;
if ( ! ThreadObject : : New ( NetworkUDPAdvertiseThread , NULL ) ) {
NetworkUDPAdvertiseThread ( NULL ) ;
}
}
void NetworkUDPInitialize ( )
{
assert ( _udp_client_socket = = NULL & & _udp_server_socket = = NULL & & _udp_master_socket = = NULL ) ;
_network_udp_mutex - > BeginCritical ( ) ;
_udp_client_socket = new ClientNetworkUDPSocketHandler ( ) ;
_udp_server_socket = new ServerNetworkUDPSocketHandler ( ) ;
_udp_master_socket = new MasterNetworkUDPSocketHandler ( ) ;
_network_udp_server = false ;
_network_udp_broadcast = 0 ;
_network_udp_mutex - > EndCritical ( ) ;
}
void NetworkUDPShutdown ( )
{
NetworkUDPCloseAll ( ) ;
_network_udp_mutex - > BeginCritical ( ) ;
delete _udp_client_socket ;
delete _udp_server_socket ;
delete _udp_master_socket ;
_udp_client_socket = NULL ;
_udp_server_socket = NULL ;
_udp_master_socket = NULL ;
_network_udp_mutex - > EndCritical ( ) ;
}
# endif /* ENABLE_NETWORK */