/** \file NetAddress.cpp \maintainer Morgan McGuire, http://graphics.cs.williams.edu \created 2005-02-06 \edited 2013-03-17 */ #include "G3D/platform.h" #include "G3D/NetAddress.h" #include "G3D/BinaryInput.h" #include "G3D/BinaryOutput.h" #include "G3D/Array.h" #include "G3D/stringutils.h" #include "G3D/System.h" #include "G3D/NetworkDevice.h" #include "G3D/Log.h" #if defined(G3D_LINUX) || defined(G3D_OSX) #include #include #include #include #include #include #include #define _alloca alloca #define SOCKET_ERROR -1 # ifndef SOCKADDR_IN # define SOCKADDR_IN struct sockaddr_in # endif # ifndef SOCKET # define SOCKET int # endif // SOCKADDR_IN is supposed to be defined in NetAddress.h #ifndef SOCKADDR_IN # error Network headers included in wrong order #endif #endif namespace G3D { NetAddress::NetAddress() { System::memset(&addr, 0, sizeof(addr)); } void NetAddress::init(uint32 host, uint16 port) { if ((host != 0) || (port != 0)) { addr.sin_family = AF_INET; addr.sin_port = htons(port); if (host == 0) { host = INADDR_ANY; } addr.sin_addr.s_addr = htonl(host); } else { System::memset(&addr, 0, sizeof(addr)); } } NetAddress::NetAddress (const std::string& hostname, uint16 port) { init(hostname, port); } void NetAddress::init (const std::string& hostname, uint16 port) { uint32 addr; if (hostname == "") { addr = INADDR_NONE; } else { addr = inet_addr(hostname.c_str()); } // The address wasn't in numeric form, resolve it if (addr == INADDR_NONE) { // Get the IP address of the server and store it in host struct hostent* host = gethostbyname(hostname.c_str()); if (host == NULL) { init(0, 0); return; } System::memcpy(&addr, host->h_addr_list[0], host->h_length); } if (addr != INADDR_NONE) { addr = ntohl(addr); } init(addr, port); } NetAddress::NetAddress(uint32 hostip, uint16 port) { init(hostip, port); } NetAddress NetAddress::broadcastAddress(uint16 port) { return NetAddress(NetworkDevice::instance()->broadcastAddressArray()[0], port); } NetAddress::NetAddress(const std::string& hostnameAndPort) { Array part = stringSplit(hostnameAndPort, ':'); debugAssert(part.length() == 2); init(part[0], atoi(part[1].c_str())); } NetAddress::NetAddress(const SOCKADDR_IN& a) { addr = a; } NetAddress::NetAddress(const struct in_addr& addr, uint16 port) { #ifdef G3D_WINDOWS init(ntohl(addr.S_un.S_addr), port); #else init(htonl(addr.s_addr), port); #endif } void NetAddress::localHostAddresses(Array& array) { array.resize(0); char ac[256]; if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) { Log::common()->printf("Error while getting local host name\n"); return; } struct hostent* phe = gethostbyname(ac); if (phe == 0) { Log::common()->printf("Error while getting local host address\n"); return; } for (int i = 0; (phe->h_addr_list[i] != 0); ++i) { struct in_addr addr; memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr)); array.append(NetAddress(addr)); } } void NetAddress::serialize(class BinaryOutput& b) const { b.writeUInt32(ip()); b.writeUInt16(port()); } void NetAddress::deserialize(class BinaryInput& b) { uint32 i; uint16 p; i = b.readUInt32(); p = b.readUInt16(); init(i, p); } bool NetAddress::ok() const { return addr.sin_family != 0; } std::string NetAddress::ipString() const { return format("%s", inet_ntoa(*(in_addr*)&(addr.sin_addr))); } std::string NetAddress::toString() const { return ipString() + format(":%d", ntohs(addr.sin_port)); } }