OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/dns/mdns_client_impl.h" | 5 #include "net/dns/mdns_client_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop/message_loop_proxy.h" | 8 #include "base/message_loop/message_loop_proxy.h" |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/time/default_clock.h" | 10 #include "base/time/default_clock.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 | 92 |
93 void MDnsConnection::SocketHandler::OnDatagramReceived(int rv) { | 93 void MDnsConnection::SocketHandler::OnDatagramReceived(int rv) { |
94 if (rv >= OK) | 94 if (rv >= OK) |
95 rv = DoLoop(rv); | 95 rv = DoLoop(rv); |
96 | 96 |
97 if (rv != OK) | 97 if (rv != OK) |
98 connection_->OnError(this, rv); | 98 connection_->OnError(this, rv); |
99 } | 99 } |
100 | 100 |
101 int MDnsConnection::SocketHandler::Send(IOBuffer* buffer, unsigned size) { | 101 int MDnsConnection::SocketHandler::Send(IOBuffer* buffer, unsigned size) { |
102 return socket_->SendTo(buffer, size, multicast_addr_, | 102 return socket_->SendTo(buffer, |
| 103 size, |
| 104 multicast_addr_, |
103 base::Bind(&MDnsConnection::SocketHandler::SendDone, | 105 base::Bind(&MDnsConnection::SocketHandler::SendDone, |
104 base::Unretained(this) )); | 106 base::Unretained(this))); |
105 } | 107 } |
106 | 108 |
107 void MDnsConnection::SocketHandler::SendDone(int rv) { | 109 void MDnsConnection::SocketHandler::SendDone(int rv) { |
108 // TODO(noamsml): Retry logic. | 110 // TODO(noamsml): Retry logic. |
109 } | 111 } |
110 | 112 |
111 MDnsConnection::MDnsConnection(MDnsConnection::Delegate* delegate) : | 113 MDnsConnection::MDnsConnection(MDnsConnection::Delegate* delegate) |
112 delegate_(delegate) { | 114 : delegate_(delegate) { |
113 } | 115 } |
114 | 116 |
115 MDnsConnection::~MDnsConnection() { | 117 MDnsConnection::~MDnsConnection() { |
116 } | 118 } |
117 | 119 |
118 bool MDnsConnection::Init(MDnsSocketFactory* socket_factory) { | 120 bool MDnsConnection::Init(MDnsSocketFactory* socket_factory) { |
119 ScopedVector<DatagramServerSocket> sockets; | 121 ScopedVector<DatagramServerSocket> sockets; |
120 socket_factory->CreateSockets(&sockets); | 122 socket_factory->CreateSockets(&sockets); |
121 | 123 |
122 for (size_t i = 0; i < sockets.size(); ++i) { | 124 for (size_t i = 0; i < sockets.size(); ++i) { |
(...skipping 24 matching lines...) Expand all Loading... |
147 int rv = socket_handlers_[i]->Send(buffer, size); | 149 int rv = socket_handlers_[i]->Send(buffer, size); |
148 if (rv >= OK || rv == ERR_IO_PENDING) { | 150 if (rv >= OK || rv == ERR_IO_PENDING) { |
149 success = true; | 151 success = true; |
150 } else { | 152 } else { |
151 VLOG(1) << "Send failed, socket=" << i << ", error=" << rv; | 153 VLOG(1) << "Send failed, socket=" << i << ", error=" << rv; |
152 } | 154 } |
153 } | 155 } |
154 return success; | 156 return success; |
155 } | 157 } |
156 | 158 |
157 void MDnsConnection::OnError(SocketHandler* loop, | 159 void MDnsConnection::OnError(SocketHandler* loop, int error) { |
158 int error) { | |
159 // TODO(noamsml): Specific handling of intermittent errors that can be handled | 160 // TODO(noamsml): Specific handling of intermittent errors that can be handled |
160 // in the connection. | 161 // in the connection. |
161 delegate_->OnConnectionError(error); | 162 delegate_->OnConnectionError(error); |
162 } | 163 } |
163 | 164 |
164 void MDnsConnection::OnDatagramReceived( | 165 void MDnsConnection::OnDatagramReceived(DnsResponse* response, |
165 DnsResponse* response, | 166 const IPEndPoint& recv_addr, |
166 const IPEndPoint& recv_addr, | 167 int bytes_read) { |
167 int bytes_read) { | |
168 // TODO(noamsml): More sophisticated error handling. | 168 // TODO(noamsml): More sophisticated error handling. |
169 DCHECK_GT(bytes_read, 0); | 169 DCHECK_GT(bytes_read, 0); |
170 delegate_->HandlePacket(response, bytes_read); | 170 delegate_->HandlePacket(response, bytes_read); |
171 } | 171 } |
172 | 172 |
173 MDnsClientImpl::Core::Core(MDnsClientImpl* client) | 173 MDnsClientImpl::Core::Core(MDnsClientImpl* client) |
174 : client_(client), connection_(new MDnsConnection(this)) { | 174 : client_(client), connection_(new MDnsConnection(this)) { |
175 } | 175 } |
176 | 176 |
177 MDnsClientImpl::Core::~Core() { | 177 MDnsClientImpl::Core::~Core() { |
178 STLDeleteValues(&listeners_); | 178 STLDeleteValues(&listeners_); |
179 } | 179 } |
180 | 180 |
181 bool MDnsClientImpl::Core::Init(MDnsSocketFactory* socket_factory) { | 181 bool MDnsClientImpl::Core::Init(MDnsSocketFactory* socket_factory) { |
182 return connection_->Init(socket_factory); | 182 return connection_->Init(socket_factory); |
183 } | 183 } |
184 | 184 |
185 bool MDnsClientImpl::Core::SendQuery(uint16 rrtype, std::string name) { | 185 bool MDnsClientImpl::Core::SendQuery(uint16 rrtype, std::string name) { |
186 std::string name_dns; | 186 std::string name_dns; |
187 if (!DNSDomainFromDot(name, &name_dns)) | 187 if (!DNSDomainFromDot(name, &name_dns)) |
188 return false; | 188 return false; |
189 | 189 |
190 DnsQuery query(0, name_dns, rrtype); | 190 DnsQuery query(0, name_dns, rrtype); |
191 query.set_flags(0); // Remove the RD flag from the query. It is unneeded. | 191 query.set_flags(0); // Remove the RD flag from the query. It is unneeded. |
192 | 192 |
193 return connection_->Send(query.io_buffer(), query.io_buffer()->size()); | 193 return connection_->Send(query.io_buffer(), query.io_buffer()->size()); |
194 } | 194 } |
195 | 195 |
196 void MDnsClientImpl::Core::HandlePacket(DnsResponse* response, | 196 void MDnsClientImpl::Core::HandlePacket(DnsResponse* response, int bytes_read) { |
197 int bytes_read) { | |
198 unsigned offset; | 197 unsigned offset; |
199 // Note: We store cache keys rather than record pointers to avoid | 198 // Note: We store cache keys rather than record pointers to avoid |
200 // erroneous behavior in case a packet contains multiple exclusive | 199 // erroneous behavior in case a packet contains multiple exclusive |
201 // records with the same type and name. | 200 // records with the same type and name. |
202 std::map<MDnsCache::Key, MDnsCache::UpdateType> update_keys; | 201 std::map<MDnsCache::Key, MDnsCache::UpdateType> update_keys; |
203 | 202 |
204 if (!response->InitParseWithoutQuery(bytes_read)) { | 203 if (!response->InitParseWithoutQuery(bytes_read)) { |
205 DVLOG(1) << "Could not understand an mDNS packet."; | 204 DVLOG(1) << "Could not understand an mDNS packet."; |
206 return; // Message is unreadable. | 205 return; // Message is unreadable. |
207 } | 206 } |
208 | 207 |
209 // TODO(noamsml): duplicate query suppression. | 208 // TODO(noamsml): duplicate query suppression. |
210 if (!(response->flags() & dns_protocol::kFlagResponse)) | 209 if (!(response->flags() & dns_protocol::kFlagResponse)) |
211 return; // Message is a query. ignore it. | 210 return; // Message is a query. ignore it. |
212 | 211 |
213 DnsRecordParser parser = response->Parser(); | 212 DnsRecordParser parser = response->Parser(); |
214 unsigned answer_count = response->answer_count() + | 213 unsigned answer_count = |
215 response->additional_answer_count(); | 214 response->answer_count() + response->additional_answer_count(); |
216 | 215 |
217 for (unsigned i = 0; i < answer_count; i++) { | 216 for (unsigned i = 0; i < answer_count; i++) { |
218 offset = parser.GetOffset(); | 217 offset = parser.GetOffset(); |
219 scoped_ptr<const RecordParsed> record = RecordParsed::CreateFrom( | 218 scoped_ptr<const RecordParsed> record = |
220 &parser, base::Time::Now()); | 219 RecordParsed::CreateFrom(&parser, base::Time::Now()); |
221 | 220 |
222 if (!record) { | 221 if (!record) { |
223 DVLOG(1) << "Could not understand an mDNS record."; | 222 DVLOG(1) << "Could not understand an mDNS record."; |
224 | 223 |
225 if (offset == parser.GetOffset()) { | 224 if (offset == parser.GetOffset()) { |
226 DVLOG(1) << "Abandoned parsing the rest of the packet."; | 225 DVLOG(1) << "Abandoned parsing the rest of the packet."; |
227 return; // The parser did not advance, abort reading the packet. | 226 return; // The parser did not advance, abort reading the packet. |
228 } else { | 227 } else { |
229 continue; // We may be able to extract other records from the packet. | 228 continue; // We may be able to extract other records from the packet. |
230 } | 229 } |
231 } | 230 } |
232 | 231 |
233 if ((record->klass() & dns_protocol::kMDnsClassMask) != | 232 if ((record->klass() & dns_protocol::kMDnsClassMask) != |
234 dns_protocol::kClassIN) { | 233 dns_protocol::kClassIN) { |
235 DVLOG(1) << "Received an mDNS record with non-IN class. Ignoring."; | 234 DVLOG(1) << "Received an mDNS record with non-IN class. Ignoring."; |
236 continue; // Ignore all records not in the IN class. | 235 continue; // Ignore all records not in the IN class. |
237 } | 236 } |
238 | 237 |
239 MDnsCache::Key update_key = MDnsCache::Key::CreateFor(record.get()); | 238 MDnsCache::Key update_key = MDnsCache::Key::CreateFor(record.get()); |
240 MDnsCache::UpdateType update = cache_.UpdateDnsRecord(record.Pass()); | 239 MDnsCache::UpdateType update = cache_.UpdateDnsRecord(record.Pass()); |
241 | 240 |
242 // Cleanup time may have changed. | 241 // Cleanup time may have changed. |
243 ScheduleCleanup(cache_.next_expiration()); | 242 ScheduleCleanup(cache_.next_expiration()); |
244 | 243 |
245 update_keys.insert(std::make_pair(update_key, update)); | 244 update_keys.insert(std::make_pair(update_key, update)); |
246 } | 245 } |
247 | 246 |
248 for (std::map<MDnsCache::Key, MDnsCache::UpdateType>::iterator i = | 247 for (std::map<MDnsCache::Key, MDnsCache::UpdateType>::iterator i = |
249 update_keys.begin(); i != update_keys.end(); i++) { | 248 update_keys.begin(); |
| 249 i != update_keys.end(); |
| 250 i++) { |
250 const RecordParsed* record = cache_.LookupKey(i->first); | 251 const RecordParsed* record = cache_.LookupKey(i->first); |
251 if (!record) | 252 if (!record) |
252 continue; | 253 continue; |
253 | 254 |
254 if (record->type() == dns_protocol::kTypeNSEC) { | 255 if (record->type() == dns_protocol::kTypeNSEC) { |
255 #if defined(ENABLE_NSEC) | 256 #if defined(ENABLE_NSEC) |
256 NotifyNsecRecord(record); | 257 NotifyNsecRecord(record); |
257 #endif | 258 #endif |
258 } else { | 259 } else { |
259 AlertListeners(i->second, ListenerKey(record->name(), record->type()), | 260 AlertListeners( |
260 record); | 261 i->second, ListenerKey(record->name(), record->type()), record); |
261 } | 262 } |
262 } | 263 } |
263 } | 264 } |
264 | 265 |
265 void MDnsClientImpl::Core::NotifyNsecRecord(const RecordParsed* record) { | 266 void MDnsClientImpl::Core::NotifyNsecRecord(const RecordParsed* record) { |
266 DCHECK_EQ(dns_protocol::kTypeNSEC, record->type()); | 267 DCHECK_EQ(dns_protocol::kTypeNSEC, record->type()); |
267 const NsecRecordRdata* rdata = record->rdata<NsecRecordRdata>(); | 268 const NsecRecordRdata* rdata = record->rdata<NsecRecordRdata>(); |
268 DCHECK(rdata); | 269 DCHECK(rdata); |
269 | 270 |
270 // Remove all cached records matching the nonexistent RR types. | 271 // Remove all cached records matching the nonexistent RR types. |
271 std::vector<const RecordParsed*> records_to_remove; | 272 std::vector<const RecordParsed*> records_to_remove; |
272 | 273 |
273 cache_.FindDnsRecords(0, record->name(), &records_to_remove, | 274 cache_.FindDnsRecords( |
274 base::Time::Now()); | 275 0, record->name(), &records_to_remove, base::Time::Now()); |
275 | 276 |
276 for (std::vector<const RecordParsed*>::iterator i = records_to_remove.begin(); | 277 for (std::vector<const RecordParsed*>::iterator i = records_to_remove.begin(); |
277 i != records_to_remove.end(); i++) { | 278 i != records_to_remove.end(); |
| 279 i++) { |
278 if ((*i)->type() == dns_protocol::kTypeNSEC) | 280 if ((*i)->type() == dns_protocol::kTypeNSEC) |
279 continue; | 281 continue; |
280 if (!rdata->GetBit((*i)->type())) { | 282 if (!rdata->GetBit((*i)->type())) { |
281 scoped_ptr<const RecordParsed> record_removed = cache_.RemoveRecord((*i)); | 283 scoped_ptr<const RecordParsed> record_removed = cache_.RemoveRecord((*i)); |
282 DCHECK(record_removed); | 284 DCHECK(record_removed); |
283 OnRecordRemoved(record_removed.get()); | 285 OnRecordRemoved(record_removed.get()); |
284 } | 286 } |
285 } | 287 } |
286 | 288 |
287 // Alert all listeners waiting for the nonexistent RR types. | 289 // Alert all listeners waiting for the nonexistent RR types. |
288 ListenerMap::iterator i = | 290 ListenerMap::iterator i = |
289 listeners_.upper_bound(ListenerKey(record->name(), 0)); | 291 listeners_.upper_bound(ListenerKey(record->name(), 0)); |
290 for (; i != listeners_.end() && i->first.first == record->name(); i++) { | 292 for (; i != listeners_.end() && i->first.first == record->name(); i++) { |
291 if (!rdata->GetBit(i->first.second)) { | 293 if (!rdata->GetBit(i->first.second)) { |
292 FOR_EACH_OBSERVER(MDnsListenerImpl, *i->second, AlertNsecRecord()); | 294 FOR_EACH_OBSERVER(MDnsListenerImpl, *i->second, AlertNsecRecord()); |
293 } | 295 } |
294 } | 296 } |
295 } | 297 } |
296 | 298 |
297 void MDnsClientImpl::Core::OnConnectionError(int error) { | 299 void MDnsClientImpl::Core::OnConnectionError(int error) { |
298 // TODO(noamsml): On connection error, recreate connection and flush cache. | 300 // TODO(noamsml): On connection error, recreate connection and flush cache. |
299 } | 301 } |
300 | 302 |
301 void MDnsClientImpl::Core::AlertListeners( | 303 void MDnsClientImpl::Core::AlertListeners(MDnsCache::UpdateType update_type, |
302 MDnsCache::UpdateType update_type, | 304 const ListenerKey& key, |
303 const ListenerKey& key, | 305 const RecordParsed* record) { |
304 const RecordParsed* record) { | |
305 ListenerMap::iterator listener_map_iterator = listeners_.find(key); | 306 ListenerMap::iterator listener_map_iterator = listeners_.find(key); |
306 if (listener_map_iterator == listeners_.end()) return; | 307 if (listener_map_iterator == listeners_.end()) |
| 308 return; |
307 | 309 |
308 FOR_EACH_OBSERVER(MDnsListenerImpl, *listener_map_iterator->second, | 310 FOR_EACH_OBSERVER(MDnsListenerImpl, |
| 311 *listener_map_iterator->second, |
309 HandleRecordUpdate(update_type, record)); | 312 HandleRecordUpdate(update_type, record)); |
310 } | 313 } |
311 | 314 |
312 void MDnsClientImpl::Core::AddListener( | 315 void MDnsClientImpl::Core::AddListener(MDnsListenerImpl* listener) { |
313 MDnsListenerImpl* listener) { | |
314 ListenerKey key(listener->GetName(), listener->GetType()); | 316 ListenerKey key(listener->GetName(), listener->GetType()); |
315 std::pair<ListenerMap::iterator, bool> observer_insert_result = | 317 std::pair<ListenerMap::iterator, bool> observer_insert_result = |
316 listeners_.insert( | 318 listeners_.insert( |
317 make_pair(key, static_cast<ObserverList<MDnsListenerImpl>*>(NULL))); | 319 make_pair(key, static_cast<ObserverList<MDnsListenerImpl>*>(NULL))); |
318 | 320 |
319 // If an equivalent key does not exist, actually create the observer list. | 321 // If an equivalent key does not exist, actually create the observer list. |
320 if (observer_insert_result.second) | 322 if (observer_insert_result.second) |
321 observer_insert_result.first->second = new ObserverList<MDnsListenerImpl>(); | 323 observer_insert_result.first->second = new ObserverList<MDnsListenerImpl>(); |
322 | 324 |
323 ObserverList<MDnsListenerImpl>* observer_list = | 325 ObserverList<MDnsListenerImpl>* observer_list = |
324 observer_insert_result.first->second; | 326 observer_insert_result.first->second; |
325 | 327 |
326 observer_list->AddObserver(listener); | 328 observer_list->AddObserver(listener); |
327 } | 329 } |
328 | 330 |
329 void MDnsClientImpl::Core::RemoveListener(MDnsListenerImpl* listener) { | 331 void MDnsClientImpl::Core::RemoveListener(MDnsListenerImpl* listener) { |
330 ListenerKey key(listener->GetName(), listener->GetType()); | 332 ListenerKey key(listener->GetName(), listener->GetType()); |
331 ListenerMap::iterator observer_list_iterator = listeners_.find(key); | 333 ListenerMap::iterator observer_list_iterator = listeners_.find(key); |
332 | 334 |
333 DCHECK(observer_list_iterator != listeners_.end()); | 335 DCHECK(observer_list_iterator != listeners_.end()); |
334 DCHECK(observer_list_iterator->second->HasObserver(listener)); | 336 DCHECK(observer_list_iterator->second->HasObserver(listener)); |
335 | 337 |
336 observer_list_iterator->second->RemoveObserver(listener); | 338 observer_list_iterator->second->RemoveObserver(listener); |
337 | 339 |
338 // Remove the observer list from the map if it is empty | 340 // Remove the observer list from the map if it is empty |
339 if (!observer_list_iterator->second->might_have_observers()) { | 341 if (!observer_list_iterator->second->might_have_observers()) { |
340 // Schedule the actual removal for later in case the listener removal | 342 // Schedule the actual removal for later in case the listener removal |
341 // happens while iterating over the observer list. | 343 // happens while iterating over the observer list. |
342 base::MessageLoop::current()->PostTask( | 344 base::MessageLoop::current()->PostTask( |
343 FROM_HERE, base::Bind( | 345 FROM_HERE, |
| 346 base::Bind( |
344 &MDnsClientImpl::Core::CleanupObserverList, AsWeakPtr(), key)); | 347 &MDnsClientImpl::Core::CleanupObserverList, AsWeakPtr(), key)); |
345 } | 348 } |
346 } | 349 } |
347 | 350 |
348 void MDnsClientImpl::Core::CleanupObserverList(const ListenerKey& key) { | 351 void MDnsClientImpl::Core::CleanupObserverList(const ListenerKey& key) { |
349 ListenerMap::iterator found = listeners_.find(key); | 352 ListenerMap::iterator found = listeners_.find(key); |
350 if (found != listeners_.end() && !found->second->might_have_observers()) { | 353 if (found != listeners_.end() && !found->second->might_have_observers()) { |
351 delete found->second; | 354 delete found->second; |
352 listeners_.erase(found); | 355 listeners_.erase(found); |
353 } | 356 } |
354 } | 357 } |
355 | 358 |
356 void MDnsClientImpl::Core::ScheduleCleanup(base::Time cleanup) { | 359 void MDnsClientImpl::Core::ScheduleCleanup(base::Time cleanup) { |
357 // Cleanup is already scheduled, no need to do anything. | 360 // Cleanup is already scheduled, no need to do anything. |
358 if (cleanup == scheduled_cleanup_) return; | 361 if (cleanup == scheduled_cleanup_) |
| 362 return; |
359 scheduled_cleanup_ = cleanup; | 363 scheduled_cleanup_ = cleanup; |
360 | 364 |
361 // This cancels the previously scheduled cleanup. | 365 // This cancels the previously scheduled cleanup. |
362 cleanup_callback_.Reset(base::Bind( | 366 cleanup_callback_.Reset( |
363 &MDnsClientImpl::Core::DoCleanup, base::Unretained(this))); | 367 base::Bind(&MDnsClientImpl::Core::DoCleanup, base::Unretained(this))); |
364 | 368 |
365 // If |cleanup| is empty, then no cleanup necessary. | 369 // If |cleanup| is empty, then no cleanup necessary. |
366 if (cleanup != base::Time()) { | 370 if (cleanup != base::Time()) { |
367 base::MessageLoop::current()->PostDelayedTask( | 371 base::MessageLoop::current()->PostDelayedTask( |
368 FROM_HERE, | 372 FROM_HERE, cleanup_callback_.callback(), cleanup - base::Time::Now()); |
369 cleanup_callback_.callback(), | |
370 cleanup - base::Time::Now()); | |
371 } | 373 } |
372 } | 374 } |
373 | 375 |
374 void MDnsClientImpl::Core::DoCleanup() { | 376 void MDnsClientImpl::Core::DoCleanup() { |
375 cache_.CleanupRecords(base::Time::Now(), base::Bind( | 377 cache_.CleanupRecords(base::Time::Now(), |
376 &MDnsClientImpl::Core::OnRecordRemoved, base::Unretained(this))); | 378 base::Bind(&MDnsClientImpl::Core::OnRecordRemoved, |
| 379 base::Unretained(this))); |
377 | 380 |
378 ScheduleCleanup(cache_.next_expiration()); | 381 ScheduleCleanup(cache_.next_expiration()); |
379 } | 382 } |
380 | 383 |
381 void MDnsClientImpl::Core::OnRecordRemoved( | 384 void MDnsClientImpl::Core::OnRecordRemoved(const RecordParsed* record) { |
382 const RecordParsed* record) { | |
383 AlertListeners(MDnsCache::RecordRemoved, | 385 AlertListeners(MDnsCache::RecordRemoved, |
384 ListenerKey(record->name(), record->type()), record); | 386 ListenerKey(record->name(), record->type()), |
| 387 record); |
385 } | 388 } |
386 | 389 |
387 void MDnsClientImpl::Core::QueryCache( | 390 void MDnsClientImpl::Core::QueryCache( |
388 uint16 rrtype, const std::string& name, | 391 uint16 rrtype, |
| 392 const std::string& name, |
389 std::vector<const RecordParsed*>* records) const { | 393 std::vector<const RecordParsed*>* records) const { |
390 cache_.FindDnsRecords(rrtype, name, records, base::Time::Now()); | 394 cache_.FindDnsRecords(rrtype, name, records, base::Time::Now()); |
391 } | 395 } |
392 | 396 |
393 MDnsClientImpl::MDnsClientImpl() { | 397 MDnsClientImpl::MDnsClientImpl() { |
394 } | 398 } |
395 | 399 |
396 MDnsClientImpl::~MDnsClientImpl() { | 400 MDnsClientImpl::~MDnsClientImpl() { |
397 } | 401 } |
398 | 402 |
(...skipping 25 matching lines...) Expand all Loading... |
424 | 428 |
425 scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction( | 429 scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction( |
426 uint16 rrtype, | 430 uint16 rrtype, |
427 const std::string& name, | 431 const std::string& name, |
428 int flags, | 432 int flags, |
429 const MDnsTransaction::ResultCallback& callback) { | 433 const MDnsTransaction::ResultCallback& callback) { |
430 return scoped_ptr<MDnsTransaction>( | 434 return scoped_ptr<MDnsTransaction>( |
431 new MDnsTransactionImpl(rrtype, name, flags, callback, this)); | 435 new MDnsTransactionImpl(rrtype, name, flags, callback, this)); |
432 } | 436 } |
433 | 437 |
434 MDnsListenerImpl::MDnsListenerImpl( | 438 MDnsListenerImpl::MDnsListenerImpl(uint16 rrtype, |
435 uint16 rrtype, | 439 const std::string& name, |
436 const std::string& name, | 440 MDnsListener::Delegate* delegate, |
437 MDnsListener::Delegate* delegate, | 441 MDnsClientImpl* client) |
438 MDnsClientImpl* client) | 442 : rrtype_(rrtype), |
439 : rrtype_(rrtype), name_(name), client_(client), delegate_(delegate), | 443 name_(name), |
440 started_(false), active_refresh_(false) { | 444 client_(client), |
| 445 delegate_(delegate), |
| 446 started_(false), |
| 447 active_refresh_(false) { |
441 } | 448 } |
442 | 449 |
443 MDnsListenerImpl::~MDnsListenerImpl() { | 450 MDnsListenerImpl::~MDnsListenerImpl() { |
444 if (started_) { | 451 if (started_) { |
445 DCHECK(client_->core()); | 452 DCHECK(client_->core()); |
446 client_->core()->RemoveListener(this); | 453 client_->core()->RemoveListener(this); |
447 } | 454 } |
448 } | 455 } |
449 | 456 |
450 bool MDnsListenerImpl::Start() { | 457 bool MDnsListenerImpl::Start() { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 | 531 |
525 if (!active_refresh_) | 532 if (!active_refresh_) |
526 return; | 533 return; |
527 | 534 |
528 // A zero TTL is a goodbye packet and should not be refreshed. | 535 // A zero TTL is a goodbye packet and should not be refreshed. |
529 if (ttl_ == 0) { | 536 if (ttl_ == 0) { |
530 next_refresh_.Cancel(); | 537 next_refresh_.Cancel(); |
531 return; | 538 return; |
532 } | 539 } |
533 | 540 |
534 next_refresh_.Reset(base::Bind(&MDnsListenerImpl::DoRefresh, | 541 next_refresh_.Reset(base::Bind(&MDnsListenerImpl::DoRefresh, AsWeakPtr())); |
535 AsWeakPtr())); | |
536 | 542 |
537 // Schedule refreshes at both 85% and 95% of the original TTL. These will both | 543 // Schedule refreshes at both 85% and 95% of the original TTL. These will both |
538 // be canceled and rescheduled if the record's TTL is updated due to a | 544 // be canceled and rescheduled if the record's TTL is updated due to a |
539 // response being received. | 545 // response being received. |
540 base::Time next_refresh1 = last_update_ + base::TimeDelta::FromMilliseconds( | 546 base::Time next_refresh1 = |
541 static_cast<int>(kMillisecondsPerSecond * | 547 last_update_ + |
542 kListenerRefreshRatio1 * ttl_)); | 548 base::TimeDelta::FromMilliseconds(static_cast<int>( |
| 549 kMillisecondsPerSecond * kListenerRefreshRatio1 * ttl_)); |
543 | 550 |
544 base::Time next_refresh2 = last_update_ + base::TimeDelta::FromMilliseconds( | 551 base::Time next_refresh2 = |
545 static_cast<int>(kMillisecondsPerSecond * | 552 last_update_ + |
546 kListenerRefreshRatio2 * ttl_)); | 553 base::TimeDelta::FromMilliseconds(static_cast<int>( |
| 554 kMillisecondsPerSecond * kListenerRefreshRatio2 * ttl_)); |
547 | 555 |
548 base::MessageLoop::current()->PostDelayedTask( | 556 base::MessageLoop::current()->PostDelayedTask( |
549 FROM_HERE, | 557 FROM_HERE, next_refresh_.callback(), next_refresh1 - base::Time::Now()); |
550 next_refresh_.callback(), | |
551 next_refresh1 - base::Time::Now()); | |
552 | 558 |
553 base::MessageLoop::current()->PostDelayedTask( | 559 base::MessageLoop::current()->PostDelayedTask( |
554 FROM_HERE, | 560 FROM_HERE, next_refresh_.callback(), next_refresh2 - base::Time::Now()); |
555 next_refresh_.callback(), | |
556 next_refresh2 - base::Time::Now()); | |
557 } | 561 } |
558 | 562 |
559 void MDnsListenerImpl::DoRefresh() { | 563 void MDnsListenerImpl::DoRefresh() { |
560 client_->core()->SendQuery(rrtype_, name_); | 564 client_->core()->SendQuery(rrtype_, name_); |
561 } | 565 } |
562 | 566 |
563 MDnsTransactionImpl::MDnsTransactionImpl( | 567 MDnsTransactionImpl::MDnsTransactionImpl( |
564 uint16 rrtype, | 568 uint16 rrtype, |
565 const std::string& name, | 569 const std::string& name, |
566 int flags, | 570 int flags, |
567 const MDnsTransaction::ResultCallback& callback, | 571 const MDnsTransaction::ResultCallback& callback, |
568 MDnsClientImpl* client) | 572 MDnsClientImpl* client) |
569 : rrtype_(rrtype), name_(name), callback_(callback), client_(client), | 573 : rrtype_(rrtype), |
570 started_(false), flags_(flags) { | 574 name_(name), |
| 575 callback_(callback), |
| 576 client_(client), |
| 577 started_(false), |
| 578 flags_(flags) { |
571 DCHECK((flags_ & MDnsTransaction::FLAG_MASK) == flags_); | 579 DCHECK((flags_ & MDnsTransaction::FLAG_MASK) == flags_); |
572 DCHECK(flags_ & MDnsTransaction::QUERY_CACHE || | 580 DCHECK(flags_ & MDnsTransaction::QUERY_CACHE || |
573 flags_ & MDnsTransaction::QUERY_NETWORK); | 581 flags_ & MDnsTransaction::QUERY_NETWORK); |
574 } | 582 } |
575 | 583 |
576 MDnsTransactionImpl::~MDnsTransactionImpl() { | 584 MDnsTransactionImpl::~MDnsTransactionImpl() { |
577 timeout_.Cancel(); | 585 timeout_.Cancel(); |
578 } | 586 } |
579 | 587 |
580 bool MDnsTransactionImpl::Start() { | 588 bool MDnsTransactionImpl::Start() { |
581 DCHECK(!started_); | 589 DCHECK(!started_); |
582 started_ = true; | 590 started_ = true; |
583 | 591 |
584 base::WeakPtr<MDnsTransactionImpl> weak_this = AsWeakPtr(); | 592 base::WeakPtr<MDnsTransactionImpl> weak_this = AsWeakPtr(); |
585 if (flags_ & MDnsTransaction::QUERY_CACHE) { | 593 if (flags_ & MDnsTransaction::QUERY_CACHE) { |
586 ServeRecordsFromCache(); | 594 ServeRecordsFromCache(); |
587 | 595 |
588 if (!weak_this || !is_active()) return true; | 596 if (!weak_this || !is_active()) |
| 597 return true; |
589 } | 598 } |
590 | 599 |
591 if (flags_ & MDnsTransaction::QUERY_NETWORK) { | 600 if (flags_ & MDnsTransaction::QUERY_NETWORK) { |
592 return QueryAndListen(); | 601 return QueryAndListen(); |
593 } | 602 } |
594 | 603 |
595 // If this is a cache only query, signal that the transaction is over | 604 // If this is a cache only query, signal that the transaction is over |
596 // immediately. | 605 // immediately. |
597 SignalTransactionOver(); | 606 SignalTransactionOver(); |
598 return true; | 607 return true; |
599 } | 608 } |
600 | 609 |
601 const std::string& MDnsTransactionImpl::GetName() const { | 610 const std::string& MDnsTransactionImpl::GetName() const { |
602 return name_; | 611 return name_; |
603 } | 612 } |
604 | 613 |
605 uint16 MDnsTransactionImpl::GetType() const { | 614 uint16 MDnsTransactionImpl::GetType() const { |
606 return rrtype_; | 615 return rrtype_; |
607 } | 616 } |
608 | 617 |
609 void MDnsTransactionImpl::CacheRecordFound(const RecordParsed* record) { | 618 void MDnsTransactionImpl::CacheRecordFound(const RecordParsed* record) { |
610 DCHECK(started_); | 619 DCHECK(started_); |
611 OnRecordUpdate(MDnsListener::RECORD_ADDED, record); | 620 OnRecordUpdate(MDnsListener::RECORD_ADDED, record); |
612 } | 621 } |
613 | 622 |
614 void MDnsTransactionImpl::TriggerCallback(MDnsTransaction::Result result, | 623 void MDnsTransactionImpl::TriggerCallback(MDnsTransaction::Result result, |
615 const RecordParsed* record) { | 624 const RecordParsed* record) { |
616 DCHECK(started_); | 625 DCHECK(started_); |
617 if (!is_active()) return; | 626 if (!is_active()) |
| 627 return; |
618 | 628 |
619 // Ensure callback is run after touching all class state, so that | 629 // Ensure callback is run after touching all class state, so that |
620 // the callback can delete the transaction. | 630 // the callback can delete the transaction. |
621 MDnsTransaction::ResultCallback callback = callback_; | 631 MDnsTransaction::ResultCallback callback = callback_; |
622 | 632 |
623 // Reset the transaction if it expects a single result, or if the result | 633 // Reset the transaction if it expects a single result, or if the result |
624 // is a final one (everything except for a record). | 634 // is a final one (everything except for a record). |
625 if (flags_ & MDnsTransaction::SINGLE_RESULT || | 635 if (flags_ & MDnsTransaction::SINGLE_RESULT || |
626 result != MDnsTransaction::RESULT_RECORD) { | 636 result != MDnsTransaction::RESULT_RECORD) { |
627 Reset(); | 637 Reset(); |
628 } | 638 } |
629 | 639 |
630 callback.Run(result, record); | 640 callback.Run(result, record); |
631 } | 641 } |
632 | 642 |
633 void MDnsTransactionImpl::Reset() { | 643 void MDnsTransactionImpl::Reset() { |
634 callback_.Reset(); | 644 callback_.Reset(); |
635 listener_.reset(); | 645 listener_.reset(); |
636 timeout_.Cancel(); | 646 timeout_.Cancel(); |
637 } | 647 } |
638 | 648 |
639 void MDnsTransactionImpl::OnRecordUpdate(MDnsListener::UpdateType update, | 649 void MDnsTransactionImpl::OnRecordUpdate(MDnsListener::UpdateType update, |
640 const RecordParsed* record) { | 650 const RecordParsed* record) { |
641 DCHECK(started_); | 651 DCHECK(started_); |
642 if (update == MDnsListener::RECORD_ADDED || | 652 if (update == MDnsListener::RECORD_ADDED || |
643 update == MDnsListener::RECORD_CHANGED) | 653 update == MDnsListener::RECORD_CHANGED) |
644 TriggerCallback(MDnsTransaction::RESULT_RECORD, record); | 654 TriggerCallback(MDnsTransaction::RESULT_RECORD, record); |
645 } | 655 } |
646 | 656 |
647 void MDnsTransactionImpl::SignalTransactionOver() { | 657 void MDnsTransactionImpl::SignalTransactionOver() { |
648 DCHECK(started_); | 658 DCHECK(started_); |
649 if (flags_ & MDnsTransaction::SINGLE_RESULT) { | 659 if (flags_ & MDnsTransaction::SINGLE_RESULT) { |
650 TriggerCallback(MDnsTransaction::RESULT_NO_RESULTS, NULL); | 660 TriggerCallback(MDnsTransaction::RESULT_NO_RESULTS, NULL); |
651 } else { | 661 } else { |
652 TriggerCallback(MDnsTransaction::RESULT_DONE, NULL); | 662 TriggerCallback(MDnsTransaction::RESULT_DONE, NULL); |
653 } | 663 } |
654 } | 664 } |
655 | 665 |
656 void MDnsTransactionImpl::ServeRecordsFromCache() { | 666 void MDnsTransactionImpl::ServeRecordsFromCache() { |
657 std::vector<const RecordParsed*> records; | 667 std::vector<const RecordParsed*> records; |
658 base::WeakPtr<MDnsTransactionImpl> weak_this = AsWeakPtr(); | 668 base::WeakPtr<MDnsTransactionImpl> weak_this = AsWeakPtr(); |
659 | 669 |
660 if (client_->core()) { | 670 if (client_->core()) { |
661 client_->core()->QueryCache(rrtype_, name_, &records); | 671 client_->core()->QueryCache(rrtype_, name_, &records); |
662 for (std::vector<const RecordParsed*>::iterator i = records.begin(); | 672 for (std::vector<const RecordParsed*>::iterator i = records.begin(); |
663 i != records.end() && weak_this; ++i) { | 673 i != records.end() && weak_this; |
| 674 ++i) { |
664 weak_this->TriggerCallback(MDnsTransaction::RESULT_RECORD, *i); | 675 weak_this->TriggerCallback(MDnsTransaction::RESULT_RECORD, *i); |
665 } | 676 } |
666 | 677 |
667 #if defined(ENABLE_NSEC) | 678 #if defined(ENABLE_NSEC) |
668 if (records.empty()) { | 679 if (records.empty()) { |
669 DCHECK(weak_this); | 680 DCHECK(weak_this); |
670 client_->core()->QueryCache(dns_protocol::kTypeNSEC, name_, &records); | 681 client_->core()->QueryCache(dns_protocol::kTypeNSEC, name_, &records); |
671 if (!records.empty()) { | 682 if (!records.empty()) { |
672 const NsecRecordRdata* rdata = | 683 const NsecRecordRdata* rdata = |
673 records.front()->rdata<NsecRecordRdata>(); | 684 records.front()->rdata<NsecRecordRdata>(); |
674 DCHECK(rdata); | 685 DCHECK(rdata); |
675 if (!rdata->GetBit(rrtype_)) | 686 if (!rdata->GetBit(rrtype_)) |
676 weak_this->TriggerCallback(MDnsTransaction::RESULT_NSEC, NULL); | 687 weak_this->TriggerCallback(MDnsTransaction::RESULT_NSEC, NULL); |
677 } | 688 } |
678 } | 689 } |
679 #endif | 690 #endif |
680 } | 691 } |
681 } | 692 } |
682 | 693 |
683 bool MDnsTransactionImpl::QueryAndListen() { | 694 bool MDnsTransactionImpl::QueryAndListen() { |
684 listener_ = client_->CreateListener(rrtype_, name_, this); | 695 listener_ = client_->CreateListener(rrtype_, name_, this); |
685 if (!listener_->Start()) | 696 if (!listener_->Start()) |
686 return false; | 697 return false; |
687 | 698 |
688 DCHECK(client_->core()); | 699 DCHECK(client_->core()); |
689 if (!client_->core()->SendQuery(rrtype_, name_)) | 700 if (!client_->core()->SendQuery(rrtype_, name_)) |
690 return false; | 701 return false; |
691 | 702 |
692 timeout_.Reset(base::Bind(&MDnsTransactionImpl::SignalTransactionOver, | 703 timeout_.Reset( |
693 AsWeakPtr())); | 704 base::Bind(&MDnsTransactionImpl::SignalTransactionOver, AsWeakPtr())); |
694 base::MessageLoop::current()->PostDelayedTask( | 705 base::MessageLoop::current()->PostDelayedTask( |
695 FROM_HERE, | 706 FROM_HERE, |
696 timeout_.callback(), | 707 timeout_.callback(), |
697 base::TimeDelta::FromSeconds(MDnsTransactionTimeoutSeconds)); | 708 base::TimeDelta::FromSeconds(MDnsTransactionTimeoutSeconds)); |
698 | 709 |
699 return true; | 710 return true; |
700 } | 711 } |
701 | 712 |
702 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { | 713 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { |
703 TriggerCallback(RESULT_NSEC, NULL); | 714 TriggerCallback(RESULT_NSEC, NULL); |
704 } | 715 } |
705 | 716 |
706 void MDnsTransactionImpl::OnCachePurged() { | 717 void MDnsTransactionImpl::OnCachePurged() { |
707 // TODO(noamsml): Cache purge situations not yet implemented | 718 // TODO(noamsml): Cache purge situations not yet implemented |
708 } | 719 } |
709 | 720 |
710 } // namespace net | 721 } // namespace net |
OLD | NEW |