1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/base/ip_endpoint.h" 6 7 #include "base/logging.h" 8 #include "base/string_number_conversions.h" 9 #if defined(OS_WIN) 10 #include <winsock2.h> 11 #elif defined(OS_POSIX) 12 #include <netinet/in.h> 13 #endif 14 15 namespace net { 16 17 IPEndPoint::IPEndPoint() : port_(0) {} 18 19 IPEndPoint::~IPEndPoint() {} 20 21 IPEndPoint::IPEndPoint(const IPAddressNumber& address, int port) 22 : address_(address), 23 port_(port) {} 24 25 IPEndPoint::IPEndPoint(const IPEndPoint& endpoint) { 26 address_ = endpoint.address_; 27 port_ = endpoint.port_; 28 } 29 30 int IPEndPoint::GetFamily() const { 31 switch (address_.size()) { 32 case kIPv4AddressSize: { 33 return AF_INET; 34 } 35 case kIPv6AddressSize: { 36 return AF_INET6; 37 } 38 default: { 39 NOTREACHED() << "Bad IP address"; 40 return AF_UNSPEC; 41 } 42 } 43 } 44 45 bool IPEndPoint::ToSockAddr(struct sockaddr* address, 46 size_t* address_length) const { 47 DCHECK(address); 48 DCHECK(address_length); 49 switch (address_.size()) { 50 case kIPv4AddressSize: { 51 if (*address_length < sizeof(struct sockaddr_in)) 52 return false; 53 *address_length = sizeof(struct sockaddr_in); 54 struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(address); 55 memset(addr, 0, sizeof(struct sockaddr_in)); 56 addr->sin_family = AF_INET; 57 addr->sin_port = htons(port_); 58 memcpy(&addr->sin_addr, &address_[0], kIPv4AddressSize); 59 break; 60 } 61 case kIPv6AddressSize: { 62 if (*address_length < sizeof(struct sockaddr_in6)) 63 return false; 64 *address_length = sizeof(struct sockaddr_in6); 65 struct sockaddr_in6* addr6 = 66 reinterpret_cast<struct sockaddr_in6*>(address); 67 memset(addr6, 0, sizeof(struct sockaddr_in6)); 68 addr6->sin6_family = AF_INET6; 69 addr6->sin6_port = htons(port_); 70 memcpy(&addr6->sin6_addr, &address_[0], kIPv6AddressSize); 71 break; 72 } 73 default: { 74 NOTREACHED() << "Bad IP address"; 75 break; 76 } 77 } 78 return true; 79 } 80 81 bool IPEndPoint::FromSockAddr(const struct sockaddr* address, 82 size_t address_length) { 83 DCHECK(address); 84 switch (address->sa_family) { 85 case AF_INET: { 86 const struct sockaddr_in* addr = 87 reinterpret_cast<const struct sockaddr_in*>(address); 88 port_ = ntohs(addr->sin_port); 89 const char* bytes = reinterpret_cast<const char*>(&addr->sin_addr); 90 address_.assign(&bytes[0], &bytes[kIPv4AddressSize]); 91 break; 92 } 93 case AF_INET6: { 94 const struct sockaddr_in6* addr = 95 reinterpret_cast<const struct sockaddr_in6*>(address); 96 port_ = ntohs(addr->sin6_port); 97 const char* bytes = reinterpret_cast<const char*>(&addr->sin6_addr); 98 address_.assign(&bytes[0], &bytes[kIPv6AddressSize]); 99 break; 100 } 101 default: { 102 NOTREACHED() << "Bad IP address"; 103 break; 104 } 105 } 106 return true; 107 } 108 109 std::string IPEndPoint::ToString() const { 110 struct sockaddr_storage addr_storage; 111 size_t addr_len = sizeof(addr_storage); 112 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 113 if (!ToSockAddr(addr, &addr_len)) { 114 return ""; 115 } 116 return NetAddressToStringWithPort(addr, addr_len); 117 } 118 119 bool IPEndPoint::operator<(const IPEndPoint& that) const { 120 // Sort IPv4 before IPv6. 121 if (address_.size() != that.address_.size()) { 122 return address_.size() < that.address_.size(); 123 } 124 if (address_ != that.address_) { 125 return address_ < that.address_; 126 } 127 return port_ < that.port_; 128 } 129 130 bool IPEndPoint::operator==(const IPEndPoint& that) const { 131 return address_ == that.address_ && port_ == that.port_; 132 } 133 134 } // namespace net 135