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
15namespace net {
16
17IPEndPoint::IPEndPoint() : port_(0) {}
18
19IPEndPoint::~IPEndPoint() {}
20
21IPEndPoint::IPEndPoint(const IPAddressNumber& address, int port)
22    : address_(address),
23      port_(port) {}
24
25IPEndPoint::IPEndPoint(const IPEndPoint& endpoint) {
26  address_ = endpoint.address_;
27  port_ = endpoint.port_;
28}
29
30int 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
45bool 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
81bool 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
109std::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
119bool 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
130bool IPEndPoint::operator==(const IPEndPoint& that) const {
131  return address_ == that.address_ && port_ == that.port_;
132}
133
134}  // namespace net
135