changeset 11550:1449b6fb6ce6 draft

(svn r15915) -Codechange: let the udp code use NetworkAddress.
author rubidium <rubidium@openttd.org>
date Thu, 02 Apr 2009 19:21:26 +0000
parents df3afb578e51
children 939f22f810ef
files src/network/core/address.cpp src/network/core/address.h src/network/core/udp.cpp src/network/core/udp.h src/network/network_udp.cpp
diffstat 5 files changed, 90 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- 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 @@
 	return buf;
 }
 
+const sockaddr_storage *NetworkAddress::GetAddress()
+{
+	if (!this->resolved) this->GetIP();
+	return &this->address;
+}
+
 #endif /* ENABLE_NETWORK */
--- 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:
 	/**
@@ -29,9 +28,22 @@
 	 */
 	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 @@
 	 */
 	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 @@
 	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 @@
 	 * 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 @@
 	 * Get the port
 	 * @return the port
 	 */
-	uint16 GetPort() const
-	{
-		return this->port;
-	}
+	uint16 GetPort() const;
 
 	/**
 	 * Check whether the IP address has been resolved already
--- a/src/network/core/udp.cpp
+++ b/src/network/core/udp.cpp
@@ -82,14 +82,14 @@
  * @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::ReceivePackets()
 {
-	struct sockaddr_in client_addr;
+	struct sockaddr_storage client_addr;
 	socklen_t client_len;
 	int nbytes;
 	Packet p(this);
@@ -117,19 +117,18 @@
 
 	/* 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 @@
  * @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 @@
 
 		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 @@
  */
 #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);
--- 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 @@
 	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 @@
 	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 @@
 	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);
--- a/src/network/network_udp.cpp
+++ b/src/network/network_udp.cpp
@@ -104,7 +104,7 @@
 	/* 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 @@
 	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 @@
 	/* 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 @@
 		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 @@
 				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 @@
 	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 @@
 
 	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 @@
 /* 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 @@
 {
 	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<NetworkGameList>(1);
@@ -481,10 +466,7 @@
 	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 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");