diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index cbb9defb04..bd7f569ae3 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -11,25 +11,37 @@ #include "host.h" #include "../../string_func.h" -const char *NetworkAddress::GetHostname() const +const char *NetworkAddress::GetHostname() { - if (this->hostname != NULL) return this->hostname; - - in_addr addr; - addr.s_addr = this->ip; - return inet_ntoa(addr); + if (this->hostname == NULL) { + this->hostname = strdup(inet_ntoa(((struct sockaddr_in *)&this->address)->sin_addr)); + } + return this->hostname; } uint32 NetworkAddress::GetIP() { + assert(this->address.ss_family == AF_INET); + if (!this->resolved) { - this->ip = NetworkResolveHost(this->hostname); + ((struct sockaddr_in *)&this->address)->sin_addr.s_addr = NetworkResolveHost(this->hostname); this->resolved = true; } - return this->ip; + return ((struct sockaddr_in *)&this->address)->sin_addr.s_addr; } -const char *NetworkAddress::GetAddressAsString() const +uint16 NetworkAddress::GetPort() const +{ + switch (this->address.ss_family) { + case AF_INET: + return ntohs(((struct sockaddr_in *)&this->address)->sin_port); + + default: + NOT_REACHED(); + } +} + +const char *NetworkAddress::GetAddressAsString() { /* 6 = for the : and 5 for the decimal port number */ static char buf[NETWORK_HOSTNAME_LENGTH + 6]; @@ -38,4 +50,10 @@ const char *NetworkAddress::GetAddressAsString() const return buf; } +const sockaddr_storage *NetworkAddress::GetAddress() +{ + if (!this->resolved) this->GetIP(); + return &this->address; +} + #endif /* ENABLE_NETWORK */ diff --git a/src/network/core/address.h b/src/network/core/address.h index 30d86b5e85..7488aad3f7 100644 --- a/src/network/core/address.h +++ b/src/network/core/address.h @@ -16,10 +16,9 @@ */ 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 + bool resolved; ///< Has the IP address been resolved + char *hostname; ///< The hostname, NULL if there isn't one + sockaddr_storage address; ///< The resolved address public: /** @@ -28,10 +27,23 @@ public: * @param port the port */ NetworkAddress(in_addr_t ip, uint16 port) : + resolved(true), + hostname(NULL) + { + memset(&this->address, 0, sizeof(this->address)); + this->address.ss_family = AF_INET; + ((struct sockaddr_in*)&this->address)->sin_addr.s_addr = ip; + ((struct sockaddr_in*)&this->address)->sin_port = htons(port); + } + + /** + * Create a network address based on a resolved IP and port + * @param address the IP address with port + */ + NetworkAddress(struct sockaddr_storage &address) : resolved(true), hostname(NULL), - ip(ip), - port(port) + address(address) { } @@ -42,10 +54,11 @@ public: */ NetworkAddress(const char *hostname = NULL, uint16 port = 0) : resolved(false), - hostname(hostname == NULL ? NULL : strdup(hostname)), - ip(0), - port(port) + hostname(hostname == NULL ? NULL : strdup(hostname)) { + memset(&this->address, 0, sizeof(this->address)); + this->address.ss_family = AF_INET; + ((struct sockaddr_in*)&this->address)->sin_port = htons(port); } /** @@ -55,8 +68,7 @@ public: NetworkAddress(const NetworkAddress &address) : resolved(address.resolved), hostname(address.hostname == NULL ? NULL : strdup(address.hostname)), - ip(address.ip), - port(address.port) + address(address.address) { } @@ -71,13 +83,19 @@ public: * IPv4 dotted representation is given. * @return the hostname */ - const char *GetHostname() const; + const char *GetHostname(); /** * Get the address as a string, e.g. 127.0.0.1:12345. * @return the address */ - const char *GetAddressAsString() const; + const char *GetAddressAsString(); + + /** + * Get the address in it's internal representation. + * @return the address + */ + const sockaddr_storage *GetAddress(); /** * Get the IP address. If the IP has not been resolved yet this will resolve @@ -90,10 +108,7 @@ public: * Get the port * @return the port */ - uint16 GetPort() const - { - return this->port; - } + uint16 GetPort() const; /** * Check whether the IP address has been resolved already diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp index 6c921ae0ab..31ae8a4460 100644 --- a/src/network/core/udp.cpp +++ b/src/network/core/udp.cpp @@ -82,14 +82,14 @@ NetworkRecvStatus NetworkUDPSocketHandler::CloseConnection() * @param p the packet to send * @param recv the receiver (target) of the packet */ -void NetworkUDPSocketHandler::SendPacket(Packet *p, const struct sockaddr_in *recv) +void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv) { int res; p->PrepareToSend(); /* Send the buffer */ - res = sendto(this->sock, (const char*)p->buffer, p->size, 0, (struct sockaddr *)recv, sizeof(*recv)); + res = sendto(this->sock, (const char*)p->buffer, p->size, 0, (struct sockaddr *)recv->GetAddress(), sizeof(*recv->GetAddress())); /* Check for any errors, but ignore it otherwise */ if (res == -1) DEBUG(net, 1, "[udp] sendto failed with: %i", GET_LAST_ERROR()); @@ -100,7 +100,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, const struct sockaddr_in *re */ void NetworkUDPSocketHandler::ReceivePackets() { - struct sockaddr_in client_addr; + struct sockaddr_storage client_addr; socklen_t client_len; int nbytes; Packet p(this); @@ -117,19 +117,18 @@ void NetworkUDPSocketHandler::ReceivePackets() /* We got some bytes for the base header of the packet. */ if (nbytes > 2) { + NetworkAddress address(client_addr); p.PrepareToRead(); /* If the size does not match the packet must be corrupted. * Otherwise it will be marked as corrupted later on. */ if (nbytes != p.size) { - DEBUG(net, 1, "received a packet with mismatching size from %s:%d", - inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); - + DEBUG(net, 1, "received a packet with mismatching size from %s", address.GetAddressAsString()); return; } /* Handle the packet */ - this->HandleUDPPacket(&p, &client_addr); + this->HandleUDPPacket(&p, &address); } } @@ -277,7 +276,7 @@ void NetworkUDPSocketHandler::Recv_NetworkGameInfo(Packet *p, NetworkGameInfo *i * @param p the received packet * @param client_addr the sender of the packet */ -void NetworkUDPSocketHandler::HandleUDPPacket(Packet *p, const struct sockaddr_in *client_addr) +void NetworkUDPSocketHandler::HandleUDPPacket(Packet *p, NetworkAddress *client_addr) { PacketUDPType type; @@ -301,9 +300,9 @@ void NetworkUDPSocketHandler::HandleUDPPacket(Packet *p, const struct sockaddr_i default: if (this->HasClientQuit()) { - DEBUG(net, 0, "[udp] received invalid packet type %d from %s:%d", type, inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); + DEBUG(net, 0, "[udp] received invalid packet type %d from %s", type, client_addr->GetAddressAsString()); } else { - DEBUG(net, 0, "[udp] received illegal packet from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); + DEBUG(net, 0, "[udp] received illegal packet from %s", client_addr->GetAddressAsString()); } break; } @@ -317,9 +316,9 @@ void NetworkUDPSocketHandler::HandleUDPPacket(Packet *p, const struct sockaddr_i */ #define DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(type) \ void NetworkUDPSocketHandler::NetworkPacketReceive_## type ##_command(\ - Packet *p, const struct sockaddr_in *client_addr) { \ - DEBUG(net, 0, "[udp] received packet type %d on wrong port from %s:%d", \ - type, inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); \ + Packet *p, NetworkAddress *client_addr) { \ + DEBUG(net, 0, "[udp] received packet type %d on wrong port from %s", \ + type, client_addr->GetAddressAsString()); \ } DEFINE_UNAVAILABLE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER); diff --git a/src/network/core/udp.h b/src/network/core/udp.h index 3696bada4b..dd019b3bbb 100644 --- a/src/network/core/udp.h +++ b/src/network/core/udp.h @@ -67,6 +67,7 @@ #ifdef ENABLE_NETWORK #include "os_abstraction.h" +#include "address.h" #include "core.h" #include "game.h" #include "packet.h" @@ -88,8 +89,8 @@ enum PacketUDPType { PACKET_UDP_END ///< Must ALWAYS be on the end of this list!! (period) }; -#define DECLARE_UDP_RECEIVE_COMMAND(type) virtual void NetworkPacketReceive_## type ##_command(Packet *p, const struct sockaddr_in *) -#define DEF_UDP_RECEIVE_COMMAND(cls, type) void cls ##NetworkUDPSocketHandler::NetworkPacketReceive_ ## type ## _command(Packet *p, const struct sockaddr_in *client_addr) +#define DECLARE_UDP_RECEIVE_COMMAND(type) virtual void NetworkPacketReceive_## type ##_command(Packet *p, NetworkAddress *client_addr) +#define DEF_UDP_RECEIVE_COMMAND(cls, type) void cls ##NetworkUDPSocketHandler::NetworkPacketReceive_ ## type ## _command(Packet *p, NetworkAddress *client_addr) /** Base socket handler for all UDP sockets */ class NetworkUDPSocketHandler : public NetworkSocketHandler { @@ -110,7 +111,7 @@ protected: DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS); DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS); - void HandleUDPPacket(Packet *p, const struct sockaddr_in *client_addr); + void HandleUDPPacket(Packet *p, NetworkAddress *client_addr); /** * Function that is called for every GRFConfig that is read when receiving @@ -127,7 +128,7 @@ public: bool Listen(uint32 host, uint16 port, bool broadcast); void Close(); - void SendPacket(Packet *p, const struct sockaddr_in *recv); + void SendPacket(Packet *p, NetworkAddress *recv); void ReceivePackets(); void Send_NetworkGameInfo(Packet *p, const NetworkGameInfo *info); diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index 6f533937e1..a509eb09ed 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -104,7 +104,7 @@ DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_FIND_SERVER) /* Let the client know that we are here */ this->SendPacket(&packet, client_addr); - DEBUG(net, 2, "[udp] queried from '%s'", inet_ntoa(client_addr->sin_addr)); + DEBUG(net, 2, "[udp] queried from '%s'", client_addr->GetHostname()); } DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_DETAIL_INFO) @@ -154,7 +154,7 @@ DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_GET_NEWGRFS) uint8 in_reply_count = 0; size_t packet_len = 0; - DEBUG(net, 6, "[udp] newgrf data request from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); + DEBUG(net, 6, "[udp] newgrf data request from %s", client_addr->GetAddressAsString()); num_grfs = p->Recv_uint8 (); if (num_grfs > NETWORK_MAX_GRF_COUNT) return; @@ -217,10 +217,10 @@ DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_RESPONSE) /* Just a fail-safe.. should never happen */ if (_network_udp_server) return; - DEBUG(net, 4, "[udp] server response from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); + DEBUG(net, 4, "[udp] server response from %s", client_addr->GetAddressAsString()); /* Find next item */ - item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port)); + item = NetworkGameListAddItem(client_addr->GetIP(), client_addr->GetPort()); this->Recv_NetworkGameInfo(p, &item->info); @@ -236,7 +236,6 @@ DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_RESPONSE) const GRFConfig *in_request[NETWORK_MAX_GRF_COUNT]; const GRFConfig *c; uint in_request_count = 0; - struct sockaddr_in out_addr; for (c = item->info.grfconfig; c != NULL; c = c->next) { if (c->status == GCS_NOT_FOUND) item->info.compatible = false; @@ -255,15 +254,13 @@ DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_RESPONSE) this->Send_GRFIdentifier(&packet, in_request[i]); } - out_addr.sin_family = AF_INET; - out_addr.sin_port = htons(item->port); - out_addr.sin_addr.s_addr = item->ip; + NetworkAddress out_addr(item->ip, item->port); this->SendPacket(&packet, &out_addr); } } if (item->info.hostname[0] == '\0') - snprintf(item->info.hostname, sizeof(item->info.hostname), "%s", inet_ntoa(client_addr->sin_addr)); + snprintf(item->info.hostname, sizeof(item->info.hostname), "%s", client_addr->GetHostname()); /* Check if we are allowed on this server based on the revision-match */ item->info.version_compatible = IsNetworkCompatibleVersion(item->info.server_revision); @@ -302,7 +299,7 @@ DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_NEWGRFS) uint8 num_grfs; uint i; - DEBUG(net, 6, "[udp] newgrf data reply from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); + DEBUG(net, 6, "[udp] newgrf data reply from %s", client_addr->GetAddressAsString()); num_grfs = p->Recv_uint8 (); if (num_grfs > NETWORK_MAX_GRF_COUNT) return; @@ -369,13 +366,9 @@ static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket) for (i = 0; _broadcast_list[i] != 0; i++) { Packet p(PACKET_UDP_CLIENT_FIND_SERVER); - struct sockaddr_in out_addr; + NetworkAddress out_addr(_broadcast_list[i], _settings_client.network.server_port); - out_addr.sin_family = AF_INET; - out_addr.sin_port = htons(_settings_client.network.server_port); - out_addr.sin_addr.s_addr = _broadcast_list[i]; - - DEBUG(net, 4, "[udp] broadcasting to %s", inet_ntoa(out_addr.sin_addr)); + DEBUG(net, 4, "[udp] broadcasting to %s", out_addr.GetHostname()); socket->SendPacket(&p, &out_addr); } @@ -385,24 +378,19 @@ static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket) /* Request the the server-list from the master server */ void NetworkUDPQueryMasterServer() { - struct sockaddr_in out_addr; - if (!_udp_client_socket->IsConnected()) { if (!_udp_client_socket->Listen(0, 0, true)) return; } Packet p(PACKET_UDP_CLIENT_GET_LIST); - - 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); + NetworkAddress out_addr(NETWORK_MASTER_SERVER_HOST, NETWORK_MASTER_SERVER_PORT); /* packet only contains protocol version */ p.Send_uint8(NETWORK_MASTER_SERVER_VERSION); _udp_client_socket->SendPacket(&p, &out_addr); - DEBUG(net, 2, "[udp] master server queried at %s:%d", inet_ntoa(out_addr.sin_addr), ntohs(out_addr.sin_port)); + DEBUG(net, 2, "[udp] master server queried at %s", out_addr.GetAddressAsString()); } /* Find all servers */ @@ -440,10 +428,7 @@ void NetworkUDPQueryServerThread(void *pntr) { NetworkUDPQueryServerInfo *info = (NetworkUDPQueryServerInfo*)pntr; - struct sockaddr_in out_addr; - out_addr.sin_family = AF_INET; - out_addr.sin_port = htons(info->GetPort()); - out_addr.sin_addr.s_addr = info->GetIP(); + NetworkAddress out_addr(info->GetIP(), info->GetPort()); /* Clear item in gamelist */ NetworkGameList *item = CallocT(1); @@ -481,10 +466,7 @@ void NetworkUDPRemoveAdvertiseThread(void *pntr) DEBUG(net, 1, "[udp] removing advertise from master server"); /* 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); + NetworkAddress out_addr(NETWORK_MASTER_SERVER_HOST, NETWORK_MASTER_SERVER_PORT); /* Send the packet */ Packet p(PACKET_UDP_SERVER_UNREGISTER); @@ -516,10 +498,7 @@ void NetworkUDPRemoveAdvertise() 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); + NetworkAddress out_addr(NETWORK_MASTER_SERVER_HOST, NETWORK_MASTER_SERVER_PORT); DEBUG(net, 1, "[udp] advertising to master server");