OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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_proxy.h" | 8 #include "base/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" |
11 #include "net/base/dns_util.h" | 11 #include "net/base/dns_util.h" |
12 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
13 #include "net/base/net_log.h" | 13 #include "net/base/net_log.h" |
14 #include "net/base/rand_callback.h" | 14 #include "net/base/rand_callback.h" |
15 #include "net/dns/dns_protocol.h" | 15 #include "net/dns/dns_protocol.h" |
16 #include "net/dns/mdns_query.h" | |
17 #include "net/udp/datagram_socket.h" | 16 #include "net/udp/datagram_socket.h" |
18 | 17 |
19 namespace net { | 18 namespace net { |
20 | 19 |
21 static const char kMDNSMulticastGroupIPv4[] = "224.0.0.251"; | 20 static const char kMDnsMulticastGroupIPv4[] = "224.0.0.251"; |
22 static const char kMDNSMulticastGroupIPv6[] = "FF02::FB"; | 21 static const char kMDnsMulticastGroupIPv6[] = "FF02::FB"; |
23 | 22 |
24 static const unsigned kMDnsTransactionTimeoutSeconds = 3; | 23 static const unsigned kMDnsTransactionNoResultsSeconds = 3; |
25 | 24 |
26 MDnsClientImpl::Core::Core(MDnsClientImpl* client, | 25 MDnsClientImpl::Core::Core(MDnsClientImpl* client, |
27 MDnsConnectionFactory* connection_factory) | 26 MDnsConnectionFactory* connection_factory) |
28 : client_(client), connection_(connection_factory->CreateConnection(this)) { | 27 : client_(client), connection_(connection_factory->CreateConnection(this)) { |
29 } | 28 } |
30 | 29 |
31 MDnsClientImpl::Core::~Core() { | 30 MDnsClientImpl::Core::~Core() { |
32 cleanup_callback_.Cancel(); | 31 cleanup_callback_.Cancel(); |
33 STLDeleteValues(&listeners_); | 32 STLDeleteValues(&listeners_); |
34 } | 33 } |
35 | 34 |
36 bool MDnsClientImpl::Core::Init() { | 35 bool MDnsClientImpl::Core::Init() { |
37 return connection_->Init(); | 36 return connection_->Init() == OK; |
38 } | 37 } |
39 | 38 |
40 bool MDnsClientImpl::Core::SendQuery(uint16 rrtype, std::string name) { | 39 bool MDnsClientImpl::Core::SendQuery(uint16 rrtype, std::string name) { |
41 std::string name_dns; | 40 std::string name_dns; |
42 if (!DNSDomainFromDot(name, &name_dns)) | 41 if (!DNSDomainFromDot(name, &name_dns)) |
43 return false; | 42 return false; |
44 | 43 |
45 MDnsQuery query(name_dns, rrtype); | 44 // TODO(noamsml): Remove RD flag from query and add known-answer suppression. |
45 DnsQuery query(0, name_dns, rrtype); | |
46 | 46 |
47 connection_->Send(query.io_buffer(), query.size()); | 47 return connection_->Send(query.io_buffer(), query.io_buffer()->size()) == OK; |
48 | |
49 return true; | |
50 } | 48 } |
51 | 49 |
52 void MDnsClientImpl::Core::HandlePacket(DnsResponse* response, | 50 void MDnsClientImpl::Core::HandlePacket(DnsResponse* response, |
53 int bytes_read) { | 51 int bytes_read) { |
54 unsigned offset; | 52 unsigned offset; |
55 | 53 |
56 if (!response->InitParseWithoutQuery(bytes_read)) { | 54 if (!response->InitParseWithoutQuery(bytes_read)) { |
57 LOG(WARNING) << "Could not understand an mDNS packet."; | 55 LOG(WARNING) << "Could not understand an mDNS packet."; |
58 return; // Message is unreadable. | 56 return; // Message is unreadable. |
59 } | 57 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 } | 112 } |
115 | 113 |
116 AlertListeners(update_external, | 114 AlertListeners(update_external, |
117 ListenerKey(record->type(), record->name()), record); | 115 ListenerKey(record->type(), record->name()), record); |
118 // Alert listeners listening only for rrtype and not for name. | 116 // Alert listeners listening only for rrtype and not for name. |
119 AlertListeners(update_external, ListenerKey(record->type(), ""), record); | 117 AlertListeners(update_external, ListenerKey(record->type(), ""), record); |
120 } | 118 } |
121 } | 119 } |
122 } | 120 } |
123 | 121 |
122 void MDnsClientImpl::Core::OnConnectionError(int error) { | |
123 // TODO(noamsml): On connection error, recreate connection and flush cache. | |
124 } | |
125 | |
124 void MDnsClientImpl::Core::AlertListeners( | 126 void MDnsClientImpl::Core::AlertListeners( |
125 MDnsUpdateType update_type, | 127 MDnsUpdateType update_type, |
126 const ListenerKey& key, | 128 const ListenerKey& key, |
127 const RecordParsed* record) { | 129 const RecordParsed* record) { |
128 ListenerMap::iterator listener_map_iterator = listeners_.find(key); | 130 ListenerMap::iterator listener_map_iterator = listeners_.find(key); |
129 if (listener_map_iterator == listeners_.end()) return; | 131 if (listener_map_iterator == listeners_.end()) return; |
130 | 132 |
131 FOR_EACH_OBSERVER(MDnsListenerImpl, *listener_map_iterator->second, | 133 FOR_EACH_OBSERVER(MDnsListenerImpl, *listener_map_iterator->second, |
132 AlertDelegate(update_type, record)); | 134 AlertDelegate(update_type, record)); |
133 } | 135 } |
134 | 136 |
135 void MDnsClientImpl::Core::AddListener( | 137 void MDnsClientImpl::Core::AddListener( |
136 MDnsListenerImpl* listener, bool alert_existing_records) { | 138 MDnsListenerImpl* listener) { |
137 ListenerKey key(listener->GetType(), listener->GetName()); | 139 ListenerKey key(listener->GetType(), listener->GetName()); |
138 std::pair<ListenerMap::iterator, bool> observer_insert_result = | 140 std::pair<ListenerMap::iterator, bool> observer_insert_result = |
139 listeners_.insert( | 141 listeners_.insert( |
140 make_pair(key, static_cast<ObserverList<MDnsListenerImpl>*>(NULL))); | 142 make_pair(key, static_cast<ObserverList<MDnsListenerImpl>*>(NULL))); |
141 | 143 |
142 // If an equivalent key does not exist, actually create the observer list. | 144 // If an equivalent key does not exist, actually create the observer list. |
143 if (observer_insert_result.second) { | 145 if (observer_insert_result.second) { |
144 observer_insert_result.first->second = new ObserverList<MDnsListenerImpl>(); | 146 observer_insert_result.first->second = new ObserverList<MDnsListenerImpl>(); |
145 } | 147 } |
146 | 148 |
147 ObserverList<MDnsListenerImpl>* observer_list = | 149 ObserverList<MDnsListenerImpl>* observer_list = |
148 observer_insert_result.first->second; | 150 observer_insert_result.first->second; |
149 | 151 |
150 observer_list->AddObserver(listener); | 152 observer_list->AddObserver(listener); |
151 | |
152 if (alert_existing_records) { | |
153 std::vector<const RecordParsed*> records; | |
154 | |
155 cache_.FindDnsRecords(listener->GetType(), listener->GetName(), | |
156 &records, base::Time::Now()); | |
157 | |
158 base::WeakPtr<MDnsListenerImpl> weak_listener = listener->AsWeakPtr(); | |
159 | |
160 for (std::vector<const RecordParsed*>::iterator i = records.begin(); | |
161 i != records.end(); i++) { | |
162 if (weak_listener) { | |
163 weak_listener->AlertDelegate(kMDnsRecordAdded, *i); | |
164 } | |
165 } | |
166 } | |
167 } | 153 } |
168 | 154 |
169 void MDnsClientImpl::Core::RemoveListener(MDnsListenerImpl* listener) { | 155 void MDnsClientImpl::Core::RemoveListener(MDnsListenerImpl* listener) { |
170 ListenerKey key(listener->GetType(), listener->GetName()); | 156 ListenerKey key(listener->GetType(), listener->GetName()); |
171 ListenerMap::iterator observer_list_iterator = listeners_.find(key); | 157 ListenerMap::iterator observer_list_iterator = listeners_.find(key); |
172 | 158 |
173 DCHECK(observer_list_iterator != listeners_.end()); | 159 DCHECK(observer_list_iterator != listeners_.end()); |
174 DCHECK(observer_list_iterator->second->HasObserver(listener)); | 160 DCHECK(observer_list_iterator->second->HasObserver(listener)); |
175 | 161 |
176 observer_list_iterator->second->RemoveObserver(listener); | 162 observer_list_iterator->second->RemoveObserver(listener); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
262 } | 248 } |
263 } | 249 } |
264 | 250 |
265 bool MDnsClientImpl::IsListeningForTests() { | 251 bool MDnsClientImpl::IsListeningForTests() { |
266 return core_.get() != NULL; | 252 return core_.get() != NULL; |
267 } | 253 } |
268 | 254 |
269 scoped_ptr<MDnsListener> MDnsClientImpl::CreateListener( | 255 scoped_ptr<MDnsListener> MDnsClientImpl::CreateListener( |
270 uint16 rrtype, | 256 uint16 rrtype, |
271 const std::string& name, | 257 const std::string& name, |
272 bool active, | |
273 bool alert_existing_records, | |
274 MDnsListener::Delegate* delegate) { | 258 MDnsListener::Delegate* delegate) { |
275 return scoped_ptr<net::MDnsListener>( | 259 return scoped_ptr<net::MDnsListener>( |
276 new MDnsListenerImpl(rrtype, name, active, alert_existing_records, | 260 new MDnsListenerImpl(rrtype, name, delegate, this)); |
277 delegate, this)); | |
278 } | 261 } |
279 | 262 |
280 scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction( | 263 scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction( |
281 uint16 rrtype, | 264 uint16 rrtype, |
282 const std::string& name, | 265 const std::string& name, |
266 int flags, | |
283 const MDnsTransaction::ResultCallback& callback) { | 267 const MDnsTransaction::ResultCallback& callback) { |
284 return scoped_ptr<MDnsTransaction>( | 268 return scoped_ptr<MDnsTransaction>( |
285 new MDnsTransactionImpl(rrtype, name, callback, this)); | 269 new MDnsTransactionImpl(rrtype, name, flags, callback, this)); |
286 } | 270 } |
287 | 271 |
288 MDnsListenerImpl::MDnsListenerImpl( | 272 MDnsListenerImpl::MDnsListenerImpl( |
289 uint16 rrtype, | 273 uint16 rrtype, |
290 const std::string& name, | 274 const std::string& name, |
291 bool active, | |
292 bool alert_existing_records, | |
293 MDnsListener::Delegate* delegate, | 275 MDnsListener::Delegate* delegate, |
294 MDnsClientImpl* client) | 276 MDnsClientImpl* client) |
295 : rrtype_(rrtype), name_(name), active_(active), | 277 : rrtype_(rrtype), name_(name), client_(client), delegate_(delegate), |
296 alert_existing_records_(alert_existing_records), client_(client), | 278 started_(false) { |
297 delegate_(delegate), started_(false) { | |
298 } | 279 } |
299 | 280 |
300 bool MDnsListenerImpl::Start() { | 281 bool MDnsListenerImpl::Start() { |
301 DCHECK(!started_); | 282 DCHECK(!started_); |
302 | 283 |
303 if (!client_->AddListenRef()) return false; | 284 if (!client_->AddListenRef()) return false; |
304 started_ = true; | 285 started_ = true; |
305 | 286 |
306 client_->core()->AddListener(this, alert_existing_records_); | 287 client_->core()->AddListener(this); |
307 | 288 |
308 if (active_) SendQuery(false); // TODO(noamsml): Retry logic. | |
309 return true; | 289 return true; |
310 } | 290 } |
311 | 291 |
312 MDnsListenerImpl::~MDnsListenerImpl() { | 292 MDnsListenerImpl::~MDnsListenerImpl() { |
313 if (started_) { | 293 if (started_) { |
314 client_->core()->RemoveListener(this); | 294 client_->core()->RemoveListener(this); |
315 client_->SubtractListenRef(); | 295 client_->SubtractListenRef(); |
316 } | 296 } |
317 } | 297 } |
318 | 298 |
319 const std::string& MDnsListenerImpl::GetName() const { | 299 const std::string& MDnsListenerImpl::GetName() const { |
320 return name_; | 300 return name_; |
321 } | 301 } |
322 | 302 |
323 uint16 MDnsListenerImpl::GetType() const { | 303 uint16 MDnsListenerImpl::GetType() const { |
324 return rrtype_; | 304 return rrtype_; |
325 } | 305 } |
326 | 306 |
327 bool MDnsListenerImpl::IsActive() const { | |
328 return active_; | |
329 } | |
330 | |
331 bool MDnsListenerImpl::SendQuery(bool force_refresh_cache) { | |
332 DCHECK(started_); | |
333 // TODO(noamsml): Logic related to force_refresh_cache | |
334 if (name_.size() == 0) return false; | |
335 return client_->core()->SendQuery(rrtype_, name_); | |
336 } | |
337 | |
338 bool MDnsListenerImpl::QueryCache( | |
339 std::vector<const RecordParsed*>* records) const { | |
340 DCHECK(started_); | |
341 if (name_.size() == 0) return false; | |
342 client_->core()->QueryCache(rrtype_, name_, records); | |
343 return true; | |
344 } | |
345 | |
346 void MDnsListenerImpl::AlertDelegate(MDnsUpdateType update_type, | 307 void MDnsListenerImpl::AlertDelegate(MDnsUpdateType update_type, |
347 const RecordParsed* record) { | 308 const RecordParsed* record) { |
348 DCHECK(started_); | 309 DCHECK(started_); |
349 delegate_->OnRecordUpdate(update_type, record); | 310 delegate_->OnRecordUpdate(update_type, record); |
350 } | 311 } |
351 | 312 |
352 MDnsTransactionImpl::MDnsTransactionImpl( | 313 MDnsTransactionImpl::MDnsTransactionImpl( |
353 uint16 rrtype, | 314 uint16 rrtype, |
354 const std::string& name, | 315 const std::string& name, |
316 int flags, | |
355 const MDnsTransaction::ResultCallback& callback, | 317 const MDnsTransaction::ResultCallback& callback, |
356 MDnsClientImpl* client) | 318 MDnsClientImpl* client) |
357 : rrtype_(rrtype), name_(name), callback_(callback), client_(client), | 319 : rrtype_(rrtype), name_(name), callback_(callback), client_(client), |
358 started_(false) { | 320 started_(false), flags_(flags) { |
321 DCHECK((flags_ & kMDnsTransactionFlagMask) == flags_); | |
322 DCHECK(flags_ & kMDnsTransactionQueryCache || | |
323 flags_ & kMDnsTransactionQueryNetwork); | |
359 } | 324 } |
360 | 325 |
361 MDnsTransactionImpl::~MDnsTransactionImpl() { | 326 MDnsTransactionImpl::~MDnsTransactionImpl() { |
327 timeout_.Cancel(); | |
362 } | 328 } |
363 | 329 |
364 bool MDnsTransactionImpl::Start() { | 330 bool MDnsTransactionImpl::Start() { |
365 DCHECK(!started_); | 331 DCHECK(!started_); |
366 started_ = true; | 332 started_ = true; |
367 std::vector<const RecordParsed*> records; | 333 std::vector<const RecordParsed*> records; |
368 if (client_->core()) { | 334 base::WeakPtr<MDnsTransactionImpl> weak_this = AsWeakPtr(); |
369 client_->core()->QueryCache(rrtype_, name_, &records); | 335 |
370 if (!records.empty()) { | 336 if (flags_ & kMDnsTransactionQueryCache) { |
371 TriggerCallback(kMDnsTransactionSuccess, records.front()); | 337 if (client_->core()) { |
372 return true; | 338 client_->core()->QueryCache(rrtype_, name_, &records); |
339 for (std::vector<const RecordParsed*>::iterator i = records.begin(); | |
340 i != records.end() && weak_this; ++i) { | |
341 weak_this->TriggerCallback(kMDnsTransactionRecord, records.front()); | |
342 } | |
373 } | 343 } |
374 } | 344 } |
375 | 345 |
376 listener_ = client_->CreateListener(rrtype_, name_, true /*active*/, | 346 if (!weak_this) return true; |
377 false /*alert existing*/, this); | |
378 listener_->Start(); | |
379 | 347 |
380 timeout_.Reset(base::Bind(&MDnsTransactionImpl::OnTimedOut, AsWeakPtr())); | 348 if (is_active() && flags_ & kMDnsTransactionQueryNetwork) { |
381 base::MessageLoop::current()->PostDelayedTask( | 349 listener_ = client_->CreateListener(rrtype_, name_, this); |
382 FROM_HERE, | 350 if (!listener_->Start()) return false; |
383 timeout_.callback(), | |
384 base::TimeDelta::FromSeconds(kMDnsTransactionTimeoutSeconds)); | |
385 | 351 |
386 return listener_.get() != NULL; | 352 DCHECK(client_->core()); |
353 if (!client_->core()->SendQuery(rrtype_, name_)) { | |
354 return false; | |
355 } | |
356 | |
357 timeout_.Reset(base::Bind(&MDnsTransactionImpl::SignalTransactionOver, | |
358 weak_this)); | |
359 base::MessageLoop::current()->PostDelayedTask( | |
360 FROM_HERE, | |
361 timeout_.callback(), | |
362 base::TimeDelta::FromSeconds(kMDnsTransactionNoResultsSeconds)); | |
363 | |
364 return listener_.get() != NULL; | |
365 } else { | |
366 // If this is a cache only query, signal that the transaction is over | |
367 // immediately. | |
368 SignalTransactionOver(); | |
369 } | |
370 | |
371 return true; | |
387 } | 372 } |
388 | 373 |
389 const std::string& MDnsTransactionImpl::GetName() const { | 374 const std::string& MDnsTransactionImpl::GetName() const { |
390 return name_; | 375 return name_; |
391 } | 376 } |
392 | 377 |
393 uint16 MDnsTransactionImpl::GetType() const { | 378 uint16 MDnsTransactionImpl::GetType() const { |
394 return rrtype_; | 379 return rrtype_; |
395 } | 380 } |
396 | 381 |
397 void MDnsTransactionImpl::CacheRecordFound(const RecordParsed* record) { | 382 void MDnsTransactionImpl::CacheRecordFound(const RecordParsed* record) { |
398 DCHECK(started_); | 383 DCHECK(started_); |
399 OnRecordUpdate(kMDnsRecordAdded, record); | 384 OnRecordUpdate(kMDnsRecordAdded, record); |
400 } | 385 } |
401 | 386 |
402 void MDnsTransactionImpl::TriggerCallback(MDnsTransactionResult result, | 387 void MDnsTransactionImpl::TriggerCallback(MDnsTransactionResult result, |
403 const RecordParsed* record) { | 388 const RecordParsed* record) { |
404 DCHECK(started_); | 389 DCHECK(started_); |
405 if (callback_.is_null()) return; | 390 if (!is_active()) return; |
406 | 391 |
407 // Ensure callback is run after touching all class state, so that | 392 // Ensure callback is run after touching all class state, so that |
408 // the callback can delete the transaction. | 393 // the callback can delete the transaction. |
409 MDnsTransaction::ResultCallback callback = callback_; | 394 MDnsTransaction::ResultCallback callback = callback_; |
410 | 395 |
396 if (flags_ & kMDnsTransactionSingleResult) { | |
397 Reset(); | |
398 } | |
399 | |
400 callback.Run(result, record); | |
401 } | |
402 | |
403 void MDnsTransactionImpl::Reset() { | |
411 callback_.Reset(); | 404 callback_.Reset(); |
412 listener_.reset(); | 405 listener_.reset(); |
413 timeout_.Cancel(); | 406 timeout_.Cancel(); |
414 | |
415 callback.Run(result, record); | |
416 } | 407 } |
417 | 408 |
418 void MDnsTransactionImpl::OnRecordUpdate(MDnsUpdateType update, | 409 void MDnsTransactionImpl::OnRecordUpdate(MDnsUpdateType update, |
419 const RecordParsed* record) { | 410 const RecordParsed* record) { |
420 DCHECK(started_); | 411 DCHECK(started_); |
421 if (update == kMDnsRecordAdded || update == kMDnsRecordChanged) { | 412 if (update == kMDnsRecordAdded || update == kMDnsRecordChanged) { |
422 TriggerCallback(kMDnsTransactionSuccess, record); | 413 TriggerCallback(kMDnsTransactionRecord, record); |
423 } | 414 } |
424 } | 415 } |
425 | 416 |
426 void MDnsTransactionImpl::OnTimedOut() { | 417 void MDnsTransactionImpl::SignalTransactionOver() { |
427 DCHECK(started_); | 418 DCHECK(started_); |
428 TriggerCallback(kMDnsTransactionTimeout, NULL); | 419 base::WeakPtr<MDnsTransactionImpl> weak_this = AsWeakPtr(); |
420 | |
421 if (flags_ & kMDnsTransactionSingleResult) { | |
422 TriggerCallback(kMDnsTransactionNoResults, NULL); | |
423 } else { | |
424 TriggerCallback(kMDnsTransactionDone, NULL); | |
425 } | |
426 | |
427 if (weak_this) { | |
428 weak_this->Reset(); | |
429 } | |
429 } | 430 } |
430 | 431 |
431 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { | 432 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { |
432 // TODO(noamsml): NSEC records not yet implemented | 433 // TODO(noamsml): NSEC records not yet implemented |
433 } | 434 } |
434 | 435 |
435 MDnsConnectionImpl::RecvLoop::RecvLoop( | 436 void MDnsTransactionImpl::OnCachePurged() { |
436 DatagramServerSocket* socket, MDnsConnectionImpl* connection) | 437 // TODO(noamsml): Cache purge situations not yet implemented |
437 : socket_(socket), connection_(connection), | |
438 response_(new DnsResponse(dns_protocol::kMaxMulticastSize)) { | |
439 } | 438 } |
440 | 439 |
441 MDnsConnectionImpl::RecvLoop::~RecvLoop() { | 440 MDnsConnectionImpl::SocketHandler::SocketHandler( |
441 MDnsConnectionImpl* connection, const IPEndPoint& multicast_addr) | |
442 : socket_owned_(new UDPServerSocket(NULL, NetLog::Source())), | |
443 socket_(socket_owned_.get()), connection_(connection), | |
444 response_(new DnsResponse(dns_protocol::kMaxMulticastSize)), | |
445 multicast_addr_(multicast_addr) { | |
442 } | 446 } |
443 | 447 |
444 void MDnsConnectionImpl::RecvLoop::DoLoop(int rv) { | 448 MDnsConnectionImpl::SocketHandler::SocketHandler( |
449 DatagramServerSocket* socket, | |
450 MDnsConnectionImpl* connection, const IPEndPoint& multicast_addr) | |
451 : socket_(socket), connection_(connection), | |
452 response_(new DnsResponse(dns_protocol::kMaxMulticastSize)), | |
453 multicast_addr_(multicast_addr) { | |
454 } | |
455 | |
456 | |
457 MDnsConnectionImpl::SocketHandler::~SocketHandler() { | |
458 } | |
459 | |
460 int MDnsConnectionImpl::SocketHandler::Start() { | |
461 int rv = BindSocket(); | |
462 if (rv != OK) { | |
463 return rv; | |
464 } | |
465 | |
466 return DoLoop(0); | |
467 } | |
468 | |
469 int MDnsConnectionImpl::SocketHandler::DoLoop(int rv) { | |
445 do { | 470 do { |
446 if (rv > 0) { | 471 if (rv > 0) { |
447 connection_->OnDatagramReceived(socket_, | 472 connection_->OnDatagramReceived(socket_, |
448 response_.get(), &recv_addr_, rv); | 473 response_.get(), &recv_addr_, rv); |
449 } | 474 } |
450 | 475 |
451 rv = socket_->RecvFrom( | 476 rv = socket_->RecvFrom( |
452 response_->io_buffer(), | 477 response_->io_buffer(), |
453 response_->io_buffer()->size(), | 478 response_->io_buffer()->size(), |
454 &recv_addr_, | 479 &recv_addr_, |
455 base::Bind(&MDnsConnectionImpl::RecvLoop::OnDatagramReceived, | 480 base::Bind(&MDnsConnectionImpl::SocketHandler::OnDatagramReceived, |
456 base::Unretained(this))); | 481 base::Unretained(this))); |
457 } while (rv > 0); | 482 } while (rv > 0); |
458 | 483 |
459 if (rv != ERR_IO_PENDING) { | 484 if (rv != ERR_IO_PENDING) { |
460 connection_->OnError(this, socket_, rv); | 485 return rv; |
486 } | |
487 | |
488 return OK; | |
489 } | |
490 | |
491 void MDnsConnectionImpl::SocketHandler::OnDatagramReceived(int rv) { | |
492 if (rv >= OK) { | |
493 rv = DoLoop(rv); | |
494 } | |
495 | |
496 if (rv != OK) { | |
497 connection_->OnError(this, rv); | |
461 } | 498 } |
462 } | 499 } |
463 | 500 |
464 void MDnsConnectionImpl::RecvLoop::OnDatagramReceived(int rv) { | 501 int MDnsConnectionImpl::SocketHandler::Send(IOBuffer* buffer, unsigned size) { |
465 DoLoop(rv); | 502 return socket_->SendTo( |
503 buffer, size, multicast_addr_, | |
504 base::Bind(&MDnsConnectionImpl::SocketHandler::SendDone, | |
505 base::Unretained(this) )); | |
466 } | 506 } |
467 | 507 |
508 void MDnsConnectionImpl::SocketHandler::SendDone(int sent) { | |
509 // TODO(noamsml): Retry logic. | |
510 } | |
511 | |
512 int MDnsConnectionImpl::SocketHandler::BindSocket() { | |
513 IPAddressNumber address_any; | |
514 address_any.resize(multicast_addr_.address().size(), 0); | |
515 | |
516 IPEndPoint bind_endpoint(address_any, multicast_addr_.port()); | |
517 | |
518 socket_->AllowAddressReuse(); | |
519 int rv = socket_->Listen(bind_endpoint); | |
520 | |
521 if (rv < OK) return rv; | |
522 | |
523 socket_->SetMulticastLoopbackMode(false); | |
524 | |
525 return socket_->JoinGroup(multicast_addr_.address()); | |
526 } | |
527 | |
528 | |
468 MDnsConnectionImpl::MDnsConnectionImpl(MDnsConnection::Delegate* delegate) | 529 MDnsConnectionImpl::MDnsConnectionImpl(MDnsConnection::Delegate* delegate) |
469 : socket_ipv4_(new UDPServerSocket(NULL, NetLog::Source())), | 530 : socket_handler_ipv4_(this, GetIPEndPoint(kMDnsMulticastGroupIPv4, |
szym
2013/06/10 21:58:28
If you always use this with the same port, why not
Noam Samuel
2013/06/11 20:35:03
Done.
| |
470 socket_ipv6_(new UDPServerSocket(NULL, NetLog::Source())), | 531 dns_protocol::kDefaultPortMulticast)), |
471 loop_ipv4_(socket_ipv4_.get(), this), | 532 socket_handler_ipv6_(this, GetIPEndPoint(kMDnsMulticastGroupIPv6, |
472 loop_ipv6_(socket_ipv6_.get(), this), | 533 dns_protocol::kDefaultPortMulticast)), |
534 delegate_(delegate) { | |
535 } | |
536 | |
537 MDnsConnectionImpl::MDnsConnectionImpl(DatagramServerSocket* socket_ipv4, | |
538 DatagramServerSocket* socket_ipv6, | |
539 MDnsConnection::Delegate* delegate) | |
540 : socket_handler_ipv4_(socket_ipv4, this, | |
541 GetIPEndPoint(kMDnsMulticastGroupIPv4, | |
542 dns_protocol::kDefaultPortMulticast)), | |
543 socket_handler_ipv6_(socket_ipv6, this, | |
544 GetIPEndPoint(kMDnsMulticastGroupIPv6, | |
545 dns_protocol::kDefaultPortMulticast)), | |
473 delegate_(delegate) { | 546 delegate_(delegate) { |
474 } | 547 } |
475 | 548 |
476 MDnsConnectionImpl::~MDnsConnectionImpl() { | 549 MDnsConnectionImpl::~MDnsConnectionImpl() { |
477 socket_ipv4_->Close(); | |
478 socket_ipv6_->Close(); | |
479 } | 550 } |
480 | 551 |
481 bool MDnsConnectionImpl::Init() { | 552 int MDnsConnectionImpl::Init() { |
482 if (!BindSocket(socket_ipv4_.get(), kIPv4AddressSize, | 553 int rv; |
483 kMDNSMulticastGroupIPv4)) | |
484 return false; | |
485 | 554 |
486 if (!BindSocket(socket_ipv6_.get(), kIPv6AddressSize, | 555 rv = socket_handler_ipv4_.Start(); |
487 kMDNSMulticastGroupIPv6)) | 556 if (rv != OK) return rv; |
488 return false; | 557 rv = socket_handler_ipv6_.Start(); |
489 | 558 if (rv != OK) return rv; |
490 loop_ipv4_.DoLoop(0); | |
491 loop_ipv6_.DoLoop(0); | |
492 | 559 |
493 return true; | 560 return true; |
494 } | 561 } |
495 | 562 |
496 bool MDnsConnectionImpl::Send(IOBuffer* buffer, unsigned size) { | 563 int MDnsConnectionImpl::Send(IOBuffer* buffer, unsigned size) { |
497 int rv = socket_ipv4_->SendTo( | 564 int rv; |
498 buffer, | |
499 size, | |
500 GetIPv4SendEndpoint(), | |
501 base::Bind(&MDnsConnectionImpl::SendDone, | |
502 base::Unretained(this) )); | |
503 if (rv < OK && rv != ERR_IO_PENDING) return false; | |
504 | 565 |
505 rv = socket_ipv6_->SendTo( | 566 rv = socket_handler_ipv4_.Send(buffer, size); |
506 buffer, | 567 if (rv < OK && rv != ERR_IO_PENDING) return rv; |
507 size, | |
508 GetIPv6SendEndpoint(), | |
509 base::Bind(&MDnsConnectionImpl::SendDone, | |
510 base::Unretained(this) )); | |
511 if (rv < OK && rv != ERR_IO_PENDING) return false; | |
512 | 568 |
513 return true; | 569 rv = socket_handler_ipv6_.Send(buffer, size); |
570 if (rv < OK && rv != ERR_IO_PENDING) return rv; | |
571 | |
572 return OK; | |
514 } | 573 } |
515 | 574 |
516 void MDnsConnectionImpl::SendDone(int sent) { | 575 void MDnsConnectionImpl::OnError(SocketHandler* loop, |
517 // TODO(noamsml): Queueing and retry logic. | 576 int error) { |
577 // TODO(noamsml): Specific handling of intermittent errors that can be handled | |
578 // in the connection. | |
579 delegate_->OnConnectionError(error); | |
518 } | 580 } |
519 | 581 |
520 void MDnsConnectionImpl::OnError(RecvLoop* loop, | 582 IPEndPoint MDnsConnectionImpl::GetIPEndPoint(const char* address, int port) { |
521 DatagramServerSocket* socket, | |
522 int error) { | |
523 // TODO(noamsml): Error handling. | |
524 } | |
525 | |
526 bool MDnsConnectionImpl::BindSocket( | |
527 DatagramServerSocket* socket, | |
528 int addr_size, | |
529 const char* multicast_group) { | |
530 IPAddressNumber address_any; | |
531 address_any.resize(addr_size, 0); | |
532 | |
533 IPAddressNumber multicast_group_number; | 583 IPAddressNumber multicast_group_number; |
534 | 584 bool success = ParseIPLiteralToNumber(address, |
535 IPEndPoint bind_endpoint(address_any, dns_protocol::kDefaultPortMulticast); | |
536 | |
537 bool success = ParseIPLiteralToNumber(multicast_group, | |
538 &multicast_group_number); | 585 &multicast_group_number); |
539 DCHECK(success); | 586 DCHECK(success); |
540 | 587 return IPEndPoint(multicast_group_number, port); |
541 socket->AllowAddressReuse(); | |
542 int status = socket->Listen(bind_endpoint); | |
543 | |
544 if (status < 0) | |
545 return false; | |
546 | |
547 socket->SetMulticastLoopbackMode(false); | |
548 | |
549 status = socket->JoinGroup(multicast_group_number); | |
550 | |
551 if (status < 0) | |
552 return false; | |
553 | |
554 return true; | |
555 } | |
556 | |
557 IPEndPoint MDnsConnectionImpl::GetIPv4SendEndpoint() { | |
558 IPAddressNumber multicast_group_number; | |
559 bool success = ParseIPLiteralToNumber(kMDNSMulticastGroupIPv4, | |
560 &multicast_group_number); | |
561 DCHECK(success); | |
562 return IPEndPoint(multicast_group_number, | |
563 dns_protocol::kDefaultPortMulticast); | |
564 } | |
565 | |
566 IPEndPoint MDnsConnectionImpl::GetIPv6SendEndpoint() { | |
567 IPAddressNumber multicast_group_number; | |
568 bool success = ParseIPLiteralToNumber(kMDNSMulticastGroupIPv6, | |
569 &multicast_group_number); | |
570 DCHECK(success); | |
571 return IPEndPoint(multicast_group_number, | |
572 dns_protocol::kDefaultPortMulticast); | |
573 } | 588 } |
574 | 589 |
575 void MDnsConnectionImpl::OnDatagramReceived( | 590 void MDnsConnectionImpl::OnDatagramReceived( |
576 DatagramServerSocket* socket, | 591 DatagramServerSocket* socket, |
577 DnsResponse* response, | 592 DnsResponse* response, |
578 IPEndPoint* recv_addr, | 593 IPEndPoint* recv_addr, |
579 int bytes_read) { | 594 int bytes_read) { |
580 // TODO(noamsml): More sophisticated error handling. | 595 // TODO(noamsml): More sophisticated error handling. |
581 DCHECK_GT(bytes_read, 0); | 596 DCHECK_GT(bytes_read, 0); |
582 delegate_->HandlePacket(response, bytes_read); | 597 delegate_->HandlePacket(response, bytes_read); |
583 } | 598 } |
584 | 599 |
585 MDnsConnectionImplFactory::MDnsConnectionImplFactory() { | 600 MDnsConnectionImplFactory::MDnsConnectionImplFactory() { |
586 } | 601 } |
587 | 602 |
588 MDnsConnectionImplFactory::~MDnsConnectionImplFactory() { | 603 MDnsConnectionImplFactory::~MDnsConnectionImplFactory() { |
589 } | 604 } |
590 | 605 |
591 scoped_ptr<MDnsConnection> MDnsConnectionImplFactory::CreateConnection( | 606 scoped_ptr<MDnsConnection> MDnsConnectionImplFactory::CreateConnection( |
592 MDnsConnection::Delegate* delegate) { | 607 MDnsConnection::Delegate* delegate) { |
593 return scoped_ptr<MDnsConnection>(new MDnsConnectionImpl(delegate)); | 608 return scoped_ptr<MDnsConnection>(new MDnsConnectionImpl(delegate)); |
594 } | 609 } |
595 | 610 |
596 } // namespace net | 611 } // namespace net |
OLD | NEW |