| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/extensions/api/dial/dial_service.h" | 5 #include "chrome/browser/extensions/api/dial/dial_service.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> |
| 9 #include <utility> |
| 8 | 10 |
| 9 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
| 10 #include "base/callback.h" | 12 #include "base/callback.h" |
| 11 #include "base/logging.h" | 13 #include "base/logging.h" |
| 12 #include "base/rand_util.h" | 14 #include "base/rand_util.h" |
| 13 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 15 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 16 #include "chrome/browser/extensions/api/dial/dial_device_data.h" | 18 #include "chrome/browser/extensions/api/dial/dial_device_data.h" |
| 17 #include "chrome/common/chrome_version_info.h" | 19 #include "chrome/common/chrome_version_info.h" |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 #else | 464 #else |
| 463 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind( | 465 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind( |
| 464 &GetNetworkListOnFileThread, | 466 &GetNetworkListOnFileThread, |
| 465 base::MessageLoopProxy::current(), base::Bind( | 467 base::MessageLoopProxy::current(), base::Bind( |
| 466 &DialServiceImpl::SendNetworkList, AsWeakPtr()))); | 468 &DialServiceImpl::SendNetworkList, AsWeakPtr()))); |
| 467 #endif | 469 #endif |
| 468 } | 470 } |
| 469 | 471 |
| 470 void DialServiceImpl::SendNetworkList(const NetworkInterfaceList& networks) { | 472 void DialServiceImpl::SendNetworkList(const NetworkInterfaceList& networks) { |
| 471 DCHECK(thread_checker_.CalledOnValidThread()); | 473 DCHECK(thread_checker_.CalledOnValidThread()); |
| 474 typedef std::pair<uint32, net::AddressFamily> InterfaceIndexAddressFamily; |
| 475 std::set<InterfaceIndexAddressFamily> interface_index_addr_family_seen; |
| 472 std::vector<IPAddressNumber> ip_addresses; | 476 std::vector<IPAddressNumber> ip_addresses; |
| 473 | 477 |
| 474 // Returns the first IPv4 address found. If there is a need for discovery | 478 // Binds a socket to each IPv4 network interface found. Note that |
| 475 // across multiple networks, we could manage multiple sockets. | 479 // there may be duplicates in |networks|, so address family + interface index |
| 480 // is used to identify unique interfaces. |
| 476 // TODO(mfoltz): Support IPV6 multicast. http://crbug.com/165286 | 481 // TODO(mfoltz): Support IPV6 multicast. http://crbug.com/165286 |
| 477 for (NetworkInterfaceList::const_iterator iter = networks.begin(); | 482 for (NetworkInterfaceList::const_iterator iter = networks.begin(); |
| 478 iter != networks.end(); ++iter) { | 483 iter != networks.end(); ++iter) { |
| 484 net::AddressFamily addr_family = net::GetAddressFamily(iter->address); |
| 479 DVLOG(1) << "Found " << iter->name << ", " | 485 DVLOG(1) << "Found " << iter->name << ", " |
| 480 << net::IPAddressToString(iter->address); | 486 << net::IPAddressToString(iter->address) |
| 481 if (iter->address.size() == net::kIPv4AddressSize) { | 487 << ", address family: " << addr_family; |
| 482 ip_addresses.push_back(iter->address); | 488 if (addr_family == net::ADDRESS_FAMILY_IPV4) { |
| 483 break; | 489 InterfaceIndexAddressFamily interface_index_addr_family = |
| 490 std::make_pair(iter->interface_index, addr_family); |
| 491 bool inserted = interface_index_addr_family_seen |
| 492 .insert(interface_index_addr_family) |
| 493 .second; |
| 494 // We have not seen this interface before, so add its IP address to the |
| 495 // discovery list. |
| 496 if (inserted) { |
| 497 VLOG(2) << "Encountered " |
| 498 << "interface index: " << iter->interface_index << ", " |
| 499 << "address family: " << addr_family << " for the first time, " |
| 500 << "adding IP address " << net::IPAddressToString(iter->address) |
| 501 << " to list."; |
| 502 ip_addresses.push_back(iter->address); |
| 503 } else { |
| 504 VLOG(2) << "Already encountered " |
| 505 << "interface index: " << iter->interface_index << ", " |
| 506 << "address family: " << addr_family << " before, not adding."; |
| 507 } |
| 484 } | 508 } |
| 485 } | 509 } |
| 486 | 510 |
| 487 DiscoverOnAddresses(ip_addresses); | 511 DiscoverOnAddresses(ip_addresses); |
| 488 } | 512 } |
| 489 | 513 |
| 490 void DialServiceImpl::DiscoverOnAddresses( | 514 void DialServiceImpl::DiscoverOnAddresses( |
| 491 const std::vector<IPAddressNumber>& ip_addresses) { | 515 const std::vector<IPAddressNumber>& ip_addresses) { |
| 492 if (ip_addresses.size() == 0) { | 516 if (ip_addresses.empty()) { |
| 493 DVLOG(1) << "Could not find a valid interface to bind. Finishing discovery"; | 517 DVLOG(1) << "Could not find a valid interface to bind. Finishing discovery"; |
| 494 FinishDiscovery(); | 518 FinishDiscovery(); |
| 495 return; | 519 return; |
| 496 } | 520 } |
| 497 | 521 |
| 498 // Schedule a timer to finish the discovery process (and close the sockets). | 522 // Schedule a timer to finish the discovery process (and close the sockets). |
| 499 if (finish_delay_ > TimeDelta::FromSeconds(0)) { | 523 if (finish_delay_ > TimeDelta::FromSeconds(0)) { |
| 500 VLOG(2) << "Starting timer to finish discovery."; | 524 VLOG(2) << "Starting timer to finish discovery."; |
| 501 finish_timer_.Start(FROM_HERE, | 525 finish_timer_.Start(FROM_HERE, |
| 502 finish_delay_, | 526 finish_delay_, |
| 503 this, | 527 this, |
| 504 &DialServiceImpl::FinishDiscovery); | 528 &DialServiceImpl::FinishDiscovery); |
| 505 } | 529 } |
| 506 | 530 |
| 507 for (std::vector<IPAddressNumber>::const_iterator iter = ip_addresses.begin(); | 531 for (std::vector<IPAddressNumber>::const_iterator iter = ip_addresses.begin(); |
| 508 iter != ip_addresses.end(); | 532 iter != ip_addresses.end(); |
| 509 ++iter) { | 533 ++iter) |
| 510 BindAndAddSocket(*iter); | 534 BindAndAddSocket(*iter); |
| 511 } | |
| 512 | 535 |
| 513 SendOneRequest(); | 536 SendOneRequest(); |
| 514 } | 537 } |
| 515 | 538 |
| 516 void DialServiceImpl::BindAndAddSocket(const IPAddressNumber& bind_ip_address) { | 539 void DialServiceImpl::BindAndAddSocket(const IPAddressNumber& bind_ip_address) { |
| 517 scoped_ptr<DialServiceImpl::DialSocket> dial_socket(CreateDialSocket()); | 540 scoped_ptr<DialServiceImpl::DialSocket> dial_socket(CreateDialSocket()); |
| 518 if (dial_socket->CreateAndBindSocket(bind_ip_address, net_log_, | 541 if (dial_socket->CreateAndBindSocket(bind_ip_address, net_log_, |
| 519 net_log_source_)) | 542 net_log_source_)) |
| 520 dial_sockets_.push_back(dial_socket.release()); | 543 dial_sockets_.push_back(dial_socket.release()); |
| 521 } | 544 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 if (!discovery_active_) { | 577 if (!discovery_active_) { |
| 555 VLOG(2) << "Request sent after discovery finished. Ignoring."; | 578 VLOG(2) << "Request sent after discovery finished. Ignoring."; |
| 556 return; | 579 return; |
| 557 } | 580 } |
| 558 | 581 |
| 559 VLOG(2) << "Notifying observers of discovery request"; | 582 VLOG(2) << "Notifying observers of discovery request"; |
| 560 FOR_EACH_OBSERVER(Observer, observer_list_, OnDiscoveryRequest(this)); | 583 FOR_EACH_OBSERVER(Observer, observer_list_, OnDiscoveryRequest(this)); |
| 561 // If we need to send additional requests, schedule a timer to do so. | 584 // If we need to send additional requests, schedule a timer to do so. |
| 562 if (num_requests_sent_ < max_requests_ && num_requests_sent_ == 1) { | 585 if (num_requests_sent_ < max_requests_ && num_requests_sent_ == 1) { |
| 563 VLOG(2) << "Scheduling timer to send additional requests"; | 586 VLOG(2) << "Scheduling timer to send additional requests"; |
| 587 // TODO(imcheng): Move this to SendOneRequest() once the implications are |
| 588 // understood. |
| 564 request_timer_.Start(FROM_HERE, | 589 request_timer_.Start(FROM_HERE, |
| 565 request_interval_, | 590 request_interval_, |
| 566 this, | 591 this, |
| 567 &DialServiceImpl::SendOneRequest); | 592 &DialServiceImpl::SendOneRequest); |
| 568 } | 593 } |
| 569 } | 594 } |
| 570 | 595 |
| 571 void DialServiceImpl::NotifyOnDeviceDiscovered( | 596 void DialServiceImpl::NotifyOnDeviceDiscovered( |
| 572 const DialDeviceData& device_data) { | 597 const DialDeviceData& device_data) { |
| 573 DCHECK(thread_checker_.CalledOnValidThread()); | 598 DCHECK(thread_checker_.CalledOnValidThread()); |
| 574 if (!discovery_active_) { | 599 if (!discovery_active_) { |
| 575 VLOG(2) << "Got response after discovery finished. Ignoring."; | 600 VLOG(2) << "Got response after discovery finished. Ignoring."; |
| 576 return; | 601 return; |
| 577 } | 602 } |
| 578 FOR_EACH_OBSERVER(Observer, observer_list_, | 603 FOR_EACH_OBSERVER(Observer, observer_list_, |
| 579 OnDeviceDiscovered(this, device_data)); | 604 OnDeviceDiscovered(this, device_data)); |
| 580 } | 605 } |
| 581 | 606 |
| 582 void DialServiceImpl::NotifyOnError() { | 607 void DialServiceImpl::NotifyOnError() { |
| 583 DCHECK(thread_checker_.CalledOnValidThread()); | 608 DCHECK(thread_checker_.CalledOnValidThread()); |
| 609 // TODO(imcheng): Modify upstream so that the device list is not cleared |
| 610 // when it could still potentially discover devices on other sockets. |
| 584 FOR_EACH_OBSERVER(Observer, observer_list_, | 611 FOR_EACH_OBSERVER(Observer, observer_list_, |
| 585 OnError(this, DIAL_SERVICE_SOCKET_ERROR)); | 612 OnError(this, |
| 613 HasOpenSockets() ? DIAL_SERVICE_SOCKET_ERROR |
| 614 : DIAL_SERVICE_NO_INTERFACES)); |
| 586 } | 615 } |
| 587 | 616 |
| 588 void DialServiceImpl::FinishDiscovery() { | 617 void DialServiceImpl::FinishDiscovery() { |
| 589 DCHECK(thread_checker_.CalledOnValidThread()); | 618 DCHECK(thread_checker_.CalledOnValidThread()); |
| 590 DCHECK(discovery_active_); | 619 DCHECK(discovery_active_); |
| 591 VLOG(2) << "Discovery finished."; | 620 VLOG(2) << "Discovery finished."; |
| 592 // Close all open sockets. | 621 // Close all open sockets. |
| 593 dial_sockets_.clear(); | 622 dial_sockets_.clear(); |
| 594 finish_timer_.Stop(); | 623 finish_timer_.Stop(); |
| 595 request_timer_.Stop(); | 624 request_timer_.Stop(); |
| 596 discovery_active_ = false; | 625 discovery_active_ = false; |
| 597 num_requests_sent_ = 0; | 626 num_requests_sent_ = 0; |
| 598 FOR_EACH_OBSERVER(Observer, observer_list_, OnDiscoveryFinished(this)); | 627 FOR_EACH_OBSERVER(Observer, observer_list_, OnDiscoveryFinished(this)); |
| 599 } | 628 } |
| 600 | 629 |
| 601 bool DialServiceImpl::HasOpenSockets() { | 630 bool DialServiceImpl::HasOpenSockets() { |
| 602 for (ScopedVector<DialSocket>::const_iterator iter = dial_sockets_.begin(); | 631 for (ScopedVector<DialSocket>::const_iterator iter = dial_sockets_.begin(); |
| 603 iter != dial_sockets_.end(); | 632 iter != dial_sockets_.end(); |
| 604 ++iter) { | 633 ++iter) { |
| 605 if (!((*iter)->IsClosed())) | 634 if (!((*iter)->IsClosed())) |
| 606 return true; | 635 return true; |
| 607 } | 636 } |
| 608 return false; | 637 return false; |
| 609 } | 638 } |
| 610 | 639 |
| 611 } // namespace extensions | 640 } // namespace extensions |
| OLD | NEW |