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

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

Issue 556068: BSD port: USE_NSS and other macros instead of OS_LINUX where applicable (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 11 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/host_resolver_proc.h" 5 #include "net/base/host_resolver_proc.h"
6 6
7 #include "build/build_config.h" 7 #include "build/build_config.h"
8 8
9 #if defined(OS_LINUX) 9 #if defined(OS_POSIX) && !defined(OS_MACOSX)
10 #include <resolv.h> 10 #include <resolv.h>
11 #endif 11 #endif
12 12
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/time.h" 14 #include "base/time.h"
15 #include "net/base/address_list.h" 15 #include "net/base/address_list.h"
16 #include "net/base/net_errors.h" 16 #include "net/base/net_errors.h"
17 #include "net/base/sys_addrinfo.h" 17 #include "net/base/sys_addrinfo.h"
18 18
19 #if defined(OS_LINUX) 19 #if defined(OS_POSIX) && !defined(OS_MACOSX)
20 #include "base/singleton.h" 20 #include "base/singleton.h"
21 #include "base/thread_local_storage.h" 21 #include "base/thread_local_storage.h"
22 #endif 22 #endif
23 23
24 namespace net { 24 namespace net {
25 25
26 HostResolverProc* HostResolverProc::default_proc_ = NULL; 26 HostResolverProc* HostResolverProc::default_proc_ = NULL;
27 27
28 HostResolverProc::HostResolverProc(HostResolverProc* previous) { 28 HostResolverProc::HostResolverProc(HostResolverProc* previous) {
29 SetPreviousProc(previous); 29 SetPreviousProc(previous);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 int HostResolverProc::ResolveUsingPrevious(const std::string& host, 70 int HostResolverProc::ResolveUsingPrevious(const std::string& host,
71 AddressFamily address_family, 71 AddressFamily address_family,
72 AddressList* addrlist) { 72 AddressList* addrlist) {
73 if (previous_proc_) 73 if (previous_proc_)
74 return previous_proc_->Resolve(host, address_family, addrlist); 74 return previous_proc_->Resolve(host, address_family, addrlist);
75 75
76 // Final fallback is the system resolver. 76 // Final fallback is the system resolver.
77 return SystemHostResolverProc(host, address_family, addrlist); 77 return SystemHostResolverProc(host, address_family, addrlist);
78 } 78 }
79 79
80 #if defined(OS_LINUX) 80 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
81 // On Linux changes to /etc/resolv.conf can go unnoticed thus resulting in 81 // On Linux/BSD, changes to /etc/resolv.conf can go unnoticed thus resulting
82 // DNS queries failing either because nameservers are unknown on startup 82 // in DNS queries failing either because nameservers are unknown on startup
83 // or because nameserver info has changed as a result of e.g. connecting to 83 // or because nameserver info has changed as a result of e.g. connecting to
84 // a new network. Some distributions patch glibc to stat /etc/resolv.conf 84 // a new network. Some distributions patch glibc to stat /etc/resolv.conf
85 // to try to automatically detect such changes but these patches are not 85 // to try to automatically detect such changes but these patches are not
86 // universal and even patched systems such as Jaunty appear to need calls 86 // universal and even patched systems such as Jaunty appear to need calls
87 // to res_ninit to reload the nameserver information in different threads. 87 // to res_ninit to reload the nameserver information in different threads.
88 // 88 //
89 // We adopt the Mozilla solution here which is to call res_ninit when 89 // We adopt the Mozilla solution here which is to call res_ninit when
90 // lookups fail and to rate limit the reloading to once per second per 90 // lookups fail and to rate limit the reloading to once per second per
91 // thread. 91 // thread.
92 //
93 // OpenBSD does not have thread-safe res_ninit/res_nclose so we can't do
94 // the same trick there.
92 95
93 // Keep a timer per calling thread to rate limit the calling of res_ninit. 96 // Keep a timer per calling thread to rate limit the calling of res_ninit.
94 class DnsReloadTimer { 97 class DnsReloadTimer {
95 public: 98 public:
96 // Check if the timer for the calling thread has expired. When no 99 // Check if the timer for the calling thread has expired. When no
97 // timer exists for the calling thread, create one. 100 // timer exists for the calling thread, create one.
98 bool Expired() { 101 bool Expired() {
99 const base::TimeDelta kRetryTime = base::TimeDelta::FromSeconds(1); 102 const base::TimeDelta kRetryTime = base::TimeDelta::FromSeconds(1);
100 base::TimeTicks now = base::TimeTicks::Now(); 103 base::TimeTicks now = base::TimeTicks::Now();
101 base::TimeTicks* timer_ptr = 104 base::TimeTicks* timer_ptr =
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 // interact with. 141 // interact with.
139 static ThreadLocalStorage::Slot tls_index_ ; 142 static ThreadLocalStorage::Slot tls_index_ ;
140 143
141 DISALLOW_COPY_AND_ASSIGN(DnsReloadTimer); 144 DISALLOW_COPY_AND_ASSIGN(DnsReloadTimer);
142 }; 145 };
143 146
144 // A TLS slot to the TimeTicks for the current thread. 147 // A TLS slot to the TimeTicks for the current thread.
145 // static 148 // static
146 ThreadLocalStorage::Slot DnsReloadTimer::tls_index_(base::LINKER_INITIALIZED); 149 ThreadLocalStorage::Slot DnsReloadTimer::tls_index_(base::LINKER_INITIALIZED);
147 150
148 #endif // defined(OS_LINUX) 151 #endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
149 152
150 int SystemHostResolverProc(const std::string& host, 153 int SystemHostResolverProc(const std::string& host,
151 AddressFamily address_family, 154 AddressFamily address_family,
152 AddressList* addrlist) { 155 AddressList* addrlist) {
153 // The result of |getaddrinfo| for empty hosts is inconsistent across systems. 156 // The result of |getaddrinfo| for empty hosts is inconsistent across systems.
154 // On Windows it gives the default interface's address, whereas on Linux it 157 // On Windows it gives the default interface's address, whereas on Linux it
155 // gives an error. We will make it fail on all platforms for consistency. 158 // gives an error. We will make it fail on all platforms for consistency.
156 if (host.empty()) 159 if (host.empty())
157 return ERR_NAME_NOT_RESOLVED; 160 return ERR_NAME_NOT_RESOLVED;
158 161
159 struct addrinfo* ai = NULL; 162 struct addrinfo* ai = NULL;
160 struct addrinfo hints = {0}; 163 struct addrinfo hints = {0};
161 164
162 switch (address_family) { 165 switch (address_family) {
163 case ADDRESS_FAMILY_IPV4: 166 case ADDRESS_FAMILY_IPV4:
164 hints.ai_family = AF_INET; 167 hints.ai_family = AF_INET;
165 break; 168 break;
166 case ADDRESS_FAMILY_IPV6: 169 case ADDRESS_FAMILY_IPV6:
167 hints.ai_family = AF_INET6; 170 hints.ai_family = AF_INET6;
168 break; 171 break;
169 case ADDRESS_FAMILY_UNSPECIFIED: 172 case ADDRESS_FAMILY_UNSPECIFIED:
170 hints.ai_family = AF_UNSPEC; 173 hints.ai_family = AF_UNSPEC;
171 break; 174 break;
172 default: 175 default:
173 NOTREACHED(); 176 NOTREACHED();
174 hints.ai_family = AF_UNSPEC; 177 hints.ai_family = AF_UNSPEC;
175 } 178 }
176 179
177 #if defined(OS_WIN) 180 #if defined(OS_WIN) || defined(OS_OPENBSD)
178 // DO NOT USE AI_ADDRCONFIG ON WINDOWS. 181 // DO NOT USE AI_ADDRCONFIG ON WINDOWS.
179 // 182 //
180 // The following comment in <winsock2.h> is the best documentation I found 183 // The following comment in <winsock2.h> is the best documentation I found
181 // on AI_ADDRCONFIG for Windows: 184 // on AI_ADDRCONFIG for Windows:
182 // Flags used in "hints" argument to getaddrinfo() 185 // Flags used in "hints" argument to getaddrinfo()
183 // - AI_ADDRCONFIG is supported starting with Vista 186 // - AI_ADDRCONFIG is supported starting with Vista
184 // - default is AI_ADDRCONFIG ON whether the flag is set or not 187 // - default is AI_ADDRCONFIG ON whether the flag is set or not
185 // because the performance penalty in not having ADDRCONFIG in 188 // because the performance penalty in not having ADDRCONFIG in
186 // the multi-protocol stack environment is severe; 189 // the multi-protocol stack environment is severe;
187 // this defaulting may be disabled by specifying the AI_ALL flag, 190 // this defaulting may be disabled by specifying the AI_ALL flag,
188 // in that case AI_ADDRCONFIG must be EXPLICITLY specified to 191 // in that case AI_ADDRCONFIG must be EXPLICITLY specified to
189 // enable ADDRCONFIG behavior 192 // enable ADDRCONFIG behavior
190 // 193 //
191 // Not only is AI_ADDRCONFIG unnecessary, but it can be harmful. If the 194 // Not only is AI_ADDRCONFIG unnecessary, but it can be harmful. If the
192 // computer is not connected to a network, AI_ADDRCONFIG causes getaddrinfo 195 // computer is not connected to a network, AI_ADDRCONFIG causes getaddrinfo
193 // to fail with WSANO_DATA (11004) for "localhost", probably because of the 196 // to fail with WSANO_DATA (11004) for "localhost", probably because of the
194 // following note on AI_ADDRCONFIG in the MSDN getaddrinfo page: 197 // following note on AI_ADDRCONFIG in the MSDN getaddrinfo page:
195 // The IPv4 or IPv6 loopback address is not considered a valid global 198 // The IPv4 or IPv6 loopback address is not considered a valid global
196 // address. 199 // address.
197 // See http://crbug.com/5234. 200 // See http://crbug.com/5234.
201 //
202 // OpenBSD does not support it, either.
198 hints.ai_flags = 0; 203 hints.ai_flags = 0;
199 #else 204 #else
200 hints.ai_flags = AI_ADDRCONFIG; 205 hints.ai_flags = AI_ADDRCONFIG;
201 #endif 206 #endif
202 207
203 // Restrict result set to only this socket type to avoid duplicates. 208 // Restrict result set to only this socket type to avoid duplicates.
204 hints.ai_socktype = SOCK_STREAM; 209 hints.ai_socktype = SOCK_STREAM;
205 210
206 int err = getaddrinfo(host.c_str(), NULL, &hints, &ai); 211 int err = getaddrinfo(host.c_str(), NULL, &hints, &ai);
207 #if defined(OS_LINUX) 212 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
208 net::DnsReloadTimer* dns_timer = Singleton<net::DnsReloadTimer>::get(); 213 net::DnsReloadTimer* dns_timer = Singleton<net::DnsReloadTimer>::get();
209 // If we fail, re-initialise the resolver just in case there have been any 214 // If we fail, re-initialise the resolver just in case there have been any
210 // changes to /etc/resolv.conf and retry. See http://crbug.com/11380 for info. 215 // changes to /etc/resolv.conf and retry. See http://crbug.com/11380 for info.
211 if (err && dns_timer->Expired()) { 216 if (err && dns_timer->Expired()) {
212 res_nclose(&_res); 217 res_nclose(&_res);
213 if (!res_ninit(&_res)) 218 if (!res_ninit(&_res))
214 err = getaddrinfo(host.c_str(), NULL, &hints, &ai); 219 err = getaddrinfo(host.c_str(), NULL, &hints, &ai);
215 } 220 }
216 #endif 221 #endif
217 222
218 if (err) 223 if (err)
219 return ERR_NAME_NOT_RESOLVED; 224 return ERR_NAME_NOT_RESOLVED;
220 225
221 addrlist->Adopt(ai); 226 addrlist->Adopt(ai);
222 return OK; 227 return OK;
223 } 228 }
224 229
225 } // namespace net 230 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698