1
0
Fork 0

(svn r15157) -Codechange: wrap the hostname/ip and port into a single structure so we can pass either one of them and not convert an ip to a string and then back again.

release/0.7
rubidium 2009-01-20 01:32:06 +00:00
parent 6e1af6a051
commit 5f3772a42c
10 changed files with 155 additions and 56 deletions

View File

@ -692,7 +692,7 @@ DEF_CONSOLE_CMD(ConNetworkConnect)
IConsolePrintF(CC_DEFAULT, " port: %s", port); IConsolePrintF(CC_DEFAULT, " port: %s", port);
} }
NetworkClientConnectGame(ip, rport); NetworkClientConnectGame(NetworkAddress(ip, rport));
return true; return true;
} }

View File

@ -451,12 +451,12 @@ void NetworkCloseClient(NetworkClientSocket *cs)
} }
// A client wants to connect to a server // A client wants to connect to a server
static bool NetworkConnect(const char *hostname, int port) static bool NetworkConnect(NetworkAddress address)
{ {
SOCKET s; SOCKET s;
struct sockaddr_in sin; struct sockaddr_in sin;
DEBUG(net, 1, "Connecting to %s %d", hostname, port); DEBUG(net, 1, "Connecting to %s %d", address.GetHostname(), address.GetPort());
s = socket(AF_INET, SOCK_STREAM, 0); s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) { if (s == INVALID_SOCKET) {
@ -467,8 +467,8 @@ static bool NetworkConnect(const char *hostname, int port)
if (!SetNoDelay(s)) DEBUG(net, 1, "Setting TCP_NODELAY failed"); if (!SetNoDelay(s)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_addr.s_addr = NetworkResolveHost(hostname); sin.sin_addr.s_addr = address.GetIP();
sin.sin_port = htons(port); sin.sin_port = htons(address.GetIP());
_network_last_host_ip = sin.sin_addr.s_addr; _network_last_host_ip = sin.sin_addr.s_addr;
/* We failed to connect for which reason what so ever */ /* We failed to connect for which reason what so ever */
@ -664,7 +664,7 @@ static void NetworkInitialize()
// Query a server to fetch his game-info // Query a server to fetch his game-info
// If game_info is true, only the gameinfo is fetched, // If game_info is true, only the gameinfo is fetched,
// else only the client_info is fetched // else only the client_info is fetched
void NetworkTCPQueryServer(const char *host, unsigned short port) void NetworkTCPQueryServer(NetworkAddress address)
{ {
if (!_network_available) return; if (!_network_available) return;
@ -672,7 +672,7 @@ void NetworkTCPQueryServer(const char *host, unsigned short port)
NetworkInitialize(); NetworkInitialize();
// Try to connect // Try to connect
_networking = NetworkConnect(host, port); _networking = NetworkConnect(address);
// We are connected // We are connected
if (_networking) { if (_networking) {
@ -701,7 +701,7 @@ void NetworkAddServer(const char *b)
ParseConnectionString(&company, &port, host); ParseConnectionString(&company, &port, host);
if (port != NULL) rport = atoi(port); if (port != NULL) rport = atoi(port);
NetworkUDPQueryServer(host, rport, true); NetworkUDPQueryServer(NetworkAddress(host, rport), true);
} }
} }
@ -727,20 +727,20 @@ void NetworkRebuildHostList()
} }
// Used by clients, to connect to a server // Used by clients, to connect to a server
void NetworkClientConnectGame(const char *host, uint16 port) void NetworkClientConnectGame(NetworkAddress address)
{ {
if (!_network_available) return; if (!_network_available) return;
if (port == 0) return; if (address.GetPort() == 0) return;
strecpy(_settings_client.network.last_host, host, lastof(_settings_client.network.last_host)); strecpy(_settings_client.network.last_host, address.GetHostname(), lastof(_settings_client.network.last_host));
_settings_client.network.last_port = port; _settings_client.network.last_port = address.GetPort();
NetworkDisconnect(); NetworkDisconnect();
NetworkInitialize(); NetworkInitialize();
// Try to connect // Try to connect
_networking = NetworkConnect(host, port); _networking = NetworkConnect(address);
// We are connected // We are connected
if (_networking) { if (_networking) {
@ -1073,13 +1073,13 @@ static void NetworkGenerateUniqueId()
snprintf(_settings_client.network.network_id, sizeof(_settings_client.network.network_id), "%s", hex_output); snprintf(_settings_client.network.network_id, sizeof(_settings_client.network.network_id), "%s", hex_output);
} }
void NetworkStartDebugLog(const char *hostname, uint16 port) void NetworkStartDebugLog(NetworkAddress address)
{ {
extern SOCKET _debug_socket; // Comes from debug.c extern SOCKET _debug_socket; // Comes from debug.c
SOCKET s; SOCKET s;
struct sockaddr_in sin; struct sockaddr_in sin;
DEBUG(net, 0, "Redirecting DEBUG() to %s:%d", hostname, port); DEBUG(net, 0, "Redirecting DEBUG() to %s:%d", address.GetHostname(), address.GetPort());
s = socket(AF_INET, SOCK_STREAM, 0); s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) { if (s == INVALID_SOCKET) {
@ -1090,11 +1090,11 @@ void NetworkStartDebugLog(const char *hostname, uint16 port)
if (!SetNoDelay(s)) DEBUG(net, 1, "Setting TCP_NODELAY failed"); if (!SetNoDelay(s)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_addr.s_addr = NetworkResolveHost(hostname); sin.sin_addr.s_addr = address.GetIP();
sin.sin_port = htons(port); sin.sin_port = htons(address.GetPort());
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) != 0) { if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
DEBUG(net, 0, "Failed to redirection DEBUG() to %s:%d", hostname, port); DEBUG(net, 0, "Failed to redirection DEBUG() to %s:%d", address.GetHostname(), address.GetIP());
return; return;
} }
@ -1154,6 +1154,24 @@ bool IsNetworkCompatibleVersion(const char *other)
return strncmp(_openttd_revision, other, NETWORK_REVISION_LENGTH - 1) == 0; return strncmp(_openttd_revision, other, NETWORK_REVISION_LENGTH - 1) == 0;
} }
const char *NetworkAddress::GetHostname() const
{
if (this->hostname != NULL) return this->hostname;
in_addr addr;
addr.s_addr = this->ip;
return inet_ntoa(addr);
}
uint32 NetworkAddress::GetIP()
{
if (!this->resolved) {
this->ip = NetworkResolveHost(this->hostname);
this->resolved = true;
}
return this->ip;
}
#endif /* ENABLE_NETWORK */ #endif /* ENABLE_NETWORK */
/* NOTE: this variable needs to be always available */ /* NOTE: this variable needs to be always available */

View File

@ -32,11 +32,11 @@ void NetworkGameLoop();
void NetworkUDPGameLoop(); void NetworkUDPGameLoop();
void NetworkUDPCloseAll(); void NetworkUDPCloseAll();
void ParseConnectionString(const char **company, const char **port, char *connection_string); void ParseConnectionString(const char **company, const char **port, char *connection_string);
void NetworkStartDebugLog(const char *hostname, uint16 port); void NetworkStartDebugLog(NetworkAddress address);
void NetworkPopulateCompanyStats(NetworkCompanyStats *stats); void NetworkPopulateCompanyStats(NetworkCompanyStats *stats);
void NetworkUpdateClientInfo(ClientID client_id); void NetworkUpdateClientInfo(ClientID client_id);
void NetworkClientConnectGame(const char *host, uint16 port); void NetworkClientConnectGame(NetworkAddress address);
void NetworkClientSendRcon(const char *password, const char *command); void NetworkClientSendRcon(const char *password, const char *command);
void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0); void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0);
void NetworkClientSetPassword(const char *password); void NetworkClientSetPassword(const char *password);

View File

@ -96,18 +96,13 @@ void NetworkGameListRequery()
if (++requery_cnt < REQUERY_EVERY_X_GAMELOOPS) return; if (++requery_cnt < REQUERY_EVERY_X_GAMELOOPS) return;
requery_cnt = 0; requery_cnt = 0;
struct in_addr ip; for (NetworkGameList *item = _network_game_list; item != NULL; item = item->next) {
NetworkGameList *item;
for (item = _network_game_list; item != NULL; item = item->next) {
item->retries++; item->retries++;
if (item->retries < REFRESH_GAMEINFO_X_REQUERIES && (item->online || item->retries >= MAX_GAME_LIST_REQUERY_COUNT)) continue; if (item->retries < REFRESH_GAMEINFO_X_REQUERIES && (item->online || item->retries >= MAX_GAME_LIST_REQUERY_COUNT)) continue;
ip.s_addr = item->ip;
/* item gets mostly zeroed by NetworkUDPQueryServer */ /* item gets mostly zeroed by NetworkUDPQueryServer */
uint8 retries = item->retries; uint8 retries = item->retries;
NetworkUDPQueryServer(inet_ntoa(ip), item->port); NetworkUDPQueryServer(NetworkAddress(item->ip, item->port));
item->retries = (retries >= REFRESH_GAMEINFO_X_REQUERIES) ? 0 : retries; item->retries = (retries >= REFRESH_GAMEINFO_X_REQUERIES) ? 0 : retries;
} }
} }

View File

@ -558,7 +558,7 @@ public:
break; break;
case NGWW_REFRESH: // Refresh case NGWW_REFRESH: // Refresh
if (this->server != NULL) NetworkUDPQueryServer(this->server->info.hostname, this->server->port); if (this->server != NULL) NetworkUDPQueryServer(NetworkAddress(this->server->info.hostname, this->server->port));
break; break;
case NGWW_NEWGRF: // NewGRF Settings case NGWW_NEWGRF: // NewGRF Settings
@ -1313,22 +1313,22 @@ struct NetworkLobbyWindow : public Window {
case NLWW_JOIN: // Join company case NLWW_JOIN: // Join company
/* Button can be clicked only when it is enabled */ /* Button can be clicked only when it is enabled */
_network_playas = this->company; _network_playas = this->company;
NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port); NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
break; break;
case NLWW_NEW: // New company case NLWW_NEW: // New company
_network_playas = COMPANY_NEW_COMPANY; _network_playas = COMPANY_NEW_COMPANY;
NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port); NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
break; break;
case NLWW_SPECTATE: // Spectate game case NLWW_SPECTATE: // Spectate game
_network_playas = COMPANY_SPECTATOR; _network_playas = COMPANY_SPECTATOR;
NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port); NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
break; break;
case NLWW_REFRESH: // Refresh case NLWW_REFRESH: // Refresh
NetworkTCPQueryServer(_settings_client.network.last_host, _settings_client.network.last_port); // company info NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // company info
NetworkUDPQueryServer(_settings_client.network.last_host, _settings_client.network.last_port); // general data NetworkUDPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // general data
/* Clear the information so removed companies don't remain */ /* Clear the information so removed companies don't remain */
memset(this->company_info, 0, sizeof(company_info)); memset(this->company_info, 0, sizeof(company_info));
break; break;
@ -1381,8 +1381,8 @@ static void ShowNetworkLobbyWindow(NetworkGameList *ngl)
{ {
DeleteWindowById(WC_NETWORK_WINDOW, 0); DeleteWindowById(WC_NETWORK_WINDOW, 0);
NetworkTCPQueryServer(_settings_client.network.last_host, _settings_client.network.last_port); // company info NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // company info
NetworkUDPQueryServer(_settings_client.network.last_host, _settings_client.network.last_port); // general data NetworkUDPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // general data
new NetworkLobbyWindow(&_network_lobby_window_desc, ngl); new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
} }

View File

@ -122,7 +122,7 @@ extern uint16 _network_udp_broadcast;
extern uint8 _network_advertise_retries; extern uint8 _network_advertise_retries;
void NetworkTCPQueryServer(const char *host, unsigned short port); void NetworkTCPQueryServer(NetworkAddress address);
void NetworkAddServer(const char *b); void NetworkAddServer(const char *b);
void NetworkRebuildHostList(); void NetworkRebuildHostList();

View File

@ -11,6 +11,7 @@
#include "../economy_type.h" #include "../economy_type.h"
#include "core/config.h" #include "core/config.h"
#include "core/game.h" #include "core/game.h"
#include "core/os_abstraction.h"
enum { enum {
/** How many clients can we have */ /** How many clients can we have */
@ -114,5 +115,95 @@ enum NetworkErrorCode {
NETWORK_ERROR_FULL, NETWORK_ERROR_FULL,
}; };
/**
* Wrapper for (un)resolved network addresses; there's no reason to transform
* a numeric IP to a string and then back again to pass it to functions. It
* furthermore allows easier delaying of the hostname lookup.
*/
class NetworkAddress {
private:
bool resolved; ///< Has the IP address been resolved
char *hostname; ///< The hostname, NULL if there isn't one
uint32 ip; ///< The resolved IP address
uint16 port; ///< The port associated with the address
public:
/**
* Create a network address based on a resolved IP and port
* @param ip the resolved ip
* @param port the port
*/
NetworkAddress(in_addr_t ip, uint16 port) :
resolved(true),
hostname(NULL),
ip(ip),
port(port)
{
}
/**
* Create a network address based on a unresolved host and port
* @param ip the unresolved hostname
* @param port the port
*/
NetworkAddress(const char *hostname, uint16 port) :
resolved(false),
hostname(strdup(hostname)),
ip(0),
port(port)
{
}
/**
* Make a clone of another address
* @param address the address to clone
*/
NetworkAddress(const NetworkAddress &address) :
resolved(address.resolved),
hostname(address.hostname == NULL ? NULL : strdup(address.hostname)),
ip(address.ip),
port(address.port)
{
}
/** Clean up our mess */
~NetworkAddress()
{
free(hostname);
}
/**
* Get the hostname; in case it wasn't given the
* IPv4 dotted representation is given.
* @return the hostname
*/
const char *GetHostname() const;
/**
* Get the IP address. If the IP has not been resolved yet this will resolve
* it possibly blocking this function for a while
* @return the IP address
*/
uint32 GetIP();
/**
* Get the port
* @return the port
*/
uint16 GetPort() const
{
return this->port;
}
/**
* Check whether the IP address has been resolved already
* @return true iff the port has been resolved
*/
bool IsResolved() const
{
return this->resolved;
}
};
#endif /* ENABLE_NETWORK */ #endif /* ENABLE_NETWORK */
#endif /* NETWORK_TYPE_H */ #endif /* NETWORK_TYPE_H */

View File

@ -276,27 +276,22 @@ DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_RESPONSE)
DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_MASTER_RESPONSE_LIST) DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_MASTER_RESPONSE_LIST)
{ {
int i;
struct in_addr ip;
uint16 port;
uint8 ver;
/* packet begins with the protocol version (uint8) /* packet begins with the protocol version (uint8)
* then an uint16 which indicates how many * then an uint16 which indicates how many
* ip:port pairs are in this packet, after that * ip:port pairs are in this packet, after that
* an uint32 (ip) and an uint16 (port) for each pair * an uint32 (ip) and an uint16 (port) for each pair
*/ */
ver = p->Recv_uint8(); uint8 ver = p->Recv_uint8();
if (ver == 1) { if (ver == 1) {
for (i = p->Recv_uint16(); i != 0 ; i--) { for (int i = p->Recv_uint16(); i != 0 ; i--) {
ip.s_addr = TO_LE32(p->Recv_uint32()); uint32 ip = TO_LE32(p->Recv_uint32());
port = p->Recv_uint16(); uint16 port = p->Recv_uint16();
/* Somehow we reached the end of the packet */ /* Somehow we reached the end of the packet */
if (this->HasClientQuit()) return; if (this->HasClientQuit()) return;
NetworkUDPQueryServer(inet_ntoa(ip), port); NetworkUDPQueryServer(NetworkAddress(ip, port));
} }
} }
} }
@ -425,7 +420,7 @@ void NetworkUDPSearchGame()
_network_udp_broadcast = 300; // Stay searching for 300 ticks _network_udp_broadcast = 300; // Stay searching for 300 ticks
} }
void NetworkUDPQueryServer(const char *host, unsigned short port, bool manually) void NetworkUDPQueryServer(NetworkAddress address, bool manually)
{ {
struct sockaddr_in out_addr; struct sockaddr_in out_addr;
NetworkGameList *item; NetworkGameList *item;
@ -436,17 +431,17 @@ void NetworkUDPQueryServer(const char *host, unsigned short port, bool manually)
} }
out_addr.sin_family = AF_INET; out_addr.sin_family = AF_INET;
out_addr.sin_port = htons(port); out_addr.sin_port = htons(address.GetPort());
out_addr.sin_addr.s_addr = NetworkResolveHost(host); out_addr.sin_addr.s_addr = address.GetIP();
// Clear item in gamelist // Clear item in gamelist
item = NetworkGameListAddItem(inet_addr(inet_ntoa(out_addr.sin_addr)), ntohs(out_addr.sin_port)); item = NetworkGameListAddItem(address.GetIP(), address.GetPort());
if (item == NULL) return; if (item == NULL) return;
if (StrEmpty(item->info.server_name)) { if (StrEmpty(item->info.server_name)) {
memset(&item->info, 0, sizeof(item->info)); memset(&item->info, 0, sizeof(item->info));
strecpy(item->info.server_name, host, lastof(item->info.server_name)); strecpy(item->info.server_name, address.GetHostname(), lastof(item->info.server_name));
strecpy(item->info.hostname, host, lastof(item->info.hostname)); strecpy(item->info.hostname, address.GetHostname(), lastof(item->info.hostname));
item->online = false; item->online = false;
} }
item->manually = manually; item->manually = manually;

View File

@ -10,7 +10,7 @@
void NetworkUDPInitialize(); void NetworkUDPInitialize();
void NetworkUDPSearchGame(); void NetworkUDPSearchGame();
void NetworkUDPQueryMasterServer(); void NetworkUDPQueryMasterServer();
void NetworkUDPQueryServer(const char *host, unsigned short port, bool manually = false); void NetworkUDPQueryServer(NetworkAddress address, bool manually = false);
void NetworkUDPAdvertise(); void NetworkUDPAdvertise();
void NetworkUDPRemoveAdvertise(); void NetworkUDPRemoveAdvertise();
void NetworkUDPShutdown(); void NetworkUDPShutdown();

View File

@ -681,7 +681,7 @@ int ttd_main(int argc, char *argv[])
ParseConnectionString(&not_used, &port, debuglog_conn); ParseConnectionString(&not_used, &port, debuglog_conn);
if (port != NULL) rport = atoi(port); if (port != NULL) rport = atoi(port);
NetworkStartDebugLog(debuglog_conn, rport); NetworkStartDebugLog(NetworkAddress(debuglog_conn, rport));
} }
#endif /* ENABLE_NETWORK */ #endif /* ENABLE_NETWORK */
@ -728,7 +728,7 @@ int ttd_main(int argc, char *argv[])
LoadIntroGame(); LoadIntroGame();
_switch_mode = SM_NONE; _switch_mode = SM_NONE;
NetworkClientConnectGame(network_conn, rport); NetworkClientConnectGame(NetworkAddress(network_conn, rport));
} }
} }
#endif /* ENABLE_NETWORK */ #endif /* ENABLE_NETWORK */
@ -1219,7 +1219,7 @@ void GameLoop()
if (_network_reconnect > 0 && --_network_reconnect == 0) { if (_network_reconnect > 0 && --_network_reconnect == 0) {
/* This means that we want to reconnect to the last host /* This means that we want to reconnect to the last host
* We do this here, because it means that the network is really closed */ * We do this here, because it means that the network is really closed */
NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port); NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
} }
/* Singleplayer */ /* Singleplayer */
StateGameLoop(); StateGameLoop();