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

Side by Side Diff: net/dns/mdns_client_impl.cc

Issue 15733008: Multicast DNS implementation (initial) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mdns_implementation2
Patch Set: Created 7 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
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698