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

Side by Side Diff: chrome/browser/media/router/discovery/dial/dial_service.cc

Issue 2756483007: [Device Discovery] Move files from browser/extensions/api/dial to browser/media/router/discovery/di… (Closed)
Patch Set: resolve code review comments from Devlin Created 3 years, 9 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) 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/media/router/discovery/dial/dial_service.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <set> 10 #include <set>
11 #include <utility> 11 #include <utility>
12 12
13 #include "base/callback.h" 13 #include "base/callback.h"
14 #include "base/location.h" 14 #include "base/location.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/memory/ptr_util.h" 16 #include "base/memory/ptr_util.h"
17 #include "base/rand_util.h" 17 #include "base/rand_util.h"
18 #include "base/single_thread_task_runner.h" 18 #include "base/single_thread_task_runner.h"
19 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/stringprintf.h" 20 #include "base/strings/stringprintf.h"
21 #include "base/threading/thread_task_runner_handle.h" 21 #include "base/threading/thread_task_runner_handle.h"
22 #include "base/time/time.h" 22 #include "base/time/time.h"
23 #include "build/build_config.h" 23 #include "build/build_config.h"
24 #include "chrome/browser/extensions/api/dial/dial_device_data.h" 24 #include "chrome/browser/media/router/discovery/dial/dial_device_data.h"
25 #include "components/version_info/version_info.h" 25 #include "components/version_info/version_info.h"
26 #include "content/public/browser/browser_thread.h" 26 #include "content/public/browser/browser_thread.h"
27 #include "net/base/address_family.h" 27 #include "net/base/address_family.h"
28 #include "net/base/completion_callback.h" 28 #include "net/base/completion_callback.h"
29 #include "net/base/io_buffer.h" 29 #include "net/base/io_buffer.h"
30 #include "net/base/ip_endpoint.h" 30 #include "net/base/ip_endpoint.h"
31 #include "net/base/net_errors.h" 31 #include "net/base/net_errors.h"
32 #include "net/base/network_interfaces.h" 32 #include "net/base/network_interfaces.h"
33 #include "net/http/http_response_headers.h" 33 #include "net/http/http_response_headers.h"
34 #include "net/http/http_util.h" 34 #include "net/http/http_util.h"
(...skipping 12 matching lines...) Expand all
47 using content::BrowserThread; 47 using content::BrowserThread;
48 using net::HttpResponseHeaders; 48 using net::HttpResponseHeaders;
49 using net::HttpUtil; 49 using net::HttpUtil;
50 using net::IOBufferWithSize; 50 using net::IOBufferWithSize;
51 using net::IPAddress; 51 using net::IPAddress;
52 using net::NetworkInterface; 52 using net::NetworkInterface;
53 using net::NetworkInterfaceList; 53 using net::NetworkInterfaceList;
54 using net::StringIOBuffer; 54 using net::StringIOBuffer;
55 using net::UDPSocket; 55 using net::UDPSocket;
56 56
57 namespace extensions { 57 namespace media_router {
58 namespace api {
59 namespace dial {
60 58
61 namespace { 59 namespace {
62 60
63 // The total number of requests to make per discovery cycle. 61 // The total number of requests to make per discovery cycle.
64 const int kDialMaxRequests = 4; 62 const int kDialMaxRequests = 4;
65 63
66 // The interval to wait between successive requests. 64 // The interval to wait between successive requests.
67 const int kDialRequestIntervalMillis = 1000; 65 const int kDialRequestIntervalMillis = 1000;
68 66
69 // The maximum delay a device may wait before responding (MX). 67 // The maximum delay a device may wait before responding (MX).
(...skipping 14 matching lines...) Expand all
84 // SSDP headers parsed from the response. 82 // SSDP headers parsed from the response.
85 const char kSsdpLocationHeader[] = "LOCATION"; 83 const char kSsdpLocationHeader[] = "LOCATION";
86 const char kSsdpCacheControlHeader[] = "CACHE-CONTROL"; 84 const char kSsdpCacheControlHeader[] = "CACHE-CONTROL";
87 const char kSsdpConfigIdHeader[] = "CONFIGID.UPNP.ORG"; 85 const char kSsdpConfigIdHeader[] = "CONFIGID.UPNP.ORG";
88 const char kSsdpUsnHeader[] = "USN"; 86 const char kSsdpUsnHeader[] = "USN";
89 87
90 // The receive buffer size, in bytes. 88 // The receive buffer size, in bytes.
91 const int kDialRecvBufferSize = 1500; 89 const int kDialRecvBufferSize = 1500;
92 90
93 // Gets a specific header from |headers| and puts it in |value|. 91 // Gets a specific header from |headers| and puts it in |value|.
94 bool GetHeader(HttpResponseHeaders* headers, const char* name, 92 bool GetHeader(HttpResponseHeaders* headers,
93 const char* name,
95 std::string* value) { 94 std::string* value) {
96 return headers->EnumerateHeader(nullptr, std::string(name), value); 95 return headers->EnumerateHeader(nullptr, std::string(name), value);
97 } 96 }
98 97
99 // Returns the request string. 98 // Returns the request string.
100 std::string BuildRequest() { 99 std::string BuildRequest() {
101 // Extra line at the end to make UPnP lib happy. 100 // Extra line at the end to make UPnP lib happy.
102 std::string request(base::StringPrintf( 101 std::string request(base::StringPrintf(
103 "M-SEARCH * HTTP/1.1\r\n" 102 "M-SEARCH * HTTP/1.1\r\n"
104 "HOST: %s:%u\r\n" 103 "HOST: %s:%u\r\n"
105 "MAN: \"ssdp:discover\"\r\n" 104 "MAN: \"ssdp:discover\"\r\n"
106 "MX: %d\r\n" 105 "MX: %d\r\n"
107 "ST: %s\r\n" 106 "ST: %s\r\n"
108 "USER-AGENT: %s/%s %s\r\n" 107 "USER-AGENT: %s/%s %s\r\n"
109 "\r\n", 108 "\r\n",
110 kDialRequestAddress, 109 kDialRequestAddress, kDialRequestPort, kDialMaxResponseDelaySecs,
111 kDialRequestPort, 110 kDialSearchType, version_info::GetProductName().c_str(),
112 kDialMaxResponseDelaySecs,
113 kDialSearchType,
114 version_info::GetProductName().c_str(),
115 version_info::GetVersionNumber().c_str(), 111 version_info::GetVersionNumber().c_str(),
116 version_info::GetOSType().c_str())); 112 version_info::GetOSType().c_str()));
117 // 1500 is a good MTU value for most Ethernet LANs. 113 // 1500 is a good MTU value for most Ethernet LANs.
118 DCHECK_LE(request.size(), 1500U); 114 DCHECK_LE(request.size(), 1500U);
119 return request; 115 return request;
120 } 116 }
121 117
122 #if defined(OS_CHROMEOS) 118 #if defined(OS_CHROMEOS)
123 // Finds the IP address of the preferred interface of network type |type| 119 // Finds the IP address of the preferred interface of network type |type|
124 // to bind the socket and inserts the address into |bind_address_list|. This 120 // to bind the socket and inserts the address into |bind_address_list|. This
125 // ChromeOS version can prioritize wifi and ethernet interfaces. 121 // ChromeOS version can prioritize wifi and ethernet interfaces.
126 void InsertBestBindAddressChromeOS(const chromeos::NetworkTypePattern& type, 122 void InsertBestBindAddressChromeOS(const chromeos::NetworkTypePattern& type,
127 net::IPAddressList* bind_address_list) { 123 net::IPAddressList* bind_address_list) {
128 const chromeos::NetworkState* state = chromeos::NetworkHandler::Get() 124 const chromeos::NetworkState* state = chromeos::NetworkHandler::Get()
129 ->network_state_handler()->ConnectedNetworkByType(type); 125 ->network_state_handler()
126 ->ConnectedNetworkByType(type);
130 IPAddress bind_ip_address; 127 IPAddress bind_ip_address;
131 if (state && bind_ip_address.AssignFromIPLiteral(state->ip_address()) && 128 if (state && bind_ip_address.AssignFromIPLiteral(state->ip_address()) &&
132 bind_ip_address.IsIPv4()) { 129 bind_ip_address.IsIPv4()) {
133 VLOG(2) << "Found " << state->type() << ", " << state->name() << ": " 130 VLOG(2) << "Found " << state->type() << ", " << state->name() << ": "
134 << state->ip_address(); 131 << state->ip_address();
135 bind_address_list->push_back(bind_ip_address); 132 bind_address_list->push_back(bind_ip_address);
136 } 133 }
137 } 134 }
138 #else 135 #else
139 NetworkInterfaceList GetNetworkListOnFileThread() { 136 NetworkInterfaceList GetNetworkListOnFileThread() {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 VLOG(1) << "Socket not connected."; 194 VLOG(1) << "Socket not connected.";
198 return; 195 return;
199 } 196 }
200 197
201 if (is_writing_) { 198 if (is_writing_) {
202 VLOG(1) << "Already writing."; 199 VLOG(1) << "Already writing.";
203 return; 200 return;
204 } 201 }
205 202
206 is_writing_ = true; 203 is_writing_ = true;
207 int result = socket_->SendTo( 204 int result =
208 send_buffer.get(), send_buffer->size(), send_address, 205 socket_->SendTo(send_buffer.get(), send_buffer->size(), send_address,
209 base::Bind(&DialServiceImpl::DialSocket::OnSocketWrite, 206 base::Bind(&DialServiceImpl::DialSocket::OnSocketWrite,
210 base::Unretained(this), 207 base::Unretained(this), send_buffer->size()));
211 send_buffer->size()));
212 bool result_ok = CheckResult("SendTo", result); 208 bool result_ok = CheckResult("SendTo", result);
213 if (result_ok && result > 0) { 209 if (result_ok && result > 0) {
214 // Synchronous write. 210 // Synchronous write.
215 OnSocketWrite(send_buffer->size(), result); 211 OnSocketWrite(send_buffer->size(), result);
216 } 212 }
217 } 213 }
218 214
219 bool DialServiceImpl::DialSocket::IsClosed() { 215 bool DialServiceImpl::DialSocket::IsClosed() {
220 DCHECK_CURRENTLY_ON(BrowserThread::IO); 216 DCHECK_CURRENTLY_ON(BrowserThread::IO);
221 return !socket_; 217 return !socket_;
(...skipping 20 matching lines...) Expand all
242 socket_.reset(); 238 socket_.reset();
243 } 239 }
244 240
245 void DialServiceImpl::DialSocket::OnSocketWrite(int send_buffer_size, 241 void DialServiceImpl::DialSocket::OnSocketWrite(int send_buffer_size,
246 int result) { 242 int result) {
247 DCHECK_CURRENTLY_ON(BrowserThread::IO); 243 DCHECK_CURRENTLY_ON(BrowserThread::IO);
248 is_writing_ = false; 244 is_writing_ = false;
249 if (!CheckResult("OnSocketWrite", result)) 245 if (!CheckResult("OnSocketWrite", result))
250 return; 246 return;
251 if (result != send_buffer_size) { 247 if (result != send_buffer_size) {
252 VLOG(1) << "Sent " << result << " chars, expected " 248 VLOG(1) << "Sent " << result << " chars, expected " << send_buffer_size
253 << send_buffer_size << " chars"; 249 << " chars";
254 } 250 }
255 discovery_request_cb_.Run(); 251 discovery_request_cb_.Run();
256 } 252 }
257 253
258 bool DialServiceImpl::DialSocket::ReadSocket() { 254 bool DialServiceImpl::DialSocket::ReadSocket() {
259 DCHECK_CURRENTLY_ON(BrowserThread::IO); 255 DCHECK_CURRENTLY_ON(BrowserThread::IO);
260 if (!socket_) { 256 if (!socket_) {
261 VLOG(1) << "Socket not connected."; 257 VLOG(1) << "Socket not connected.";
262 return false; 258 return false;
263 } 259 }
264 260
265 if (is_reading_) { 261 if (is_reading_) {
266 VLOG(1) << "Already reading."; 262 VLOG(1) << "Already reading.";
267 return false; 263 return false;
268 } 264 }
269 265
270 int result = net::OK; 266 int result = net::OK;
271 bool result_ok = true; 267 bool result_ok = true;
272 do { 268 do {
273 is_reading_ = true; 269 is_reading_ = true;
274 result = socket_->RecvFrom( 270 result = socket_->RecvFrom(
275 recv_buffer_.get(), 271 recv_buffer_.get(), kDialRecvBufferSize, &recv_address_,
276 kDialRecvBufferSize, &recv_address_,
277 base::Bind(&DialServiceImpl::DialSocket::OnSocketRead, 272 base::Bind(&DialServiceImpl::DialSocket::OnSocketRead,
278 base::Unretained(this))); 273 base::Unretained(this)));
279 result_ok = CheckResult("RecvFrom", result); 274 result_ok = CheckResult("RecvFrom", result);
280 if (result != net::ERR_IO_PENDING) 275 if (result != net::ERR_IO_PENDING)
281 is_reading_ = false; 276 is_reading_ = false;
282 if (result_ok && result > 0) { 277 if (result_ok && result > 0) {
283 // Synchronous read. 278 // Synchronous read.
284 HandleResponse(result); 279 HandleResponse(result);
285 } 280 }
286 } while (result_ok && result != net::OK && result != net::ERR_IO_PENDING); 281 } while (result_ok && result != net::OK && result != net::ERR_IO_PENDING);
(...skipping 25 matching lines...) Expand all
312 std::string response(recv_buffer_->data(), bytes_read); 307 std::string response(recv_buffer_->data(), bytes_read);
313 Time response_time = Time::Now(); 308 Time response_time = Time::Now();
314 309
315 // Attempt to parse response, notify observers if successful. 310 // Attempt to parse response, notify observers if successful.
316 DialDeviceData parsed_device; 311 DialDeviceData parsed_device;
317 if (ParseResponse(response, response_time, &parsed_device)) 312 if (ParseResponse(response, response_time, &parsed_device))
318 device_discovered_cb_.Run(parsed_device); 313 device_discovered_cb_.Run(parsed_device);
319 } 314 }
320 315
321 // static 316 // static
322 bool DialServiceImpl::DialSocket::ParseResponse( 317 bool DialServiceImpl::DialSocket::ParseResponse(const std::string& response,
323 const std::string& response, 318 const base::Time& response_time,
324 const base::Time& response_time, 319 DialDeviceData* device) {
325 DialDeviceData* device) { 320 int headers_end =
326 int headers_end = HttpUtil::LocateEndOfHeaders(response.c_str(), 321 HttpUtil::LocateEndOfHeaders(response.c_str(), response.size());
327 response.size());
328 if (headers_end < 1) { 322 if (headers_end < 1) {
329 VLOG(1) << "Headers invalid or empty, ignoring: " << response; 323 VLOG(1) << "Headers invalid or empty, ignoring: " << response;
330 return false; 324 return false;
331 } 325 }
332 std::string raw_headers = 326 std::string raw_headers =
333 HttpUtil::AssembleRawHeaders(response.c_str(), headers_end); 327 HttpUtil::AssembleRawHeaders(response.c_str(), headers_end);
334 VLOG(3) << "raw_headers: " << raw_headers << "\n"; 328 VLOG(3) << "raw_headers: " << raw_headers << "\n";
335 scoped_refptr<HttpResponseHeaders> headers = 329 scoped_refptr<HttpResponseHeaders> headers =
336 new HttpResponseHeaders(raw_headers); 330 new HttpResponseHeaders(raw_headers);
337 331
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 // is used to identify unique interfaces. 462 // is used to identify unique interfaces.
469 // TODO(mfoltz): Support IPV6 multicast. http://crbug.com/165286 463 // TODO(mfoltz): Support IPV6 multicast. http://crbug.com/165286
470 for (NetworkInterfaceList::const_iterator iter = networks.begin(); 464 for (NetworkInterfaceList::const_iterator iter = networks.begin();
471 iter != networks.end(); ++iter) { 465 iter != networks.end(); ++iter) {
472 net::AddressFamily addr_family = net::GetAddressFamily(iter->address); 466 net::AddressFamily addr_family = net::GetAddressFamily(iter->address);
473 VLOG(2) << "Found " << iter->name << ", " << iter->address.ToString() 467 VLOG(2) << "Found " << iter->name << ", " << iter->address.ToString()
474 << ", address family: " << addr_family; 468 << ", address family: " << addr_family;
475 if (addr_family == net::ADDRESS_FAMILY_IPV4) { 469 if (addr_family == net::ADDRESS_FAMILY_IPV4) {
476 InterfaceIndexAddressFamily interface_index_addr_family = 470 InterfaceIndexAddressFamily interface_index_addr_family =
477 std::make_pair(iter->interface_index, addr_family); 471 std::make_pair(iter->interface_index, addr_family);
478 bool inserted = interface_index_addr_family_seen 472 bool inserted =
479 .insert(interface_index_addr_family) 473 interface_index_addr_family_seen.insert(interface_index_addr_family)
480 .second; 474 .second;
481 // We have not seen this interface before, so add its IP address to the 475 // We have not seen this interface before, so add its IP address to the
482 // discovery list. 476 // discovery list.
483 if (inserted) { 477 if (inserted) {
484 VLOG(2) << "Encountered " 478 VLOG(2) << "Encountered "
485 << "interface index: " << iter->interface_index << ", " 479 << "interface index: " << iter->interface_index << ", "
486 << "address family: " << addr_family << " for the first time, " 480 << "address family: " << addr_family << " for the first time, "
487 << "adding IP address " << iter->address.ToString() 481 << "adding IP address " << iter->address.ToString()
488 << " to list."; 482 << " to list.";
489 ip_addresses.push_back(iter->address); 483 ip_addresses.push_back(iter->address);
490 } else { 484 } else {
(...skipping 11 matching lines...) Expand all
502 const net::IPAddressList& ip_addresses) { 496 const net::IPAddressList& ip_addresses) {
503 if (ip_addresses.empty()) { 497 if (ip_addresses.empty()) {
504 VLOG(1) << "Could not find a valid interface to bind. Finishing discovery"; 498 VLOG(1) << "Could not find a valid interface to bind. Finishing discovery";
505 FinishDiscovery(); 499 FinishDiscovery();
506 return; 500 return;
507 } 501 }
508 502
509 // Schedule a timer to finish the discovery process (and close the sockets). 503 // Schedule a timer to finish the discovery process (and close the sockets).
510 if (finish_delay_ > TimeDelta::FromSeconds(0)) { 504 if (finish_delay_ > TimeDelta::FromSeconds(0)) {
511 VLOG(2) << "Starting timer to finish discovery."; 505 VLOG(2) << "Starting timer to finish discovery.";
512 finish_timer_.Start(FROM_HERE, 506 finish_timer_.Start(FROM_HERE, finish_delay_, this,
513 finish_delay_,
514 this,
515 &DialServiceImpl::FinishDiscovery); 507 &DialServiceImpl::FinishDiscovery);
516 } 508 }
517 509
518 for (const auto& address : ip_addresses) { 510 for (const auto& address : ip_addresses) {
519 BindAndAddSocket(address); 511 BindAndAddSocket(address);
520 } 512 }
521 513
522 SendOneRequest(); 514 SendOneRequest();
523 } 515 }
524 516
(...skipping 15 matching lines...) Expand all
540 } 532 }
541 533
542 void DialServiceImpl::SendOneRequest() { 534 void DialServiceImpl::SendOneRequest() {
543 DCHECK_CURRENTLY_ON(BrowserThread::IO); 535 DCHECK_CURRENTLY_ON(BrowserThread::IO);
544 if (num_requests_sent_ == max_requests_) { 536 if (num_requests_sent_ == max_requests_) {
545 VLOG(2) << "Reached max requests; stopping request timer."; 537 VLOG(2) << "Reached max requests; stopping request timer.";
546 request_timer_.Stop(); 538 request_timer_.Stop();
547 return; 539 return;
548 } 540 }
549 num_requests_sent_++; 541 num_requests_sent_++;
550 VLOG(2) << "Sending request " << num_requests_sent_ << "/" 542 VLOG(2) << "Sending request " << num_requests_sent_ << "/" << max_requests_;
551 << max_requests_;
552 for (const auto& socket : dial_sockets_) { 543 for (const auto& socket : dial_sockets_) {
553 if (!socket->IsClosed()) 544 if (!socket->IsClosed())
554 socket->SendOneRequest(send_address_, send_buffer_); 545 socket->SendOneRequest(send_address_, send_buffer_);
555 } 546 }
556 } 547 }
557 548
558 void DialServiceImpl::NotifyOnDiscoveryRequest() { 549 void DialServiceImpl::NotifyOnDiscoveryRequest() {
559 DCHECK_CURRENTLY_ON(BrowserThread::IO); 550 DCHECK_CURRENTLY_ON(BrowserThread::IO);
560 // If discovery is inactive, no reason to notify observers. 551 // If discovery is inactive, no reason to notify observers.
561 if (!discovery_active_) { 552 if (!discovery_active_) {
562 VLOG(2) << "Request sent after discovery finished. Ignoring."; 553 VLOG(2) << "Request sent after discovery finished. Ignoring.";
563 return; 554 return;
564 } 555 }
565 556
566 VLOG(2) << "Notifying observers of discovery request"; 557 VLOG(2) << "Notifying observers of discovery request";
567 for (auto& observer : observer_list_) 558 for (auto& observer : observer_list_)
568 observer.OnDiscoveryRequest(this); 559 observer.OnDiscoveryRequest(this);
569 // If we need to send additional requests, schedule a timer to do so. 560 // If we need to send additional requests, schedule a timer to do so.
570 if (num_requests_sent_ < max_requests_ && num_requests_sent_ == 1) { 561 if (num_requests_sent_ < max_requests_ && num_requests_sent_ == 1) {
571 VLOG(2) << "Scheduling timer to send additional requests"; 562 VLOG(2) << "Scheduling timer to send additional requests";
572 // TODO(imcheng): Move this to SendOneRequest() once the implications are 563 // TODO(imcheng): Move this to SendOneRequest() once the implications are
573 // understood. 564 // understood.
574 request_timer_.Start(FROM_HERE, 565 request_timer_.Start(FROM_HERE, request_interval_, this,
575 request_interval_,
576 this,
577 &DialServiceImpl::SendOneRequest); 566 &DialServiceImpl::SendOneRequest);
578 } 567 }
579 } 568 }
580 569
581 void DialServiceImpl::NotifyOnDeviceDiscovered( 570 void DialServiceImpl::NotifyOnDeviceDiscovered(
582 const DialDeviceData& device_data) { 571 const DialDeviceData& device_data) {
583 DCHECK_CURRENTLY_ON(BrowserThread::IO); 572 DCHECK_CURRENTLY_ON(BrowserThread::IO);
584 if (!discovery_active_) { 573 if (!discovery_active_) {
585 VLOG(2) << "Got response after discovery finished. Ignoring."; 574 VLOG(2) << "Got response after discovery finished. Ignoring.";
586 return; 575 return;
(...skipping 27 matching lines...) Expand all
614 } 603 }
615 604
616 bool DialServiceImpl::HasOpenSockets() { 605 bool DialServiceImpl::HasOpenSockets() {
617 for (const auto& socket : dial_sockets_) { 606 for (const auto& socket : dial_sockets_) {
618 if (!socket->IsClosed()) 607 if (!socket->IsClosed())
619 return true; 608 return true;
620 } 609 }
621 return false; 610 return false;
622 } 611 }
623 612
624 } // namespace dial 613 } // namespace media_router
625 } // namespace api
626 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698