Thu, 11 Dec 2014 05:58:55 +0200
- code cleanup
- added network-related classes (bytestream, ipaddress, udp socket)
#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; }