Changeset - r18895:278eef2e977c
[Not reviewed]
master
0 1 0
rubidium - 13 years ago 2012-01-05 17:08:49
rubidium@openttd.org
(svn r23754) -Fix (r23752): the locks aren't reentrant
1 file changed with 65 insertions and 55 deletions:
0 comments (0 inline, 0 general)
src/network/network_udp.cpp
Show inline comments
 
@@ -45,12 +45,76 @@ static const uint ADVERTISE_RETRY_INTERV
 
static const uint ADVERTISE_RETRY_TIMES     =     3; ///< give up readvertising after this much failed retries
 

	
 
NetworkUDPSocketHandler *_udp_client_socket = NULL; ///< udp client socket
 
NetworkUDPSocketHandler *_udp_server_socket = NULL; ///< udp server socket
 
NetworkUDPSocketHandler *_udp_master_socket = NULL; ///< udp master socket
 

	
 
/** Simpler wrapper struct for NetworkUDPQueryServerThread */
 
struct NetworkUDPQueryServerInfo : NetworkAddress {
 
	bool manually; ///< Did we connect manually or not?
 

	
 
	/**
 
	 * Create the structure.
 
	 * @param address The address of the server to query.
 
	 * @param manually Whether the address was entered manually.
 
	 */
 
	NetworkUDPQueryServerInfo(const NetworkAddress &address, bool manually) :
 
		NetworkAddress(address),
 
		manually(manually)
 
	{
 
	}
 
};
 

	
 
/**
 
 * Helper function doing the actual work for querying the server.
 
 * @param address The address of the server.
 
 * @param needs_mutex Whether we need to acquire locks when sending the packet or not.
 
 * @param manually Whether the address was entered manually.
 
 */
 
static void NetworkUDPQueryServer(NetworkAddress *address, bool needs_mutex, bool manually)
 
{
 
	/* Clear item in gamelist */
 
	NetworkGameList *item = CallocT<NetworkGameList>(1);
 
	address->GetAddressAsString(item->info.server_name, lastof(item->info.server_name));
 
	strecpy(item->info.hostname, address->GetHostname(), lastof(item->info.hostname));
 
	item->address = *address;
 
	item->manually = manually;
 
	NetworkGameListAddItemDelayed(item);
 

	
 
	if (needs_mutex) _network_udp_mutex->BeginCritical();
 
	/* Init the packet */
 
	Packet p(PACKET_UDP_CLIENT_FIND_SERVER);
 
	if (_udp_client_socket != NULL) _udp_client_socket->SendPacket(&p, address);
 
	if (needs_mutex) _network_udp_mutex->EndCritical();
 
}
 

	
 
/**
 
 * Threaded part for resolving the IP of a server and querying it.
 
 * @param pntr the NetworkUDPQueryServerInfo.
 
 */
 
static void NetworkUDPQueryServerThread(void *pntr)
 
{
 
	NetworkUDPQueryServerInfo *info = (NetworkUDPQueryServerInfo*)pntr;
 
	NetworkUDPQueryServer(info, true, info->manually);
 

	
 
	delete info;
 
}
 

	
 
/**
 
 * Query a specific server.
 
 * @param address The address of the server.
 
 * @param manually Whether the address was entered manually.
 
 */
 
void NetworkUDPQueryServer(NetworkAddress address, bool manually)
 
{
 
	NetworkUDPQueryServerInfo *info = new NetworkUDPQueryServerInfo(address, manually);
 
	if (address.IsResolved() || !ThreadObject::New(NetworkUDPQueryServerThread, info)) {
 
		NetworkUDPQueryServerThread(info);
 
	}
 
}
 

	
 
///*** Communication with the masterserver ***/
 

	
 
/** Helper class for connecting to the master server. */
 
class MasterNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
 
protected:
 
	virtual void Receive_MASTER_ACK_REGISTER(Packet *p, NetworkAddress *client_addr);
 
@@ -361,13 +425,13 @@ void ClientNetworkUDPSocketHandler::Rece
 
			NetworkAddress addr(addr_storage, type == SLT_IPv4 ? sizeof(sockaddr_in) : sizeof(sockaddr_in6));
 
			addr.SetPort(p->Recv_uint16());
 

	
 
			/* Somehow we reached the end of the packet */
 
			if (this->HasClientQuit()) return;
 

	
 
			NetworkUDPQueryServer(addr);
 
			NetworkUDPQueryServer(&addr, false, false);
 
		}
 
	}
 
}
 

	
 
/** The return of the client's request of the names of some NewGRFs */
 
void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAddress *client_addr)
 
@@ -465,66 +529,12 @@ void NetworkUDPSearchGame()
 
	DEBUG(net, 0, "[udp] searching server");
 

	
 
	NetworkUDPBroadCast(_udp_client_socket);
 
	_network_udp_broadcast = 300; // Stay searching for 300 ticks
 
}
 

	
 
/** Simpler wrapper struct for NetworkUDPQueryServerThread */
 
struct NetworkUDPQueryServerInfo : NetworkAddress {
 
	bool manually; ///< Did we connect manually or not?
 

	
 
	/**
 
	 * Create the structure.
 
	 * @param address The address of the server to query.
 
	 * @param manually Whether the address was entered manually.
 
	 */
 
	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.
 
 */
 
static void NetworkUDPQueryServerThread(void *pntr)
 
{
 
	NetworkUDPQueryServerInfo *info = (NetworkUDPQueryServerInfo*)pntr;
 

	
 
	/* Clear item in gamelist */
 
	NetworkGameList *item = CallocT<NetworkGameList>(1);
 
	info->GetAddressAsString(item->info.server_name, lastof(item->info.server_name));
 
	strecpy(item->info.hostname, info->GetHostname(), lastof(item->info.hostname));
 
	item->address = *info;
 
	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, info);
 
	_network_udp_mutex->EndCritical();
 

	
 
	delete info;
 
}
 

	
 
/**
 
 * Query a specific server.
 
 * @param address The address of the server.
 
 * @param manually Whether the address was entered manually.
 
 */
 
void NetworkUDPQueryServer(NetworkAddress address, bool manually)
 
{
 
	NetworkUDPQueryServerInfo *info = new NetworkUDPQueryServerInfo(address, manually);
 
	if (address.IsResolved() || !ThreadObject::New(NetworkUDPQueryServerThread, info)) {
 
		NetworkUDPQueryServerThread(info);
 
	}
 
}
 

	
 
/**
 
 * Thread entry point for de-advertising.
 
 * @param pntr unused.
 
 */
 
static void NetworkUDPRemoveAdvertiseThread(void *pntr)
 
{
0 comments (0 inline, 0 general)