xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/platform/api/quic_socket_address.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2016 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 "quiche/quic/platform/api/quic_socket_address.h"
6 
7 #include <cstring>
8 #include <limits>
9 #include <string>
10 
11 #include "absl/strings/str_cat.h"
12 #include "quiche/quic/platform/api/quic_bug_tracker.h"
13 #include "quiche/quic/platform/api/quic_ip_address.h"
14 #include "quiche/quic/platform/api/quic_ip_address_family.h"
15 
16 namespace quic {
17 
18 namespace {
19 
HashIP(const QuicIpAddress & ip)20 uint32_t HashIP(const QuicIpAddress& ip) {
21   if (ip.IsIPv4()) {
22     return ip.GetIPv4().s_addr;
23   }
24   if (ip.IsIPv6()) {
25     auto v6addr = ip.GetIPv6();
26     const uint32_t* v6_as_ints =
27         reinterpret_cast<const uint32_t*>(&v6addr.s6_addr);
28     return v6_as_ints[0] ^ v6_as_ints[1] ^ v6_as_ints[2] ^ v6_as_ints[3];
29   }
30   return 0;
31 }
32 
33 }  // namespace
34 
QuicSocketAddress(QuicIpAddress address,uint16_t port)35 QuicSocketAddress::QuicSocketAddress(QuicIpAddress address, uint16_t port)
36     : host_(address), port_(port) {}
37 
QuicSocketAddress(const struct sockaddr_storage & saddr)38 QuicSocketAddress::QuicSocketAddress(const struct sockaddr_storage& saddr) {
39   switch (saddr.ss_family) {
40     case AF_INET: {
41       const sockaddr_in* v4 = reinterpret_cast<const sockaddr_in*>(&saddr);
42       host_ = QuicIpAddress(v4->sin_addr);
43       port_ = ntohs(v4->sin_port);
44       break;
45     }
46     case AF_INET6: {
47       const sockaddr_in6* v6 = reinterpret_cast<const sockaddr_in6*>(&saddr);
48       host_ = QuicIpAddress(v6->sin6_addr);
49       port_ = ntohs(v6->sin6_port);
50       break;
51     }
52     default:
53       QUIC_BUG(quic_bug_10075_1)
54           << "Unknown address family passed: " << saddr.ss_family;
55       break;
56   }
57 }
58 
QuicSocketAddress(const sockaddr * saddr,socklen_t len)59 QuicSocketAddress::QuicSocketAddress(const sockaddr* saddr, socklen_t len) {
60   sockaddr_storage storage;
61   static_assert(std::numeric_limits<socklen_t>::max() >= sizeof(storage),
62                 "Cannot cast sizeof(storage) to socklen_t as it does not fit");
63   if (len < static_cast<socklen_t>(sizeof(sockaddr)) ||
64       (saddr->sa_family == AF_INET &&
65        len < static_cast<socklen_t>(sizeof(sockaddr_in))) ||
66       (saddr->sa_family == AF_INET6 &&
67        len < static_cast<socklen_t>(sizeof(sockaddr_in6))) ||
68       len > static_cast<socklen_t>(sizeof(storage))) {
69     QUIC_BUG(quic_bug_10075_2) << "Socket address of invalid length provided";
70     return;
71   }
72   memcpy(&storage, saddr, len);
73   *this = QuicSocketAddress(storage);
74 }
75 
operator ==(const QuicSocketAddress & lhs,const QuicSocketAddress & rhs)76 bool operator==(const QuicSocketAddress& lhs, const QuicSocketAddress& rhs) {
77   return lhs.host_ == rhs.host_ && lhs.port_ == rhs.port_;
78 }
79 
operator !=(const QuicSocketAddress & lhs,const QuicSocketAddress & rhs)80 bool operator!=(const QuicSocketAddress& lhs, const QuicSocketAddress& rhs) {
81   return !(lhs == rhs);
82 }
83 
IsInitialized() const84 bool QuicSocketAddress::IsInitialized() const { return host_.IsInitialized(); }
85 
ToString() const86 std::string QuicSocketAddress::ToString() const {
87   switch (host_.address_family()) {
88     case IpAddressFamily::IP_V4:
89       return absl::StrCat(host_.ToString(), ":", port_);
90     case IpAddressFamily::IP_V6:
91       return absl::StrCat("[", host_.ToString(), "]:", port_);
92     default:
93       return "";
94   }
95 }
96 
FromSocket(int fd)97 int QuicSocketAddress::FromSocket(int fd) {
98   sockaddr_storage addr;
99   socklen_t addr_len = sizeof(addr);
100   int result = getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &addr_len);
101 
102   bool success = result == 0 && addr_len > 0 &&
103                  static_cast<size_t>(addr_len) <= sizeof(addr);
104   if (success) {
105     *this = QuicSocketAddress(addr);
106     return 0;
107   }
108   return -1;
109 }
110 
Normalized() const111 QuicSocketAddress QuicSocketAddress::Normalized() const {
112   return QuicSocketAddress(host_.Normalized(), port_);
113 }
114 
host() const115 QuicIpAddress QuicSocketAddress::host() const { return host_; }
116 
port() const117 uint16_t QuicSocketAddress::port() const { return port_; }
118 
generic_address() const119 sockaddr_storage QuicSocketAddress::generic_address() const {
120   union {
121     sockaddr_storage storage;
122     sockaddr_in v4;
123     sockaddr_in6 v6;
124   } result;
125   memset(&result.storage, 0, sizeof(result.storage));
126 
127   switch (host_.address_family()) {
128     case IpAddressFamily::IP_V4:
129       result.v4.sin_family = AF_INET;
130       result.v4.sin_addr = host_.GetIPv4();
131       result.v4.sin_port = htons(port_);
132       break;
133     case IpAddressFamily::IP_V6:
134       result.v6.sin6_family = AF_INET6;
135       result.v6.sin6_addr = host_.GetIPv6();
136       result.v6.sin6_port = htons(port_);
137       break;
138     default:
139       result.storage.ss_family = AF_UNSPEC;
140       break;
141   }
142   return result.storage;
143 }
144 
Hash() const145 uint32_t QuicSocketAddress::Hash() const {
146   uint32_t value = 0;
147   value ^= HashIP(host_);
148   value ^= port_ | (port_ << 16);
149   return value;
150 }
151 
152 }  // namespace quic
153