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

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

Issue 118100: Avoid doing concurrent DNS resolves of the same hostname (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Get compiling on mac Created 11 years, 6 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) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 #ifdef OS_WIN 7 #ifdef OS_WIN
8 #include <ws2tcpip.h> 8 #include <ws2tcpip.h>
9 #include <wspiapi.h> // Needed for Win2k compat. 9 #include <wspiapi.h> // Needed for Win2k compat.
10 #else 10 #else
11 #include <netdb.h> 11 #include <netdb.h>
12 #endif 12 #endif
13 13
14 #include "base/logging.h"
15
14 namespace net { 16 namespace net {
15 17
18 namespace {
19
20 // Make a deep copy of |info|. This copy should be deleted using
21 // DeleteCopyOfAddrinfo(), and NOT freeaddrinfo().
22 struct addrinfo* CreateCopyOfAddrinfo(const struct addrinfo* info) {
23 struct addrinfo* copy = new struct addrinfo;
24
25 // Copy all the fields (some of these are pointers, we will fix that next).
26 memcpy(copy, info, sizeof(addrinfo));
27
28 // ai_canonname is a NULL-terminated string.
29 if (info->ai_canonname) {
30 #ifdef OS_WIN
31 copy->ai_canonname = _strdup(info->ai_canonname);
32 #else
33 copy->ai_canonname = strdup(info->ai_canonname);
34 #endif
35 }
36
37 // ai_addr is a buffer of length ai_addrlen.
38 if (info->ai_addr) {
39 copy->ai_addr = reinterpret_cast<sockaddr *>(new char[info->ai_addrlen]);
40 memcpy(copy->ai_addr, info->ai_addr, info->ai_addrlen);
41 }
42
43 // Recursive copy.
44 if (info->ai_next)
45 copy->ai_next = CreateCopyOfAddrinfo(info->ai_next);
46
47 return copy;
48 }
49
50 // Free an addrinfo that was created by CreateCopyOfAddrinfo().
51 void FreeMyAddrinfo(struct addrinfo* info) {
52 if (info->ai_canonname)
53 free(info->ai_canonname); // Allocated by strdup.
54
55 if (info->ai_addr)
56 delete [] reinterpret_cast<char*>(info->ai_addr);
57
58 struct addrinfo* next = info->ai_next;
59
60 delete info;
61
62 // Recursive free.
63 if (next)
64 FreeMyAddrinfo(next);
65 }
66
67 // Returns the address to port field in |info|.
68 uint16* GetPortField(const struct addrinfo* info) {
69 if (info->ai_family == AF_INET) {
70 DCHECK_EQ(sizeof(sockaddr_in), info->ai_addrlen);
71 struct sockaddr_in* sockaddr =
72 reinterpret_cast<struct sockaddr_in*>(info->ai_addr);
73 return &sockaddr->sin_port;
74 } else if (info->ai_family == AF_INET6) {
75 DCHECK_EQ(sizeof(sockaddr_in6), info->ai_addrlen);
76 struct sockaddr_in6* sockaddr =
77 reinterpret_cast<struct sockaddr_in6*>(info->ai_addr);
78 return &sockaddr->sin6_port;
79 } else {
80 NOTREACHED();
81 return NULL;
82 }
83 }
84
85 // Assign the port for all addresses in the list.
86 void SetPortRecursive(struct addrinfo* info, int port) {
87 uint16* port_field = GetPortField(info);
88 *port_field = htons(port);
89
90 // Assign recursively.
91 if (info->ai_next)
92 SetPortRecursive(info->ai_next, port);
93 }
94
95 } // namespace
96
16 void AddressList::Adopt(struct addrinfo* head) { 97 void AddressList::Adopt(struct addrinfo* head) {
17 data_ = new Data(head); 98 data_ = new Data(head, true /*is_system_created*/);
99 }
100
101 void AddressList::Copy(const struct addrinfo* head) {
102 data_ = new Data(CreateCopyOfAddrinfo(head), false /*is_system_created*/);
103 }
104
105 void AddressList::SetPort(int port) {
106 SetPortRecursive(data_->head, port);
107 }
108
109 int AddressList::GetPort() const {
110 uint16* port_field = GetPortField(data_->head);
111 return ntohs(*port_field);
112 }
113
114 void AddressList::SetFrom(const AddressList& src, int port) {
115 if (src.GetPort() == port) {
116 // We can reference the data from |src| directly.
117 *this = src;
118 } else {
119 // Otherwise we need to make a copy in order to change the port number.
120 Copy(src.head());
121 SetPort(port);
122 }
123 }
124
125 void AddressList::Reset() {
126 data_ = NULL;
18 } 127 }
19 128
20 AddressList::Data::~Data() { 129 AddressList::Data::~Data() {
21 freeaddrinfo(head); 130 // Call either freeaddrinfo(head), or FreeMyAddrinfo(head), depending who
131 // created the data.
132 if (is_system_created)
133 freeaddrinfo(head);
134 else
135 FreeMyAddrinfo(head);
22 } 136 }
23 137
24 } // namespace net 138 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698