(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.

This commit is contained in:
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);
}
NetworkClientConnectGame(ip, rport);
NetworkClientConnectGame(NetworkAddress(ip, rport));
return true;
}

View File

@ -451,12 +451,12 @@ void NetworkCloseClient(NetworkClientSocket *cs)
}
// A client wants to connect to a server
static bool NetworkConnect(const char *hostname, int port)
static bool NetworkConnect(NetworkAddress address)
{
SOCKET s;
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);
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");
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = NetworkResolveHost(hostname);
sin.sin_port = htons(port);
sin.sin_addr.s_addr = address.GetIP();
sin.sin_port = htons(address.GetIP());
_network_last_host_ip = sin.sin_addr.s_addr;
/* 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
// If game_info is true, only the gameinfo 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;
@ -672,7 +672,7 @@ void NetworkTCPQueryServer(const char *host, unsigned short port)
NetworkInitialize();
// Try to connect
_networking = NetworkConnect(host, port);
_networking = NetworkConnect(address);
// We are connected
if (_networking) {
@ -701,7 +701,7 @@ void NetworkAddServer(const char *b)
ParseConnectionString(&company, &port, host);
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
void NetworkClientConnectGame(const char *host, uint16 port)
void NetworkClientConnectGame(NetworkAddress address)
{
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));
_settings_client.network.last_port = port;
strecpy(_settings_client.network.last_host, address.GetHostname(), lastof(_settings_client.network.last_host));
_settings_client.network.last_port = address.GetPort();
NetworkDisconnect();
NetworkInitialize();
// Try to connect
_networking = NetworkConnect(host, port);
_networking = NetworkConnect(address);
// We are connected
if (_networking) {
@ -1073,13 +1073,13 @@ static void NetworkGenerateUniqueId()
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
SOCKET s;
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);
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");
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = NetworkResolveHost(hostname);
sin.sin_port = htons(port);
sin.sin_addr.s_addr = address.GetIP();
sin.sin_port = htons(address.GetPort());
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;
}
@ -1154,6 +1154,24 @@ bool IsNetworkCompatibleVersion(const char *other)
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 */
/* NOTE: this variable needs to be always available */

View File

@ -32,11 +32,11 @@ void NetworkGameLoop();
void NetworkUDPGameLoop();
void NetworkUDPCloseAll();
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 NetworkUpdateClientInfo(ClientID client_id);
void NetworkClientConnectGame(const char *host, uint16 port);
void NetworkClientConnectGame(NetworkAddress address);
void NetworkClientSendRcon(const char *password, const char *command);
void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg, int64 data = 0);
void NetworkClientSetPassword(const char *password);

View File

@ -96,18 +96,13 @@ void NetworkGameListRequery()
if (++requery_cnt < REQUERY_EVERY_X_GAMELOOPS) return;
requery_cnt = 0;
struct in_addr ip;
NetworkGameList *item;
for (item = _network_game_list; item != NULL; item = item->next) {
for (NetworkGameList *item = _network_game_list; item != NULL; item = item->next) {
item->retries++;
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 */
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;
}
}

View File

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

View File

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

View File

@ -11,6 +11,7 @@
#include "../economy_type.h"
#include "core/config.h"
#include "core/game.h"
#include "core/os_abstraction.h"
enum {
/** How many clients can we have */
@ -114,5 +115,95 @@ enum NetworkErrorCode {
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 /* 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)
{
int i;
struct in_addr ip;
uint16 port;
uint8 ver;
/* packet begins with the protocol version (uint8)
* then an uint16 which indicates how many
* ip:port pairs are in this packet, after that
* an uint32 (ip) and an uint16 (port) for each pair
*/
ver = p->Recv_uint8();
uint8 ver = p->Recv_uint8();
if (ver == 1) {
for (i = p->Recv_uint16(); i != 0 ; i--) {
ip.s_addr = TO_LE32(p->Recv_uint32());
port = p->Recv_uint16();
for (int i = p->Recv_uint16(); i != 0 ; i--) {
uint32 ip = TO_LE32(p->Recv_uint32());
uint16 port = p->Recv_uint16();
/* Somehow we reached the end of the packet */
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
}
void NetworkUDPQueryServer(const char *host, unsigned short port, bool manually)
void NetworkUDPQueryServer(NetworkAddress address, bool manually)
{
struct sockaddr_in out_addr;
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_port = htons(port);
out_addr.sin_addr.s_addr = NetworkResolveHost(host);
out_addr.sin_port = htons(address.GetPort());
out_addr.sin_addr.s_addr = address.GetIP();
// 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 (StrEmpty(item->info.server_name)) {
memset(&item->info, 0, sizeof(item->info));
strecpy(item->info.server_name, host, lastof(item->info.server_name));
strecpy(item->info.hostname, host, lastof(item->info.hostname));
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;
}
item->manually = manually;

View File

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

View File

@ -681,7 +681,7 @@ int ttd_main(int argc, char *argv[])
ParseConnectionString(&not_used, &port, debuglog_conn);
if (port != NULL) rport = atoi(port);
NetworkStartDebugLog(debuglog_conn, rport);
NetworkStartDebugLog(NetworkAddress(debuglog_conn, rport));
}
#endif /* ENABLE_NETWORK */
@ -728,7 +728,7 @@ int ttd_main(int argc, char *argv[])
LoadIntroGame();
_switch_mode = SM_NONE;
NetworkClientConnectGame(network_conn, rport);
NetworkClientConnectGame(NetworkAddress(network_conn, rport));
}
}
#endif /* ENABLE_NETWORK */
@ -1219,7 +1219,7 @@ void GameLoop()
if (_network_reconnect > 0 && --_network_reconnect == 0) {
/* This means that we want to reconnect to the last host
* 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 */
StateGameLoop();