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