sources/network/ipaddress.cpp

changeset 5
146825d63b9a
child 7
01e4e9ae323a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sources/network/ipaddress.cpp	Thu Dec 11 05:58:55 2014 +0200
@@ -0,0 +1,165 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include "ipaddress.h"
+
+const IPAddress localhost (0x7F000001, 0);
+bool IPAddress::sink;
+
+// -----------------------------------------------------------------------------
+//
+IPAddress::IPAddress() :
+	host (0),
+	port (0) {}
+
+// -----------------------------------------------------------------------------
+//
+IPAddress::IPAddress (unsigned long host, unsigned short port) :
+	host (host),
+	port (port) {}
+
+// -----------------------------------------------------------------------------
+//
+IPAddress::IPAddress (const IPAddress& other) :
+	host (other.host),
+	port (other.port) {}
+
+// -----------------------------------------------------------------------------
+//
+METHOD
+IPAddress::to_string (WithPort withport) const -> String
+{
+	String val;
+
+	if (withport == IP_WITH_PORT)
+		val.sprintf ("%u.%u.%u.%u:%u", octet (0), octet (1), octet (2), octet (3), port);
+	else
+		val.sprintf ("%u.%u.%u.%u", octet (0), octet (1), octet (2), octet (3));
+
+	return val;
+}
+
+// -----------------------------------------------------------------------------
+//
+METHOD
+IPAddress::octet (int n) const -> unsigned char
+{
+	return (host >> ((3 - n) * 8)) & 0xFF;
+}
+
+// -----------------------------------------------------------------------------
+//
+METHOD
+IPAddress::set_octet (int n, unsigned char oct) -> void
+{
+	// TODO: make a big-endian version
+	host &= ~(0xFF << (3 - n) * 8);
+	host |= oct << ((3 - n) * 8);
+}
+
+// -----------------------------------------------------------------------------
+//
+METHOD
+IPAddress::compare (const IPAddress& other) const -> bool
+{
+	for (int i = 0; i < 4; ++i)
+	{
+		if (octet (i) != other.octet (i))
+			return false;
+	}
+
+	if (port != 0
+		and other.port != 0
+		and port != other.port)
+	{
+		return false;
+	}
+
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+//
+METHOD
+IPAddress::operator< (const IPAddress& other) const -> bool
+{
+	for (int i = 0; i < 4; ++i)
+	{
+		if (octet (i) != other.octet (i))
+			return octet (i) < other.octet (i);
+	}
+
+	return port < other.port;
+}
+
+// -----------------------------------------------------------------------------
+//
+METHOD
+IPAddress::to_sockaddr_in() const -> sockaddr_in
+{
+	sockaddr_in claddr;
+	memset (&claddr, 0, sizeof claddr);
+	claddr.sin_addr.s_addr = htonl (host);
+	claddr.sin_port = htons (port);
+	claddr.sin_family = AF_INET;
+	return claddr;
+}
+
+// -----------------------------------------------------------------------------
+//
+STATIC METHOD
+IPAddress::from_string (String input, bool* ok) -> IPAddress
+{
+	unsigned int parts[4];
+	int colonpos = input.find (":");
+	String addressString = colonpos == -1 ? input : input.mid (0, colonpos);
+	IPAddress value;
+
+	// Try scanf the IPv4 host first. If it's not an IP string, it could
+	// be a hostname; thus try resolve it.
+	if (sscanf (addressString, "%u.%u.%u.%u", &parts[0], &parts[1], &parts[2], &parts[3]))
+	{
+		for (short i = 0; i < 4; ++i)
+			value.set_octet (i, parts[i]);
+	}
+	else
+	{
+		// try resolve it
+		return IPAddress::resolve (addressString, ok);
+	}
+
+	if (colonpos != -1)
+		value.port = atoi (input.mid (colonpos + 1, -1));
+
+	return value;
+}
+
+// -----------------------------------------------------------------------------
+//
+STATIC METHOD
+IPAddress::resolve (String node, bool* ok) -> IPAddress
+{
+	struct addrinfo hints;
+	struct addrinfo* lookup;
+	int errorcode;
+	memset (&hints, 0, sizeof hints);
+	hints.ai_family = AF_INET;
+
+	if ((errorcode = getaddrinfo (node, nullptr, &hints, &lookup)) != 0)
+	{
+		*ok = false;
+		return IPAddress();
+	}
+
+	IPAddress result;
+	assert (lookup != nullptr);
+	sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*> (lookup[0].ai_addr);
+	result.host = ntohl (addr->sin_addr.s_addr);
+	result.port = ntohs (addr->sin_port);
+	freeaddrinfo (lookup);
+	*ok = true;
+	return result;
+}

mercurial