15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 85e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_byteorder.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winsock2.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netinet/in.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// By definition, socklen_t is large enough to hold both sizes. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const socklen_t kSockaddrInSize = sizeof(struct sockaddr_in); 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const socklen_t kSockaddrIn6Size = sizeof(struct sockaddr_in6); 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPEndPoint::IPEndPoint() : port_(0) {} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPEndPoint::~IPEndPoint() {} 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPEndPoint::IPEndPoint(const IPAddressNumber& address, int port) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : address_(address), 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_(port) {} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPEndPoint::IPEndPoint(const IPEndPoint& endpoint) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) address_ = endpoint.address_; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_ = endpoint.port_; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AddressFamily IPEndPoint::GetFamily() const { 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetAddressFamily(address_); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int IPEndPoint::GetSockAddrFamily() const { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (address_.size()) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIPv4AddressSize: 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AF_INET; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIPv6AddressSize: 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AF_INET6; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Bad IP address"; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AF_UNSPEC; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IPEndPoint::ToSockAddr(struct sockaddr* address, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socklen_t* address_length) const { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(address); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(address_length); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (address_.size()) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIPv4AddressSize: { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*address_length < kSockaddrInSize) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *address_length = kSockaddrInSize; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(address); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(addr, 0, sizeof(struct sockaddr_in)); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr->sin_family = AF_INET; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr->sin_port = base::HostToNet16(port_); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&addr->sin_addr, &address_[0], kIPv4AddressSize); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIPv6AddressSize: { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*address_length < kSockaddrIn6Size) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *address_length = kSockaddrIn6Size; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_in6* addr6 = 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<struct sockaddr_in6*>(address); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(addr6, 0, sizeof(struct sockaddr_in6)); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr6->sin6_family = AF_INET6; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr6->sin6_port = base::HostToNet16(port_); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&addr6->sin6_addr, &address_[0], kIPv6AddressSize); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IPEndPoint::FromSockAddr(const struct sockaddr* sock_addr, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socklen_t sock_addr_len) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(sock_addr); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* address; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t address_len; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 port; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetIPAddressFromSockAddr(sock_addr, sock_addr_len, &address, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &address_len, &port)) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) address_.assign(address, address + address_len); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_ = port; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string IPEndPoint::ToString() const { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IPAddressToStringWithPort(address_, port_); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string IPEndPoint::ToStringWithoutPort() const { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IPAddressToString(address_); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IPEndPoint::operator<(const IPEndPoint& that) const { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sort IPv4 before IPv6. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (address_.size() != that.address_.size()) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return address_.size() < that.address_.size(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (address_ != that.address_) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return address_ < that.address_; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return port_ < that.port_; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IPEndPoint::operator==(const IPEndPoint& that) const { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return address_ == that.address_ && port_ == that.port_; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 128