OLD | NEW |
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/host_resolver.h" | 5 #include "net/base/host_resolver.h" |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(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 #elif defined(OS_POSIX) | 10 #elif defined(OS_POSIX) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 if (mapper) { | 56 if (mapper) { |
57 rv = HostResolverProc(mapper->Map(host), port, out); | 57 rv = HostResolverProc(mapper->Map(host), port, out); |
58 } else { | 58 } else { |
59 rv = HostResolverProc(host, port, out); | 59 rv = HostResolverProc(host, port, out); |
60 } | 60 } |
61 return rv; | 61 return rv; |
62 } | 62 } |
63 | 63 |
64 //----------------------------------------------------------------------------- | 64 //----------------------------------------------------------------------------- |
65 | 65 |
66 class HostResolver::Request : | 66 class HostResolver::Request |
67 public base::RefCountedThreadSafe<HostResolver::Request> { | 67 : public base::RefCountedThreadSafe<HostResolver::Request>, |
| 68 public MessageLoop::DestructionObserver { |
68 public: | 69 public: |
69 Request(HostResolver* resolver, | 70 Request(HostResolver* resolver, |
70 const std::string& host, | 71 const std::string& host, |
71 const std::string& port, | 72 const std::string& port, |
72 AddressList* addresses, | 73 AddressList* addresses, |
73 CompletionCallback* callback) | 74 CompletionCallback* callback) |
74 : host_(host), | 75 : host_(host), |
75 port_(port), | 76 port_(port), |
76 resolver_(resolver), | 77 resolver_(resolver), |
77 addresses_(addresses), | 78 addresses_(addresses), |
78 callback_(callback), | 79 callback_(callback), |
79 origin_loop_(MessageLoop::current()), | 80 origin_loop_(MessageLoop::current()), |
80 host_mapper_(host_mapper), | 81 host_mapper_(host_mapper), |
81 error_(OK), | 82 error_(OK), |
82 results_(NULL) { | 83 results_(NULL) { |
| 84 MessageLoop::current()->AddDestructionObserver(this); |
83 } | 85 } |
84 | 86 |
85 ~Request() { | 87 virtual ~Request() { |
86 if (results_) | 88 if (results_) |
87 freeaddrinfo(results_); | 89 freeaddrinfo(results_); |
88 } | 90 } |
89 | 91 |
90 void DoLookup() { | 92 void DoLookup() { |
91 // Running on the worker thread | 93 // Running on the worker thread |
92 error_ = ResolveAddrInfo(host_mapper_, host_, port_, &results_); | 94 error_ = ResolveAddrInfo(host_mapper_, host_, port_, &results_); |
93 | 95 |
94 Task* reply = NewRunnableMethod(this, &Request::DoCallback); | 96 Task* reply = NewRunnableMethod(this, &Request::DoCallback); |
95 | 97 |
96 // The origin loop could go away while we are trying to post to it, so we | 98 // The origin loop could go away while we are trying to post to it, so we |
97 // need to call its PostTask method inside a lock. See ~HostResolver. | 99 // need to call its PostTask method inside a lock. See ~HostResolver. |
98 { | 100 { |
99 AutoLock locked(origin_loop_lock_); | 101 AutoLock locked(origin_loop_lock_); |
100 if (origin_loop_) { | 102 if (origin_loop_) { |
101 origin_loop_->PostTask(FROM_HERE, reply); | 103 origin_loop_->PostTask(FROM_HERE, reply); |
102 reply = NULL; | 104 reply = NULL; |
103 } | 105 } |
104 } | 106 } |
105 | 107 |
106 // Does nothing if it got posted. | 108 // Does nothing if it got posted. |
107 delete reply; | 109 delete reply; |
108 } | 110 } |
109 | 111 |
110 void DoCallback() { | 112 void DoCallback() { |
111 // Running on the origin thread. | 113 // Running on the origin thread. |
112 DCHECK(error_ || results_); | 114 DCHECK(error_ || results_); |
113 | 115 |
| 116 { |
| 117 AutoLock locked(origin_loop_lock_); |
| 118 if (origin_loop_) |
| 119 origin_loop_->RemoveDestructionObserver(this); |
| 120 } |
| 121 |
114 // We may have been cancelled! | 122 // We may have been cancelled! |
115 if (!resolver_) | 123 if (!resolver_) |
116 return; | 124 return; |
117 | 125 |
118 if (!error_) { | 126 if (!error_) { |
119 addresses_->Adopt(results_); | 127 addresses_->Adopt(results_); |
120 results_ = NULL; | 128 results_ = NULL; |
121 } | 129 } |
122 | 130 |
123 // Drop the resolver's reference to us. Do this before running the | 131 // Drop the resolver's reference to us. Do this before running the |
124 // callback since the callback might result in the resolver being | 132 // callback since the callback might result in the resolver being |
125 // destroyed. | 133 // destroyed. |
126 resolver_->request_ = NULL; | 134 resolver_->request_ = NULL; |
127 | 135 |
128 callback_->Run(error_); | 136 callback_->Run(error_); |
129 } | 137 } |
130 | 138 |
131 void Cancel() { | 139 void Cancel() { |
132 resolver_ = NULL; | 140 resolver_ = NULL; |
133 | 141 |
134 AutoLock locked(origin_loop_lock_); | 142 AutoLock locked(origin_loop_lock_); |
135 origin_loop_ = NULL; | 143 origin_loop_ = NULL; |
136 } | 144 } |
137 | 145 |
| 146 virtual void WillDestroyCurrentMessageLoop() { |
| 147 AutoLock locked(origin_loop_lock_); |
| 148 origin_loop_ = NULL; |
| 149 } |
| 150 |
138 private: | 151 private: |
139 // Set on the origin thread, read on the worker thread. | 152 // Set on the origin thread, read on the worker thread. |
140 std::string host_; | 153 std::string host_; |
141 std::string port_; | 154 std::string port_; |
142 | 155 |
143 // Only used on the origin thread (where Resolve was called). | 156 // Only used on the origin thread (where Resolve was called). |
144 HostResolver* resolver_; | 157 HostResolver* resolver_; |
145 AddressList* addresses_; | 158 AddressList* addresses_; |
146 CompletionCallback* callback_; | 159 CompletionCallback* callback_; |
147 | 160 |
(...skipping 14 matching lines...) Expand all Loading... |
162 | 175 |
163 //----------------------------------------------------------------------------- | 176 //----------------------------------------------------------------------------- |
164 | 177 |
165 HostResolver::HostResolver() { | 178 HostResolver::HostResolver() { |
166 #if defined(OS_WIN) | 179 #if defined(OS_WIN) |
167 EnsureWinsockInit(); | 180 EnsureWinsockInit(); |
168 #endif | 181 #endif |
169 } | 182 } |
170 | 183 |
171 HostResolver::~HostResolver() { | 184 HostResolver::~HostResolver() { |
172 if (request_) | 185 if (request_) { |
173 request_->Cancel(); | 186 request_->Cancel(); |
| 187 MessageLoop::current()->RemoveDestructionObserver(request_.get()); |
| 188 } |
174 } | 189 } |
175 | 190 |
176 int HostResolver::Resolve(const std::string& hostname, int port, | 191 int HostResolver::Resolve(const std::string& hostname, int port, |
177 AddressList* addresses, | 192 AddressList* addresses, |
178 CompletionCallback* callback) { | 193 CompletionCallback* callback) { |
179 DCHECK(!request_) << "resolver already in use"; | 194 DCHECK(!request_) << "resolver already in use"; |
180 | 195 |
181 const std::string& port_str = IntToString(port); | 196 const std::string& port_str = IntToString(port); |
182 | 197 |
183 // Do a synchronous resolution. | 198 // Do a synchronous resolution. |
184 if (!callback) { | 199 if (!callback) { |
185 struct addrinfo* results; | 200 struct addrinfo* results; |
186 int rv = ResolveAddrInfo(host_mapper, hostname, port_str, &results); | 201 int rv = ResolveAddrInfo(host_mapper, hostname, port_str, &results); |
187 if (rv == OK) | 202 if (rv == OK) |
188 addresses->Adopt(results); | 203 addresses->Adopt(results); |
189 return rv; | 204 return rv; |
190 } | 205 } |
191 | 206 |
192 request_ = new Request(this, hostname, port_str, addresses, callback); | 207 request_ = new Request(this, hostname, port_str, addresses, callback); |
193 | 208 |
194 // Dispatch to worker thread... | 209 // Dispatch to worker thread... |
195 if (!WorkerPool::PostTask(FROM_HERE, | 210 if (!WorkerPool::PostTask(FROM_HERE, |
196 NewRunnableMethod(request_.get(), &Request::DoLookup), true)) { | 211 NewRunnableMethod(request_.get(), &Request::DoLookup), true)) { |
197 NOTREACHED(); | 212 NOTREACHED(); |
| 213 MessageLoop::current()->RemoveDestructionObserver(request_.get()); |
198 request_ = NULL; | 214 request_ = NULL; |
199 return ERR_FAILED; | 215 return ERR_FAILED; |
200 } | 216 } |
201 | 217 |
202 return ERR_IO_PENDING; | 218 return ERR_IO_PENDING; |
203 } | 219 } |
204 | 220 |
205 } // namespace net | 221 } // namespace net |
OLD | NEW |