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