--- /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; +}