ip_endpoint.cc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // Copyright (c) 2012 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. #include "net/base/ip_endpoint.h"
  5. #include <ostream>
  6. #include <string.h>
  7. #include <tuple>
  8. #include "base/check.h"
  9. #include "base/check_op.h"
  10. #include "base/notreached.h"
  11. #include "base/strings/string_number_conversions.h"
  12. #include "base/sys_byteorder.h"
  13. #include "build/build_config.h"
  14. #include "net/base/ip_address.h"
  15. #include "net/base/sys_addrinfo.h"
  16. #if BUILDFLAG(IS_WIN)
  17. #include <winsock2.h>
  18. #include <ws2bth.h>
  19. #include "net/base/winsock_util.h" // For kBluetoothAddressSize
  20. #endif
  21. namespace net {
  22. IPEndPoint::IPEndPoint() = default;
  23. IPEndPoint::~IPEndPoint() = default;
  24. IPEndPoint::IPEndPoint(const IPAddress& address, uint16_t port)
  25. : address_(address), port_(port) {}
  26. IPEndPoint::IPEndPoint(const IPEndPoint& endpoint) = default;
  27. uint16_t IPEndPoint::port() const {
  28. #if BUILDFLAG(IS_WIN)
  29. DCHECK_NE(address_.size(), kBluetoothAddressSize);
  30. #endif
  31. return port_;
  32. }
  33. AddressFamily IPEndPoint::GetFamily() const {
  34. return GetAddressFamily(address_);
  35. }
  36. int IPEndPoint::GetSockAddrFamily() const {
  37. switch (address_.size()) {
  38. case IPAddress::kIPv4AddressSize:
  39. return AF_INET;
  40. case IPAddress::kIPv6AddressSize:
  41. return AF_INET6;
  42. #if BUILDFLAG(IS_WIN)
  43. case kBluetoothAddressSize:
  44. return AF_BTH;
  45. #endif
  46. default:
  47. NOTREACHED() << "Bad IP address";
  48. return AF_UNSPEC;
  49. }
  50. }
  51. bool IPEndPoint::ToSockAddr(struct sockaddr* address,
  52. socklen_t* address_length) const {
  53. // By definition, socklen_t is large enough to hold both sizes.
  54. constexpr socklen_t kSockaddrInSize =
  55. static_cast<socklen_t>(sizeof(struct sockaddr_in));
  56. constexpr socklen_t kSockaddrIn6Size =
  57. static_cast<socklen_t>(sizeof(struct sockaddr_in6));
  58. DCHECK(address);
  59. DCHECK(address_length);
  60. #if BUILDFLAG(IS_WIN)
  61. DCHECK_NE(address_.size(), kBluetoothAddressSize);
  62. #endif
  63. switch (address_.size()) {
  64. case IPAddress::kIPv4AddressSize: {
  65. if (*address_length < kSockaddrInSize)
  66. return false;
  67. *address_length = kSockaddrInSize;
  68. struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(address);
  69. memset(addr, 0, sizeof(struct sockaddr_in));
  70. addr->sin_family = AF_INET;
  71. addr->sin_port = base::HostToNet16(port_);
  72. memcpy(&addr->sin_addr, address_.bytes().data(),
  73. IPAddress::kIPv4AddressSize);
  74. break;
  75. }
  76. case IPAddress::kIPv6AddressSize: {
  77. if (*address_length < kSockaddrIn6Size)
  78. return false;
  79. *address_length = kSockaddrIn6Size;
  80. struct sockaddr_in6* addr6 =
  81. reinterpret_cast<struct sockaddr_in6*>(address);
  82. memset(addr6, 0, sizeof(struct sockaddr_in6));
  83. addr6->sin6_family = AF_INET6;
  84. addr6->sin6_port = base::HostToNet16(port_);
  85. memcpy(&addr6->sin6_addr, address_.bytes().data(),
  86. IPAddress::kIPv6AddressSize);
  87. break;
  88. }
  89. default:
  90. return false;
  91. }
  92. return true;
  93. }
  94. bool IPEndPoint::FromSockAddr(const struct sockaddr* sock_addr,
  95. socklen_t sock_addr_len) {
  96. DCHECK(sock_addr);
  97. switch (sock_addr->sa_family) {
  98. case AF_INET: {
  99. if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in)))
  100. return false;
  101. const struct sockaddr_in* addr =
  102. reinterpret_cast<const struct sockaddr_in*>(sock_addr);
  103. *this = IPEndPoint(
  104. IPAddress(reinterpret_cast<const uint8_t*>(&addr->sin_addr),
  105. IPAddress::kIPv4AddressSize),
  106. base::NetToHost16(addr->sin_port));
  107. return true;
  108. }
  109. case AF_INET6: {
  110. if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in6)))
  111. return false;
  112. const struct sockaddr_in6* addr =
  113. reinterpret_cast<const struct sockaddr_in6*>(sock_addr);
  114. *this = IPEndPoint(
  115. IPAddress(reinterpret_cast<const uint8_t*>(&addr->sin6_addr),
  116. IPAddress::kIPv6AddressSize),
  117. base::NetToHost16(addr->sin6_port));
  118. return true;
  119. }
  120. #if BUILDFLAG(IS_WIN)
  121. case AF_BTH: {
  122. if (sock_addr_len < static_cast<socklen_t>(sizeof(SOCKADDR_BTH)))
  123. return false;
  124. const SOCKADDR_BTH* addr =
  125. reinterpret_cast<const SOCKADDR_BTH*>(sock_addr);
  126. *this = IPEndPoint();
  127. address_ = IPAddress(reinterpret_cast<const uint8_t*>(&addr->btAddr),
  128. kBluetoothAddressSize);
  129. // Intentionally ignoring Bluetooth port. It is a ULONG, but
  130. // `IPEndPoint::port_` is a uint16_t. See https://crbug.com/1231273.
  131. return true;
  132. }
  133. #endif
  134. }
  135. return false; // Unrecognized |sa_family|.
  136. }
  137. std::string IPEndPoint::ToString() const {
  138. #if BUILDFLAG(IS_WIN)
  139. DCHECK_NE(address_.size(), kBluetoothAddressSize);
  140. #endif
  141. return IPAddressToStringWithPort(address_, port_);
  142. }
  143. std::string IPEndPoint::ToStringWithoutPort() const {
  144. #if BUILDFLAG(IS_WIN)
  145. DCHECK_NE(address_.size(), kBluetoothAddressSize);
  146. #endif
  147. return address_.ToString();
  148. }
  149. bool IPEndPoint::operator<(const IPEndPoint& other) const {
  150. // Sort IPv4 before IPv6.
  151. if (address_.size() != other.address_.size()) {
  152. return address_.size() < other.address_.size();
  153. }
  154. return std::tie(address_, port_) < std::tie(other.address_, other.port_);
  155. }
  156. bool IPEndPoint::operator==(const IPEndPoint& other) const {
  157. return address_ == other.address_ && port_ == other.port_;
  158. }
  159. bool IPEndPoint::operator!=(const IPEndPoint& that) const {
  160. return !(*this == that);
  161. }
  162. std::ostream& operator<<(std::ostream& os, const IPEndPoint& ip_endpoint) {
  163. return os << ip_endpoint.ToString();
  164. }
  165. } // namespace net