1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/* 2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle 3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc. 4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without 6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met: 7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 1. Redistributions of source code must retain the above copyright notice, 9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer. 10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright notice, 11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer in the documentation 12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * and/or other materials provided with the distribution. 13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 3. The name of the author may not be used to endorse or promote products 14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * derived from this software without specific prior written permission. 15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */ 27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef POSIX 29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <sys/types.h> 30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <sys/socket.h> 31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <netinet/in.h> 32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <netinet/ip.h> 33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <arpa/inet.h> 34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <netdb.h> 35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <unistd.h> 36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <sstream> 39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/byteorder.h" 41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h" 42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h" 43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/nethelpers.h" 44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/socketaddress.h" 45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32 47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Win32 doesn't provide inet_aton, so we add our own version here. 48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Since inet_addr returns 0xFFFFFFFF on error, if we get this value 49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// we need to test the input to see if the address really was 255.255.255.255. 50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// This is slightly fragile, but better than doing nothing. 51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint inet_aton(const char* cp, struct in_addr* inp) { 52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch inp->s_addr = inet_addr(cp); 53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (inp->s_addr == INADDR_NONE && 54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch strcmp(cp, "255.255.255.255") != 0) ? 0 : 1; 55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif // WIN32 57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base { 59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSocketAddress::SocketAddress() { 61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Clear(); 62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSocketAddress::SocketAddress(const std::string& hostname, int port) { 65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetIP(hostname); 66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetPort(port); 67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSocketAddress::SocketAddress(uint32 ip, int port) { 70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetIP(ip); 71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetPort(port); 72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSocketAddress::SocketAddress(const SocketAddress& addr) { 75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch this->operator=(addr); 76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SocketAddress::Clear() { 79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch hostname_.clear(); 80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ip_ = 0; 81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch port_ = 0; 82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::IsNil() const { 85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return hostname_.empty() && (0 == ip_) && (0 == port_); 86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::IsComplete() const { 89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (0 != ip_) && (0 != port_); 90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSocketAddress& SocketAddress::operator=(const SocketAddress& addr) { 93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch hostname_ = addr.hostname_; 94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ip_ = addr.ip_; 95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch port_ = addr.port_; 96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return *this; 97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SocketAddress::SetIP(uint32 ip) { 100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch hostname_.clear(); 101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ip_ = ip; 102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SocketAddress::SetIP(const std::string& hostname) { 105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch hostname_ = hostname; 106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ip_ = StringToIP(hostname); 107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SocketAddress::SetResolvedIP(uint32 ip) { 110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ip_ = ip; 111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SocketAddress::SetPort(int port) { 114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT((0 <= port) && (port < 65536)); 115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch port_ = port; 116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochuint32 SocketAddress::ip() const { 119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ip_; 120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochuint16 SocketAddress::port() const { 123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return port_; 124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string SocketAddress::IPAsString() const { 127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!hostname_.empty()) 128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return hostname_; 129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return IPToString(ip_); 130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string SocketAddress::PortAsString() const { 133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::ostringstream ost; 134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ost << port_; 135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ost.str(); 136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string SocketAddress::ToString() const { 139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::ostringstream ost; 140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ost << IPAsString(); 141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ost << ":"; 142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ost << port(); 143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ost.str(); 144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::FromString(const std::string& str) { 147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::string::size_type pos = str.find(':'); 148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (std::string::npos == pos) 149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetPort(strtoul(str.substr(pos + 1).c_str(), NULL, 10)); 151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetIP(str.substr(0, pos)); 152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::ostream& operator<<(std::ostream& os, const SocketAddress& addr) { 156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch os << addr.IPAsString() << ":" << addr.port(); 157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return os; 158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::IsAnyIP() const { 161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (ip_ == 0); 162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::IsLoopbackIP() const { 165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (0 == ip_) { 166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (0 == stricmp(hostname_.c_str(), "localhost")); 167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ((ip_ >> 24) == 127); 169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::IsLocalIP() const { 173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (IsLoopbackIP()) 174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::vector<uint32> ips; 177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (0 == ip_) { 178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!hostname_.empty() 179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch && (0 == stricmp(hostname_.c_str(), GetHostname().c_str()))) { 180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (GetLocalIPs(ips)) { 183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (size_t i = 0; i < ips.size(); ++i) { 184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (ips[i] == ip_) { 185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::IsPrivateIP() const { 193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ((ip_ >> 24) == 127) || 194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ((ip_ >> 24) == 10) || 195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ((ip_ >> 20) == ((172 << 4) | 1)) || 196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ((ip_ >> 16) == ((192 << 8) | 168)) || 197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ((ip_ >> 16) == ((169 << 8) | 254)); 198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::IsUnresolvedIP() const { 201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return IsAny() && !hostname_.empty(); 202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::ResolveIP(bool force, int* error) { 205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (hostname_.empty()) { 206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // nothing to resolve 207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (!force && !IsAny()) { 208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // already resolved 209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "(" << hostname_ << ")"; 211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int errcode = 0; 212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (hostent* pHost = SafeGetHostByName(hostname_.c_str(), &errcode)) { 213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ip_ = NetworkToHost32(*reinterpret_cast<uint32*>(pHost->h_addr_list[0])); 214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_VERBOSE) << "(" << hostname_ << ") resolved to: " 215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << IPToString(ip_); 216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch FreeHostEnt(pHost); 217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG_F(LS_ERROR) << "(" << hostname_ << ") err: " << errcode; 219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (error) { 221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *error = errcode; 222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (ip_ != 0); 225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::operator==(const SocketAddress& addr) const { 228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return EqualIPs(addr) && EqualPorts(addr); 229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::operator<(const SocketAddress& addr) const { 232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (ip_ < addr.ip_) 233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch else if (addr.ip_ < ip_) 235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // We only check hostnames if both IPs are zero. This matches EqualIPs() 238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (addr.ip_ == 0) { 239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (hostname_ < addr.hostname_) 240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch else if (addr.hostname_ < hostname_) 242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return port_ < addr.port_; 246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::EqualIPs(const SocketAddress& addr) const { 249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (ip_ == addr.ip_) && ((ip_ != 0) || (hostname_ == addr.hostname_)); 250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::EqualPorts(const SocketAddress& addr) const { 253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (port_ == addr.port_); 254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochsize_t SocketAddress::Hash() const { 257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch size_t h = 0; 258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch h ^= ip_; 259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch h ^= port_ | (port_ << 16); 260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return h; 261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochsize_t SocketAddress::Size_() const { 264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return sizeof(ip_) + sizeof(port_) + 2; 265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::Write_(char* buf, int len) const { 268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (len < static_cast<int>(Size_())) 269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buf[0] = 0; 271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buf[1] = AF_INET; 272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetBE16(buf + 2, port_); 273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetBE32(buf + 4, ip_); 274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::Read_(const char* buf, int len) { 278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (len < static_cast<int>(Size_()) || buf[1] != AF_INET) 279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch port_ = GetBE16(buf + 2); 281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ip_ = GetBE32(buf + 4); 282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SocketAddress::ToSockAddr(sockaddr_in* saddr) const { 286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch memset(saddr, 0, sizeof(*saddr)); 287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch saddr->sin_family = AF_INET; 288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch saddr->sin_port = HostToNetwork16(port_); 289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (0 == ip_) { 290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch saddr->sin_addr.s_addr = INADDR_ANY; 291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch saddr->sin_addr.s_addr = HostToNetwork32(ip_); 293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::FromSockAddr(const sockaddr_in& saddr) { 297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (saddr.sin_family != AF_INET) 298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetIP(NetworkToHost32(saddr.sin_addr.s_addr)); 300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetPort(NetworkToHost16(saddr.sin_port)); 301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string SocketAddress::IPToString(uint32 ip) { 305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::ostringstream ost; 306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ost << ((ip >> 24) & 0xff); 307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ost << '.'; 308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ost << ((ip >> 16) & 0xff); 309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ost << '.'; 310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ost << ((ip >> 8) & 0xff); 311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ost << '.'; 312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ost << ((ip >> 0) & 0xff); 313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ost.str(); 314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::StringToIP(const std::string& hostname, uint32* ip) { 317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch in_addr addr; 318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (inet_aton(hostname.c_str(), &addr) == 0) 319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *ip = NetworkToHost32(addr.s_addr); 321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 323f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochuint32 SocketAddress::StringToIP(const std::string& hostname) { 325f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch uint32 ip = 0; 326f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch StringToIP(hostname, &ip); 327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ip; 328f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 329f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 330f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string SocketAddress::GetHostname() { 331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char hostname[256]; 332f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (gethostname(hostname, ARRAY_SIZE(hostname)) == 0) 333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return hostname; 334f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ""; 335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SocketAddress::GetLocalIPs(std::vector<uint32>& ips) { 338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ips.clear(); 339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 340f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const std::string hostname = GetHostname(); 341f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (hostname.empty()) 342f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int errcode; 345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (hostent* pHost = SafeGetHostByName(hostname.c_str(), &errcode)) { 346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (size_t i = 0; pHost->h_addr_list[i]; ++i) { 347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch uint32 ip = 348f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch NetworkToHost32(*reinterpret_cast<uint32 *>(pHost->h_addr_list[i])); 349f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ips.push_back(ip); 350f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch FreeHostEnt(pHost); 352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return !ips.empty(); 353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 3543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(LS_ERROR) << "gethostbyname err: " << errcode; 355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // namespace talk_base 359