Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: net/base/address_list.cc

Issue 10309002: Reimplements net::AddressList without struct addrinfo. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added missing NET_EXPORT to *PortOnAddressList. Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/address_list.h" 5 #include "net/base/address_list.h"
6 6
7 #include <stdlib.h> 7 #include <string>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/string_util.h"
11 #include "net/base/net_util.h" 10 #include "net/base/net_util.h"
12 #include "net/base/sys_addrinfo.h" 11 #include "net/base/sys_addrinfo.h"
13 12
14 namespace net { 13 namespace net {
15 14
16 namespace { 15 AddressList::AddressList() {}
17 16
18 struct addrinfo* CreateAddrInfo(const IPAddressNumber& address, 17 AddressList::~AddressList() {}
19 bool canonicalize_name) {
20 struct addrinfo* ai = new addrinfo;
21 memset(ai, 0, sizeof(addrinfo));
22 ai->ai_socktype = SOCK_STREAM;
23 18
24 switch (address.size()) { 19 AddressList::AddressList(const IPEndPoint& endpoint) {
25 case kIPv4AddressSize: { 20 push_back(endpoint);
26 ai->ai_family = AF_INET;
27 const size_t sockaddr_in_size = sizeof(struct sockaddr_in);
28 ai->ai_addrlen = sockaddr_in_size;
29
30 struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(
31 new char[sockaddr_in_size]);
32 memset(addr, 0, sockaddr_in_size);
33 addr->sin_family = AF_INET;
34 #if defined(SIN6_LEN)
35 addr->sin_len = sockaddr_in_size;
36 #endif
37 memcpy(&addr->sin_addr, &address[0], kIPv4AddressSize);
eroman 2012/05/04 01:08:41 awzum how much code is getting deleted from this f
38 ai->ai_addr = reinterpret_cast<struct sockaddr*>(addr);
39 break;
40 }
41 case kIPv6AddressSize: {
42 ai->ai_family = AF_INET6;
43 const size_t sockaddr_in6_size = sizeof(struct sockaddr_in6);
44 ai->ai_addrlen = sockaddr_in6_size;
45
46 struct sockaddr_in6* addr6 = reinterpret_cast<struct sockaddr_in6*>(
47 new char[sockaddr_in6_size]);
48 memset(addr6, 0, sockaddr_in6_size);
49 addr6->sin6_family = AF_INET6;
50 #if defined(SIN6_LEN)
51 addr6->sin6_len = sockaddr_in6_size;
52 #endif
53 memcpy(&addr6->sin6_addr, &address[0], kIPv6AddressSize);
54 ai->ai_addr = reinterpret_cast<struct sockaddr*>(addr6);
55 break;
56 }
57 default: {
58 NOTREACHED() << "Bad IP address";
59 break;
60 }
61 }
62
63 if (canonicalize_name) {
64 std::string name = NetAddressToString(ai);
65 ai->ai_canonname = base::strdup(name.c_str());
66 }
67 return ai;
68 } 21 }
69 22
70 } // namespace 23 // static
71 24 AddressList AddressList::CreateFromIPAddress(const IPAddressNumber& address,
72 struct AddressList::Data : public base::RefCountedThreadSafe<Data> { 25 uint16 port) {
73 Data(struct addrinfo* ai, bool is_system_created); 26 return AddressList(IPEndPoint(address, port));
74
75 // This variable is const since it should NOT be mutated. Since
76 // Data is reference counted, this |head| could be shared by multiple
77 // instances of AddressList, hence we need to be careful not to mutate
78 // it from any one instance.
79 const struct addrinfo * const head;
80
81 // Indicates which free function to use for |head|.
82 bool is_system_created;
83
84 private:
85 friend class base::RefCountedThreadSafe<Data>;
86
87 ~Data();
88 };
89
90 AddressList::AddressList() {
91 }
92
93 AddressList::AddressList(const AddressList& addresslist)
94 : data_(addresslist.data_) {
95 }
96
97 AddressList::~AddressList() {
98 }
99
100 AddressList& AddressList::operator=(const AddressList& addresslist) {
101 data_ = addresslist.data_;
102 return *this;
103 } 27 }
104 28
105 // static 29 // static
106 AddressList AddressList::CreateFromIPAddressList( 30 AddressList AddressList::CreateFromIPAddressList(
107 const IPAddressList& addresses, 31 const IPAddressList& addresses,
108 const std::string& canonical_name) { 32 const std::string& canonical_name) {
109 DCHECK(!addresses.empty()); 33 AddressList list;
110 struct addrinfo* head = NULL; 34 list.set_canonical_name(canonical_name);
111 struct addrinfo* next = NULL; 35 for (IPAddressList::const_iterator iter = addresses.begin();
112 36 iter != addresses.end(); ++iter) {
113 for (IPAddressList::const_iterator it = addresses.begin(); 37 list.push_back(IPEndPoint(*iter, 0));
114 it != addresses.end(); ++it) {
115 if (head == NULL) {
116 head = next = CreateAddrInfo(*it, false);
117 if (!canonical_name.empty()) {
118 head->ai_canonname = base::strdup(canonical_name.c_str());
119 }
120 } else {
121 next->ai_next = CreateAddrInfo(*it, false);
122 next = next->ai_next;
123 }
124 } 38 }
125 39 return list;
126 return AddressList(new Data(head, false));
127 } 40 }
128 41
129 // static 42 // static
130 AddressList AddressList::CreateFromIPAddress( 43 AddressList AddressList::CreateFromAddrinfo(const struct addrinfo* head) {
131 const IPAddressNumber& address, 44 DCHECK(head);
132 uint16 port) { 45 AddressList list;
133 return CreateFromIPAddressWithCname(address, port, false); 46 if (head->ai_canonname)
47 list.set_canonical_name(std::string(head->ai_canonname));
48 for (const struct addrinfo* ai = head; ai; ai = ai->ai_next) {
49 IPEndPoint ipe;
50 // NOTE: Ignoring non-INET* families.
eroman 2012/05/04 01:08:41 Not likely an issue, but might be good to add a wa
51 if (ipe.FromSockAddr(ai->ai_addr, ai->ai_addrlen))
52 list.push_back(ipe);
53 }
54 return list;
134 } 55 }
135 56
136 // static 57 void AddressList::SetDefaultCanonicalName() {
137 AddressList AddressList::CreateFromIPAddressWithCname( 58 DCHECK(!empty());
138 const IPAddressNumber& address, 59 set_canonical_name(front().ToStringWithoutPort());
139 uint16 port,
140 bool canonicalize_name) {
141 struct addrinfo* ai = CreateAddrInfo(address, canonicalize_name);
142
143 SetPortForAllAddrinfos(ai, port);
144 return AddressList(new Data(ai, false /*is_system_created*/));
145 }
146
147
148 // static
149 AddressList AddressList::CreateByAdoptingFromSystem(struct addrinfo* head) {
150 return AddressList(new Data(head, true /*is_system_created*/));
151 }
152
153 // static
154 AddressList AddressList::CreateByCopying(const struct addrinfo* head) {
155 return AddressList(new Data(CreateCopyOfAddrinfo(head, true /*recursive*/),
156 false /*is_system_created*/));
157 }
158
159 // static
160 AddressList AddressList::CreateByCopyingFirstAddress(
161 const struct addrinfo* head) {
162 return AddressList(new Data(CreateCopyOfAddrinfo(head, false /*recursive*/),
163 false /*is_system_created*/));
164 }
165
166 // static
167 AddressList AddressList::CreateFromSockaddr(
168 const struct sockaddr* address,
169 socklen_t address_length,
170 int socket_type,
171 int protocol) {
172 // Do sanity checking on socket_type and protocol.
173 DCHECK(socket_type == SOCK_DGRAM || socket_type == SOCK_STREAM);
174 DCHECK(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP);
175
176 struct addrinfo* ai = new addrinfo;
177 memset(ai, 0, sizeof(addrinfo));
178 switch (address_length) {
179 case sizeof(struct sockaddr_in):
180 {
181 const struct sockaddr_in* sin =
182 reinterpret_cast<const struct sockaddr_in*>(address);
183 ai->ai_family = sin->sin_family;
184 DCHECK_EQ(AF_INET, ai->ai_family);
185 }
186 break;
187 case sizeof(struct sockaddr_in6):
188 {
189 const struct sockaddr_in6* sin6 =
190 reinterpret_cast<const struct sockaddr_in6*>(address);
191 ai->ai_family = sin6->sin6_family;
192 DCHECK_EQ(AF_INET6, ai->ai_family);
193 }
194 break;
195 default:
196 NOTREACHED() << "Bad IP address";
197 break;
198 }
199 ai->ai_socktype = socket_type;
200 ai->ai_protocol = protocol;
201 ai->ai_addrlen = address_length;
202 ai->ai_addr = reinterpret_cast<struct sockaddr*>(new char[address_length]);
203 memcpy(ai->ai_addr, address, address_length);
204 return AddressList(new Data(ai, false /*is_system_created*/));
205 }
206
207 void AddressList::Append(const struct addrinfo* head) {
208 DCHECK(head);
209 // Always create a copy, since the Data might be shared across instances.
210 struct addrinfo* new_head = CreateCopyOfAddrinfo(data_->head, true);
211 data_ = new Data(new_head, false /*is_system_created*/);
212
213 // Find the end of current linked list and append new data there.
214 struct addrinfo* copy_ptr = new_head;
215 while (copy_ptr->ai_next)
216 copy_ptr = copy_ptr->ai_next;
217 copy_ptr->ai_next = CreateCopyOfAddrinfo(head, true);
218
219 // Only the head of the list should have a canonname. Strip any
220 // canonical name in the appended data.
221 copy_ptr = copy_ptr->ai_next;
222 while (copy_ptr) {
223 if (copy_ptr->ai_canonname) {
224 free(copy_ptr->ai_canonname);
225 copy_ptr->ai_canonname = NULL;
226 }
227 copy_ptr = copy_ptr->ai_next;
228 }
229 }
230
231 void AddressList::SetPort(uint16 port) {
232 // NOTE: we need to be careful not to mutate the reference-counted data,
233 // since it might be shared by other AddressLists.
234 struct addrinfo* head = CreateCopyOfAddrinfo(data_->head, true);
235 SetPortForAllAddrinfos(head, port);
236 data_ = new Data(head, false /*is_system_created*/);
237 }
238
239 uint16 AddressList::GetPort() const {
240 return GetPortFromAddrinfo(data_->head);
241 }
242
243 bool AddressList::GetCanonicalName(std::string* canonical_name) const {
244 DCHECK(canonical_name);
245 if (!data_ || !data_->head->ai_canonname)
246 return false;
247 canonical_name->assign(data_->head->ai_canonname);
248 return true;
249 }
250
251 const struct addrinfo* AddressList::head() const {
252 if (!data_)
253 return NULL;
254 return data_->head;
255 }
256
257 AddressList::AddressList(Data* data) : data_(data) {}
258
259 AddressList::Data::Data(struct addrinfo* ai, bool is_system_created)
260 : head(ai), is_system_created(is_system_created) {
261 DCHECK(head);
262 }
263
264 AddressList::Data::~Data() {
265 // Casting away the const is safe, since upon destruction we know that
266 // no one holds a reference to the data any more.
267 struct addrinfo* mutable_head = const_cast<struct addrinfo*>(head);
268
269 // Call either freeaddrinfo(head), or FreeMyAddrinfo(head), depending who
270 // created the data.
271 if (is_system_created)
272 freeaddrinfo(mutable_head);
273 else
274 FreeCopyOfAddrinfo(mutable_head);
275 }
276
277 AddressList CreateAddressListUsingPort(const AddressList& src, int port) {
278 if (src.GetPort() == port)
279 return src;
280
281 AddressList out = src;
282 out.SetPort(port);
283 return out;
284 } 60 }
285 61
286 } // namespace net 62 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698