Changeset - r25388:32b23efdcf4e
[Not reviewed]
master
0 14 0
Patric Stout - 4 years ago 2021-05-05 21:21:14
truebrain@openttd.org
Codechange: use connection_string in favour of NetworkAddress (#9197)

We now resolve the connection_string to a NetworkAddress in a much
later state. This means there are fewer places constructing a NetworkAddress.

The main benefit of this is in later PRs that introduce different types
of NetworkAddresses. Storing this in things like NetworkGameList is
rather complex, especially as NetworkAddress has to be mutable at all
times.

Additionally, the NetworkAddress is a complex object to store simple
information: how to connect to this server.
14 files changed with 94 insertions and 100 deletions:
0 comments (0 inline, 0 general)
src/network/core/tcp.h
Show inline comments
 
@@ -74,13 +74,13 @@ private:
 

	
 
protected:
 
	/** Address we're connecting to */
 
	NetworkAddress address;
 

	
 
public:
 
	TCPConnecter(const NetworkAddress &address);
 
	TCPConnecter(const std::string &connection_string, uint16 default_port);
 
	/** Silence the warnings */
 
	virtual ~TCPConnecter() {}
 

	
 
	/**
 
	 * Callback when the connection succeeded.
 
	 * @param s the socket that we opened
src/network/core/tcp_connect.cpp
Show inline comments
 
@@ -10,29 +10,31 @@
 
 */
 

	
 
#include "../../stdafx.h"
 
#include "../../thread.h"
 

	
 
#include "tcp.h"
 
#include "../network_internal.h"
 

	
 
#include "../../safeguards.h"
 

	
 
/** List of connections that are currently being created */
 
static std::vector<TCPConnecter *> _tcp_connecters;
 

	
 
/**
 
 * Create a new connecter for the given address
 
 * @param address the (un)resolved address to connect to
 
 * @param connection_string the address to connect to
 
 */
 
TCPConnecter::TCPConnecter(const NetworkAddress &address) :
 
TCPConnecter::TCPConnecter(const std::string &connection_string, uint16 default_port) :
 
	connected(false),
 
	aborted(false),
 
	killed(false),
 
	sock(INVALID_SOCKET),
 
	address(address)
 
	sock(INVALID_SOCKET)
 
{
 
	this->address = ParseConnectionString(connection_string, default_port);
 

	
 
	_tcp_connecters.push_back(this);
 
	if (!StartNewThread(nullptr, "ottd:tcp", &TCPConnecter::ThreadEntry, this)) {
 
		this->Connect();
 
	}
 
}
 

	
src/network/core/tcp_http.cpp
Show inline comments
 
@@ -200,17 +200,15 @@ int NetworkHTTPSocketHandler::HandleHead
 

	
 
	char *url = strchr(hname, '/');
 
	if (url == nullptr) return_error("[tcp/http] invalid location");
 

	
 
	*url = '\0';
 

	
 
	NetworkAddress address = ParseConnectionString(hname, 80);
 

	
 
	/* Restore the URL. */
 
	*url = '/';
 
	new NetworkHTTPContentConnecter(address, callback, url, data, depth);
 
	new NetworkHTTPContentConnecter(hname, callback, url, data, depth);
 
	return 0;
 
}
 

	
 
#undef return_error
 

	
 
/**
src/network/core/tcp_http.h
Show inline comments
 
@@ -78,22 +78,20 @@ class NetworkHTTPContentConnecter : TCPC
 
	const char *data;       ///< The data to send
 
	int depth;              ///< How far we have recursed
 

	
 
public:
 
	/**
 
	 * Start the connecting.
 
	 * @param address  the address to connect to
 
	 * @param callback the callback for HTTP retrieval
 
	 * @param url      the url at the server
 
	 * @param data     the data to send
 
	 * @param depth    the depth (redirect recursion) of the queries
 
	 * @param connection_string The address to connect to.
 
	 * @param callback The callback for HTTP retrieval.
 
	 * @param url The url at the server.
 
	 * @param data The data to send.
 
	 * @param depth The depth (redirect recursion) of the queries.
 
	 */
 
	NetworkHTTPContentConnecter(const NetworkAddress &address,
 
			HTTPCallback *callback, const char *url,
 
			const char *data = nullptr, int depth = 0) :
 
		TCPConnecter(address),
 
	NetworkHTTPContentConnecter(const std::string &connection_string, HTTPCallback *callback, const char *url, const char *data = nullptr, int depth = 0) :
 
		TCPConnecter(connection_string, 80),
 
		callback(callback),
 
		url(stredup(url)),
 
		data(data),
 
		depth(depth)
 
	{
 
	}
src/network/network.cpp
Show inline comments
 
@@ -512,22 +512,35 @@ NetworkAddress ParseConnectionString(con
 
 *
 
 * @param company Pointer to the company variable to set iff indicted.
 
 * @param connection_string The string to parse.
 
 * @param default_port The default port to set port to if not in connection_string.
 
 * @return A valid NetworkAddress of the parsed information.
 
 */
 
NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string &connection_string, int default_port)
 
static NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string &connection_string, int default_port)
 
{
 
	char internal_connection_string[NETWORK_HOSTNAME_PORT_LENGTH + 4]; // 4 extra for the "#" and company
 
	strecpy(internal_connection_string, connection_string.c_str(), lastof(internal_connection_string));
 

	
 
	const char *port_s = nullptr;
 
	const char *company_s = nullptr;
 
	ParseFullConnectionString(&company_s, &port_s, internal_connection_string);
 

	
 
	if (company_s != nullptr) *company = (CompanyID)atoi(company_s);
 
	if (company_s != nullptr) {
 
		uint company_value = atoi(company_s);
 

	
 
		if (company_value != COMPANY_NEW_COMPANY && company_value != COMPANY_SPECTATOR) {
 
			if (company_value > MAX_COMPANIES || company_value == 0) {
 
				*company = COMPANY_SPECTATOR;
 
			} else {
 
				/* "#1" means the first company, which has index 0. */
 
				*company = (CompanyID)(company_value - 1);
 
			}
 
		} else {
 
			*company = (CompanyID)company_value;
 
		}
 
	}
 

	
 
	int port = port_s != nullptr ? atoi(port_s) : default_port;
 
	return NetworkAddress(internal_connection_string, port);
 
}
 

	
 
/**
 
@@ -604,42 +617,43 @@ static void NetworkInitialize(bool close
 
}
 

	
 
/** Non blocking connection create to query servers */
 
class TCPQueryConnecter : TCPConnecter {
 
private:
 
	bool request_company_info;
 
	std::string connection_string;
 

	
 
public:
 
	TCPQueryConnecter(const NetworkAddress &address, bool request_company_info) : TCPConnecter(address), request_company_info(request_company_info) {}
 
	TCPQueryConnecter(const std::string &connection_string, bool request_company_info) : TCPConnecter(connection_string, NETWORK_DEFAULT_PORT), request_company_info(request_company_info), connection_string(connection_string) {}
 

	
 
	void OnFailure() override
 
	{
 
		NetworkDisconnect();
 
	}
 

	
 
	void OnConnect(SOCKET s) override
 
	{
 
		_networking = true;
 
		new ClientNetworkGameSocketHandler(s, address);
 
		new ClientNetworkGameSocketHandler(s, this->connection_string);
 
		MyClient::SendInformationQuery(request_company_info);
 
	}
 
};
 

	
 
/**
 
 * Query a server to fetch his game-info.
 
 * @param address the address to query.
 
 * @param connection_string the address to query.
 
 * @param request_company_info Whether to request company info too.
 
 */
 
void NetworkTCPQueryServer(NetworkAddress address, bool request_company_info)
 
void NetworkTCPQueryServer(const std::string &connection_string, bool request_company_info)
 
{
 
	if (!_network_available) return;
 

	
 
	NetworkDisconnect();
 
	NetworkInitialize();
 

	
 
	new TCPQueryConnecter(address, request_company_info);
 
	new TCPQueryConnecter(connection_string, request_company_info);
 
}
 

	
 
/**
 
 * Validates an address entered as a string and adds the server to
 
 * the list. If you use this function, the games will be marked
 
 * as manually added.
 
@@ -647,26 +661,24 @@ void NetworkTCPQueryServer(NetworkAddres
 
 * @return The entry on the game list.
 
 */
 
NetworkGameList *NetworkAddServer(const std::string &connection_string)
 
{
 
	if (connection_string.empty()) return nullptr;
 

	
 
	NetworkAddress address = ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT);
 

	
 
	/* Ensure the item already exists in the list */
 
	NetworkGameList *item = NetworkGameListAddItem(address);
 
	NetworkGameList *item = NetworkGameListAddItem(connection_string);
 
	if (StrEmpty(item->info.server_name)) {
 
		ClearGRFConfigList(&item->info.grfconfig);
 
		address.GetAddressAsString(item->info.server_name, lastof(item->info.server_name));
 
		strecpy(item->info.server_name, connection_string.c_str(), lastof(item->info.server_name));
 
		item->manually = true;
 

	
 
		NetworkRebuildHostList();
 
		UpdateNetworkGameWindow();
 
	}
 

	
 
	NetworkTCPQueryServer(address);
 
	NetworkTCPQueryServer(connection_string);
 

	
 
	return item;
 
}
 

	
 
/**
 
 * Get the addresses to bind to.
 
@@ -690,30 +702,33 @@ void GetBindAddresses(NetworkAddressList
 
 * by the function that generates the config file. */
 
void NetworkRebuildHostList()
 
{
 
	_network_host_list.clear();
 

	
 
	for (NetworkGameList *item = _network_game_list; item != nullptr; item = item->next) {
 
		if (item->manually) _network_host_list.emplace_back(item->address.GetAddressAsString(false));
 
		if (item->manually) _network_host_list.emplace_back(item->connection_string);
 
	}
 
}
 

	
 
/** Non blocking connection create to actually connect to servers */
 
class TCPClientConnecter : TCPConnecter {
 
private:
 
	std::string connection_string;
 

	
 
public:
 
	TCPClientConnecter(const NetworkAddress &address) : TCPConnecter(address) {}
 
	TCPClientConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_DEFAULT_PORT), connection_string(connection_string) {}
 

	
 
	void OnFailure() override
 
	{
 
		ShowNetworkError(STR_NETWORK_ERROR_NOCONNECTION);
 
	}
 

	
 
	void OnConnect(SOCKET s) override
 
	{
 
		_networking = true;
 
		new ClientNetworkGameSocketHandler(s, this->address);
 
		new ClientNetworkGameSocketHandler(s, this->connection_string);
 
		IConsoleCmdExec("exec scripts/on_client.scr 0");
 
		NetworkClient_Connected();
 
	}
 
};
 

	
 
/**
 
@@ -733,40 +748,18 @@ public:
 
 * @param join_company_password The password for the company.
 
 * @return Whether the join has started.
 
 */
 
bool NetworkClientConnectGame(const std::string &connection_string, CompanyID default_company, const char *join_server_password, const char *join_company_password)
 
{
 
	CompanyID join_as = default_company;
 
	NetworkAddress address = ParseGameConnectionString(&join_as, connection_string, NETWORK_DEFAULT_PORT);
 

	
 
	if (join_as != COMPANY_NEW_COMPANY && join_as != COMPANY_SPECTATOR) {
 
		join_as--;
 
		if (join_as >= MAX_COMPANIES) {
 
			return false;
 
		}
 
	}
 

	
 
	return NetworkClientConnectGame(address, join_as, join_server_password, join_company_password);
 
}
 
	std::string resolved_connection_string = ParseGameConnectionString(&join_as, connection_string, NETWORK_DEFAULT_PORT).GetAddressAsString(false);
 

	
 
/**
 
 * Join a client to the server at the given address.
 
 * See the overloaded NetworkClientConnectGame for more details.
 
 *
 
 * @param address               The network address of the server to join to.
 
 * @param join_as               The company number to join as.
 
 * @param join_server_password  The password for the server.
 
 * @param join_company_password The password for the company.
 
 * @return Whether the join has started.
 
 */
 
bool NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password, const char *join_company_password)
 
{
 
	if (!_network_available) return false;
 
	if (!NetworkValidateClientName()) return false;
 

	
 
	_network_join.address = address;
 
	_network_join.connection_string = resolved_connection_string;
 
	_network_join.company = join_as;
 
	_network_join.server_password = join_server_password;
 
	_network_join.company_password = join_company_password;
 

	
 
	if (_game_mode == GM_MENU) {
 
		/* From the menu we can immediately continue with the actual join. */
 
@@ -789,17 +782,17 @@ bool NetworkClientConnectGame(NetworkAdd
 
 */
 
void NetworkClientJoinGame()
 
{
 
	NetworkDisconnect();
 
	NetworkInitialize();
 

	
 
	strecpy(_settings_client.network.last_joined, _network_join.address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined));
 
	strecpy(_settings_client.network.last_joined, _network_join.connection_string.c_str(), lastof(_settings_client.network.last_joined));
 
	_network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
 
	ShowJoinStatusWindow();
 

	
 
	new TCPClientConnecter(_network_join.address);
 
	new TCPClientConnecter(_network_join.connection_string);
 
}
 

	
 
static void NetworkInitGameInfo()
 
{
 
	if (StrEmpty(_settings_client.network.server_name)) {
 
		strecpy(_settings_client.network.server_name, "Unnamed Server", lastof(_settings_client.network.server_name));
src/network/network_client.cpp
Show inline comments
 
@@ -142,13 +142,13 @@ void ClientNetworkEmergencySave()
 

	
 

	
 
/**
 
 * Create a new socket for the client side of the game connection.
 
 * @param s The socket to connect with.
 
 */
 
ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s, NetworkAddress address) : NetworkGameSocketHandler(s), address(address), savegame(nullptr), status(STATUS_INACTIVE)
 
ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s, const std::string &connection_string) : NetworkGameSocketHandler(s), connection_string(connection_string), savegame(nullptr), status(STATUS_INACTIVE)
 
{
 
	assert(ClientNetworkGameSocketHandler::my_client == nullptr);
 
	ClientNetworkGameSocketHandler::my_client = this;
 
}
 

	
 
/** Clear whatever we assigned. */
 
@@ -578,13 +578,13 @@ NetworkRecvStatus ClientNetworkGameSocke
 
{
 
	if (this->status != STATUS_COMPANY_INFO && this->status != STATUS_GAME_INFO) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 

	
 
	NetworkGameList *item = GetLobbyGameInfo();
 
	if (item == nullptr) {
 
		/* This is not the lobby, so add it to the game list. */
 
		item = NetworkGameListAddItem(this->address);
 
		item = NetworkGameListAddItem(this->connection_string);
 
	}
 

	
 
	/* Clear any existing GRFConfig chain. */
 
	ClearGRFConfigList(&item->info.grfconfig);
 
	/* Retrieve the NetworkGameInfo from the packet. */
 
	DeserializeNetworkGameInfo(p, &item->info);
src/network/network_client.h
Show inline comments
 
@@ -12,13 +12,13 @@
 

	
 
#include "network_internal.h"
 

	
 
/** Class for handling the client side of the game connection. */
 
class ClientNetworkGameSocketHandler : public ZeroedMemoryAllocator, public NetworkGameSocketHandler {
 
private:
 
	NetworkAddress address;        ///< Address we are connected to.
 
	std::string connection_string; ///< Address we are connected to.
 
	struct PacketReader *savegame; ///< Packet reader for reading the savegame.
 
	byte token;                    ///< The token we need to send back to the server to prove we're the right client.
 

	
 
	/** Status of the connection with the server. */
 
	enum ServerStatus {
 
		STATUS_INACTIVE,      ///< The client is not connected nor active.
 
@@ -73,13 +73,13 @@ protected:
 

	
 
	static NetworkRecvStatus SendNewGRFsOk();
 
	static NetworkRecvStatus SendGetMap();
 
	static NetworkRecvStatus SendMapOk();
 
	void CheckConnection();
 
public:
 
	ClientNetworkGameSocketHandler(SOCKET s, NetworkAddress address);
 
	ClientNetworkGameSocketHandler(SOCKET s, const std::string &connection_string);
 
	~ClientNetworkGameSocketHandler();
 

	
 
	NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override;
 
	void ClientError(NetworkRecvStatus res);
 

	
 
	static NetworkRecvStatus SendInformationQuery(bool request_company_info);
 
@@ -112,13 +112,13 @@ typedef ClientNetworkGameSocketHandler M
 
void NetworkClient_Connected();
 
void NetworkClientSetCompanyPassword(const char *password);
 

	
 
/** Information required to join a server. */
 
struct NetworkJoinInfo {
 
	NetworkJoinInfo() : company(COMPANY_SPECTATOR), server_password(nullptr), company_password(nullptr) {}
 
	NetworkAddress address;       ///< The address of the server to join.
 
	std::string connection_string; ///< The address of the server to join.
 
	CompanyID company;            ///< The company to join.
 
	const char *server_password;  ///< The password of the server to join.
 
	const char *company_password; ///< The password of the company to join.
 
};
 

	
 
extern NetworkJoinInfo _network_join;
src/network/network_content.cpp
Show inline comments
 
@@ -340,14 +340,13 @@ void ClientNetworkContentSocketHandler::
 
	for (const ContentID &id : content) {
 
		p += seprintf(p, lastof, "%d\n", id);
 
	}
 

	
 
	this->http_response_index = -1;
 

	
 
	NetworkAddress address(NETWORK_CONTENT_MIRROR_HOST, NETWORK_CONTENT_MIRROR_PORT);
 
	new NetworkHTTPContentConnecter(address, this, NETWORK_CONTENT_MIRROR_URL, content_request);
 
	new NetworkHTTPContentConnecter(NETWORK_CONTENT_MIRROR_HOST, this, NETWORK_CONTENT_MIRROR_URL, content_request);
 
	/* NetworkHTTPContentConnecter takes over freeing of content_request! */
 
}
 

	
 
/**
 
 * Initiate downloading the content over the fallback protocol.
 
 * @param content The content to download.
 
@@ -741,13 +740,13 @@ ClientNetworkContentSocketHandler::~Clie
 
class NetworkContentConnecter : TCPConnecter {
 
public:
 
	/**
 
	 * Initiate the connecting.
 
	 * @param address The address of the server.
 
	 */
 
	NetworkContentConnecter(const NetworkAddress &address) : TCPConnecter(address) {}
 
	NetworkContentConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_CONTENT_SERVER_PORT) {}
 

	
 
	void OnFailure() override
 
	{
 
		_network_content_client.isConnecting = false;
 
		_network_content_client.OnConnect(false);
 
	}
 
@@ -767,13 +766,13 @@ public:
 
 * Connect with the content server.
 
 */
 
void ClientNetworkContentSocketHandler::Connect()
 
{
 
	if (this->sock != INVALID_SOCKET || this->isConnecting) return;
 
	this->isConnecting = true;
 
	new NetworkContentConnecter(NetworkAddress(NETWORK_CONTENT_SERVER_HOST, NETWORK_CONTENT_SERVER_PORT, AF_UNSPEC));
 
	new NetworkContentConnecter(NETWORK_CONTENT_SERVER_HOST);
 
}
 

	
 
/**
 
 * Disconnect from the content server.
 
 */
 
void ClientNetworkContentSocketHandler::Close()
src/network/network_gamelist.cpp
Show inline comments
 
@@ -41,13 +41,13 @@ static void NetworkGameListHandleDelayed
 
{
 
	while (true) {
 
		NetworkGameList *ins_item = _network_game_delayed_insertion_list.load(std::memory_order_relaxed);
 
		while (ins_item != nullptr && !_network_game_delayed_insertion_list.compare_exchange_weak(ins_item, ins_item->next, std::memory_order_acq_rel)) {}
 
		if (ins_item == nullptr) break; // No item left.
 

	
 
		NetworkGameList *item = NetworkGameListAddItem(ins_item->address);
 
		NetworkGameList *item = NetworkGameListAddItem(ins_item->connection_string);
 

	
 
		if (item != nullptr) {
 
			if (StrEmpty(item->info.server_name)) {
 
				ClearGRFConfigList(&item->info.grfconfig);
 
				memset(&item->info, 0, sizeof(item->info));
 
				strecpy(item->info.server_name, ins_item->info.server_name, lastof(item->info.server_name));
 
@@ -64,25 +64,28 @@ static void NetworkGameListHandleDelayed
 
/**
 
 * Add a new item to the linked gamelist. If the IP and Port match
 
 * return the existing item instead of adding it again
 
 * @param address the address of the to-be added item
 
 * @return a point to the newly added or already existing item
 
 */
 
NetworkGameList *NetworkGameListAddItem(NetworkAddress address)
 
NetworkGameList *NetworkGameListAddItem(const std::string &connection_string)
 
{
 
	NetworkGameList *item, *prev_item;
 

	
 
	/* Parse the connection string to ensure the default port is there. */
 
	const std::string resolved_connection_string = ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT).GetAddressAsString(false);
 

	
 
	prev_item = nullptr;
 
	for (item = _network_game_list; item != nullptr; item = item->next) {
 
		if (item->address == address) return item;
 
		if (item->connection_string == resolved_connection_string) return item;
 
		prev_item = item;
 
	}
 

	
 
	item = CallocT<NetworkGameList>(1);
 
	item->next = nullptr;
 
	item->address = address;
 
	item->connection_string = resolved_connection_string;
 

	
 
	if (prev_item == nullptr) {
 
		_network_game_list = item;
 
	} else {
 
		prev_item->next = item;
 
	}
 
@@ -138,13 +141,13 @@ void NetworkGameListRequery()
 
	for (NetworkGameList *item = _network_game_list; item != nullptr; item = item->next) {
 
		item->retries++;
 
		if (item->retries < REFRESH_GAMEINFO_X_REQUERIES && (item->online || item->retries >= MAX_GAME_LIST_REQUERY_COUNT)) continue;
 

	
 
		/* item gets mostly zeroed by NetworkUDPQueryServer */
 
		uint8 retries = item->retries;
 
		NetworkUDPQueryServer(item->address);
 
		NetworkUDPQueryServer(item->connection_string);
 
		item->retries = (retries >= REFRESH_GAMEINFO_X_REQUERIES) ? 0 : retries;
 
	}
 
}
 

	
 
/**
 
 * Rebuild the GRFConfig's of the servers in the game list as we did
src/network/network_gamelist.h
Show inline comments
 
@@ -14,22 +14,22 @@
 
#include "core/game_info.h"
 
#include "network_type.h"
 

	
 
/** Structure with information shown in the game list (GUI) */
 
struct NetworkGameList {
 
	NetworkGameInfo info;   ///< The game information of this server
 
	NetworkAddress address; ///< The connection info of the game server
 
	std::string connection_string; ///< Address of the server
 
	bool online;            ///< False if the server did not respond (default status)
 
	bool manually;          ///< True if the server was added manually
 
	uint8 retries;          ///< Number of retries (to stop requerying)
 
	NetworkGameList *next;  ///< Next pointer to make a linked game list
 
};
 

	
 
/** Game list of this client */
 
extern NetworkGameList *_network_game_list;
 

	
 
void NetworkGameListAddItemDelayed(NetworkGameList *item);
 
NetworkGameList *NetworkGameListAddItem(NetworkAddress address);
 
NetworkGameList *NetworkGameListAddItem(const std::string &connection_string);
 
void NetworkGameListRemoveItem(NetworkGameList *remove);
 
void NetworkGameListRequery();
 

	
 
#endif /* NETWORK_GAMELIST_H */
src/network/network_gui.cpp
Show inline comments
 
@@ -269,13 +269,15 @@ protected:
 
	}
 

	
 
	/** Sort servers by name. */
 
	static bool NGameNameSorter(NetworkGameList * const &a, NetworkGameList * const &b)
 
	{
 
		int r = strnatcmp(a->info.server_name, b->info.server_name, true); // Sort by name (natural sorting).
 
		return r == 0 ? a->address.CompareTo(b->address) < 0: r < 0;
 
		if (r == 0) r = a->connection_string.compare(b->connection_string);
 

	
 
		return r < 0;
 
	}
 

	
 
	/**
 
	 * Sort servers by the amount of clients online on a
 
	 * server. If the two servers have the same amount, the one with the
 
	 * higher maximum is preferred.
 
@@ -643,14 +645,13 @@ public:
 
			y += FONT_HEIGHT_NORMAL;
 

	
 
			SetDParamStr(0, sel->info.server_revision);
 
			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_VERSION); // server version
 
			y += FONT_HEIGHT_NORMAL;
 

	
 
			std::string address = sel->address.GetAddressAsString();
 
			SetDParamStr(0, address.c_str());
 
			SetDParamStr(0, sel->connection_string.c_str());
 
			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_ADDRESS); // server address
 
			y += FONT_HEIGHT_NORMAL;
 

	
 
			SetDParam(0, sel->info.start_date);
 
			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_START_DATE); // start date
 
			y += FONT_HEIGHT_NORMAL;
 
@@ -748,13 +749,13 @@ public:
 
				if (this->server != nullptr) {
 
					ShowNetworkLobbyWindow(this->server);
 
				}
 
				break;
 

	
 
			case WID_NG_REFRESH: // Refresh
 
				if (this->server != nullptr) NetworkTCPQueryServer(this->server->address);
 
				if (this->server != nullptr) NetworkTCPQueryServer(this->server->connection_string);
 
				break;
 

	
 
			case WID_NG_NEWGRF: // NewGRF Settings
 
				if (this->server != nullptr) ShowNewGRFSettings(false, false, false, &this->server->info.grfconfig);
 
				break;
 

	
 
@@ -1468,28 +1469,28 @@ struct NetworkLobbyWindow : public Windo
 
				if (click_count > 1 && !this->IsWidgetDisabled(WID_NL_JOIN)) this->OnClick(pt, WID_NL_JOIN, 1);
 
				break;
 
			}
 

	
 
			case WID_NL_JOIN:     // Join company
 
				/* Button can be clicked only when it is enabled. */
 
				NetworkClientConnectGame(this->server->address, this->company);
 
				NetworkClientConnectGame(this->server->connection_string, this->company);
 
				break;
 

	
 
			case WID_NL_NEW:      // New company
 
				NetworkClientConnectGame(this->server->address, COMPANY_NEW_COMPANY);
 
				NetworkClientConnectGame(this->server->connection_string, COMPANY_NEW_COMPANY);
 
				break;
 

	
 
			case WID_NL_SPECTATE: // Spectate game
 
				NetworkClientConnectGame(this->server->address, COMPANY_SPECTATOR);
 
				NetworkClientConnectGame(this->server->connection_string, COMPANY_SPECTATOR);
 
				break;
 

	
 
			case WID_NL_REFRESH:  // Refresh
 
				/* Clear the information so removed companies don't remain */
 
				for (auto &company : this->company_info) company = {};
 

	
 
				NetworkTCPQueryServer(this->server->address, true);
 
				NetworkTCPQueryServer(this->server->connection_string, true);
 
				break;
 
		}
 
	}
 

	
 
	void OnResize() override
 
	{
 
@@ -1551,15 +1552,15 @@ static void ShowNetworkLobbyWindow(Netwo
 
{
 
	if (!NetworkValidateClientName()) return;
 

	
 
	DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START);
 
	DeleteWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME);
 

	
 
	strecpy(_settings_client.network.last_joined, ngl->address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined));
 

	
 
	NetworkTCPQueryServer(ngl->address, true);
 
	strecpy(_settings_client.network.last_joined, ngl->connection_string.c_str(), lastof(_settings_client.network.last_joined));
 

	
 
	NetworkTCPQueryServer(ngl->connection_string, true);
 

	
 
	new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
 
}
 

	
 
/**
 
 * Get the company information of a given company to fill for the lobby.
src/network/network_internal.h
Show inline comments
 
@@ -84,13 +84,13 @@ extern uint32 _network_join_bytes;
 
extern uint32 _network_join_bytes_total;
 

	
 
extern uint8 _network_reconnect;
 

	
 
extern CompanyMask _network_company_passworded;
 

	
 
void NetworkTCPQueryServer(NetworkAddress address, bool request_company_info = false);
 
void NetworkTCPQueryServer(const std::string &connection_string, bool request_company_info = false);
 

	
 
void GetBindAddresses(NetworkAddressList *addresses, uint16 port);
 
struct NetworkGameList *NetworkAddServer(const std::string &connection_string);
 
void NetworkRebuildHostList();
 
void UpdateNetworkGameWindow();
 

	
 
@@ -116,11 +116,9 @@ void ShowNetworkError(StringID error_str
 
void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const char *name, const char *str = "", int64 data = 0);
 
uint NetworkCalculateLag(const NetworkClientSocket *cs);
 
StringID GetNetworkErrorMsg(NetworkErrorCode err);
 
bool NetworkFindName(char *new_name, const char *last);
 
const char *GenerateCompanyPasswordHash(const char *password, const char *password_server_id, uint32 password_game_seed);
 

	
 
bool NetworkClientConnectGame(NetworkAddress &address, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr);
 
NetworkAddress ParseConnectionString(const std::string &connection_string, int default_port);
 
NetworkAddress ParseGameConnectionString(CompanyID *company, const std::string &connection_string, int default_port);
 

	
 
#endif /* NETWORK_INTERNAL_H */
src/network/network_udp.cpp
Show inline comments
 
@@ -80,41 +80,42 @@ struct UDPSocket {
 
static UDPSocket _udp_client("Client"); ///< udp client socket
 
static UDPSocket _udp_server("Server"); ///< udp server socket
 
static UDPSocket _udp_master("Master"); ///< udp master socket
 

	
 
/**
 
 * Helper function doing the actual work for querying the server.
 
 * @param address The address of the server.
 
 * @param connection_string 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 DoNetworkUDPQueryServer(NetworkAddress &address, bool needs_mutex, bool manually)
 
static void DoNetworkUDPQueryServer(const std::string &connection_string, 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));
 
	item->address = address;
 
	strecpy(item->info.server_name, connection_string.c_str(), lastof(item->info.server_name));
 
	item->connection_string = connection_string;
 
	item->manually = manually;
 
	NetworkGameListAddItemDelayed(item);
 

	
 
	std::unique_lock<std::mutex> lock(_udp_client.mutex, std::defer_lock);
 
	if (needs_mutex) lock.lock();
 
	/* Init the packet */
 
	NetworkAddress address = NetworkAddress(ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT));
 
	Packet p(PACKET_UDP_CLIENT_FIND_SERVER);
 
	if (_udp_client.socket != nullptr) _udp_client.socket->SendPacket(&p, &address);
 
}
 

	
 
/**
 
 * Query a specific server.
 
 * @param address The address of the server.
 
 * @param connection_string The address of the server.
 
 * @param manually Whether the address was entered manually.
 
 */
 
void NetworkUDPQueryServer(NetworkAddress address, bool manually)
 
void NetworkUDPQueryServer(const std::string &connection_string, bool manually)
 
{
 
	if (address.IsResolved() || !StartNewThread(nullptr, "ottd:udp-query", &DoNetworkUDPQueryServer, std::move(address), true, std::move(manually))) {
 
		DoNetworkUDPQueryServer(address, true, manually);
 
	if (!StartNewThread(nullptr, "ottd:udp-query", &DoNetworkUDPQueryServer, std::move(connection_string), true, std::move(manually))) {
 
		DoNetworkUDPQueryServer(connection_string, true, manually);
 
	}
 
}
 

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

	
 
/** Helper class for connecting to the master server. */
 
@@ -315,13 +316,13 @@ void ClientNetworkUDPSocketHandler::Rece
 
	/* Just a fail-safe.. should never happen */
 
	if (_network_udp_server) return;
 

	
 
	DEBUG(net, 4, "[udp] server response from %s", client_addr->GetAddressAsString().c_str());
 

	
 
	/* Find next item */
 
	item = NetworkGameListAddItem(*client_addr);
 
	item = NetworkGameListAddItem(client_addr->GetAddressAsString(false));
 

	
 
	/* Clear any existing GRFConfig chain. */
 
	ClearGRFConfigList(&item->info.grfconfig);
 
	/* Retrieve the NetworkGameInfo from the packet. */
 
	DeserializeNetworkGameInfo(p, &item->info);
 
	/* Check for compatability with the client. */
 
@@ -354,13 +355,14 @@ void ClientNetworkUDPSocketHandler::Rece
 

	
 
			packet.Send_uint8(in_request_count);
 
			for (i = 0; i < in_request_count; i++) {
 
				SerializeGRFIdentifier(&packet, &in_request[i]->ident);
 
			}
 

	
 
			this->SendPacket(&packet, &item->address);
 
			NetworkAddress address = NetworkAddress(ParseConnectionString(item->connection_string, NETWORK_DEFAULT_PORT));
 
			this->SendPacket(&packet, &address);
 
		}
 
	}
 

	
 
	if (client_addr->GetAddress()->ss_family == AF_INET6) {
 
		strecat(item->info.server_name, " (IPv6)", lastof(item->info.server_name));
 
	}
 
@@ -395,13 +397,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;
 

	
 
			DoNetworkUDPQueryServer(addr, false, false);
 
			DoNetworkUDPQueryServer(addr.GetAddressAsString(false), 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)
src/network/network_udp.h
Show inline comments
 
@@ -12,13 +12,13 @@
 

	
 
#include "core/address.h"
 

	
 
void NetworkUDPInitialize();
 
void NetworkUDPSearchGame();
 
void NetworkUDPQueryMasterServer();
 
void NetworkUDPQueryServer(NetworkAddress address, bool manually = false);
 
void NetworkUDPQueryServer(const std::string &connection_string, bool manually = false);
 
void NetworkUDPAdvertise();
 
void NetworkUDPRemoveAdvertise(bool blocking);
 
void NetworkUDPClose();
 
void NetworkUDPServerListen();
 
void NetworkBackgroundUDPLoop();
 

	
0 comments (0 inline, 0 general)