xref: /aosp_15_r20/external/cronet/net/base/address_list.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
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/address_list.h"
6 
7 #include <iterator>
8 #include <string>
9 #include <utility>
10 #include <vector>
11 
12 #include "base/containers/flat_map.h"
13 #include "base/logging.h"
14 #include "base/values.h"
15 #include "net/base/sys_addrinfo.h"
16 
17 namespace net {
18 
19 AddressList::AddressList() = default;
20 
21 AddressList::AddressList(const AddressList&) = default;
22 
23 AddressList& AddressList::operator=(const AddressList&) = default;
24 
25 AddressList::AddressList(AddressList&&) = default;
26 
27 AddressList& AddressList::operator=(AddressList&&) = default;
28 
29 AddressList::~AddressList() = default;
30 
AddressList(const IPEndPoint & endpoint)31 AddressList::AddressList(const IPEndPoint& endpoint) {
32   push_back(endpoint);
33 }
34 
AddressList(const IPEndPoint & endpoint,std::vector<std::string> aliases)35 AddressList::AddressList(const IPEndPoint& endpoint,
36                          std::vector<std::string> aliases)
37     : dns_aliases_(std::move(aliases)) {
38   push_back(endpoint);
39 }
40 
AddressList(std::vector<IPEndPoint> endpoints)41 AddressList::AddressList(std::vector<IPEndPoint> endpoints)
42     : endpoints_(std::move(endpoints)) {}
43 
44 // static
CreateFromIPAddress(const IPAddress & address,uint16_t port)45 AddressList AddressList::CreateFromIPAddress(const IPAddress& address,
46                                              uint16_t port) {
47   return AddressList(IPEndPoint(address, port));
48 }
49 
50 // static
CreateFromIPAddressList(const IPAddressList & addresses,std::vector<std::string> aliases)51 AddressList AddressList::CreateFromIPAddressList(
52     const IPAddressList& addresses,
53     std::vector<std::string> aliases) {
54   AddressList list;
55   for (const auto& address : addresses) {
56     list.push_back(IPEndPoint(address, 0));
57   }
58   list.SetDnsAliases(std::move(aliases));
59   return list;
60 }
61 
62 // static
CreateFromAddrinfo(const struct addrinfo * head)63 AddressList AddressList::CreateFromAddrinfo(const struct addrinfo* head) {
64   DCHECK(head);
65   AddressList list;
66   if (head->ai_canonname) {
67     std::vector<std::string> aliases({std::string(head->ai_canonname)});
68     list.SetDnsAliases(std::move(aliases));
69   }
70   for (const struct addrinfo* ai = head; ai; ai = ai->ai_next) {
71     IPEndPoint ipe;
72     // NOTE: Ignoring non-INET* families.
73     if (ipe.FromSockAddr(ai->ai_addr, static_cast<socklen_t>(ai->ai_addrlen)))
74       list.push_back(ipe);
75     else
76       DLOG(WARNING) << "Unknown family found in addrinfo: " << ai->ai_family;
77   }
78   return list;
79 }
80 
81 // static
CopyWithPort(const AddressList & list,uint16_t port)82 AddressList AddressList::CopyWithPort(const AddressList& list, uint16_t port) {
83   AddressList out;
84   out.SetDnsAliases(list.dns_aliases());
85   for (const auto& i : list)
86     out.push_back(IPEndPoint(i.address(), port));
87   return out;
88 }
89 
SetDefaultCanonicalName()90 void AddressList::SetDefaultCanonicalName() {
91   DCHECK(!empty());
92   DCHECK(dns_aliases_.empty());
93   SetDnsAliases({front().ToStringWithoutPort()});
94 }
95 
SetDnsAliases(std::vector<std::string> aliases)96 void AddressList::SetDnsAliases(std::vector<std::string> aliases) {
97   // TODO(cammie): Track down the callers who use {""} for `aliases` and
98   // update so that we can enforce by DCHECK below.
99   // The empty canonical name is represented by a empty `dns_aliases_`
100   // vector, so in this case we reset the field.
101   if (aliases == std::vector<std::string>({""})) {
102     dns_aliases_ = std::vector<std::string>();
103     return;
104   }
105 
106   dns_aliases_ = std::move(aliases);
107 }
108 
AppendDnsAliases(std::vector<std::string> aliases)109 void AddressList::AppendDnsAliases(std::vector<std::string> aliases) {
110   DCHECK(aliases != std::vector<std::string>({""}));
111   using iter_t = std::vector<std::string>::iterator;
112 
113   dns_aliases_.insert(dns_aliases_.end(),
114                       std::move_iterator<iter_t>(aliases.begin()),
115                       std::move_iterator<iter_t>(aliases.end()));
116 }
117 
NetLogParams() const118 base::Value::Dict AddressList::NetLogParams() const {
119   base::Value::Dict dict;
120 
121   base::Value::List address_list;
122   for (const auto& ip_endpoint : *this)
123     address_list.Append(ip_endpoint.ToString());
124   dict.Set("address_list", std::move(address_list));
125 
126   base::Value::List alias_list;
127   for (const std::string& alias : dns_aliases_)
128     alias_list.Append(alias);
129   dict.Set("aliases", std::move(alias_list));
130 
131   return dict;
132 }
133 
Deduplicate()134 void AddressList::Deduplicate() {
135   if (size() > 1) {
136     std::vector<std::pair<IPEndPoint, int>> make_me_into_a_map(size());
137     for (auto& addr : *this)
138       make_me_into_a_map.emplace_back(addr, 0);
139     base::flat_map<IPEndPoint, int> inserted(std::move(make_me_into_a_map));
140 
141     std::vector<IPEndPoint> deduplicated_addresses;
142     deduplicated_addresses.reserve(inserted.size());
143     for (const auto& addr : *this) {
144       int& count = inserted[addr];
145       if (!count) {
146         deduplicated_addresses.push_back(addr);
147         ++count;
148       }
149     }
150     endpoints_.swap(deduplicated_addresses);
151   }
152 }
153 
154 }  // namespace net
155