Commit bf41b7c1 authored by Lily Houghton's avatar Lily Houghton Committed by Commit Bot

Migrate PrivetTrafficDetector from net::DatagramServerSocket to network::mojom::UDPSocket

As part of the network servicification project, this CL replaces the use
of net/ sockets in the PrivetTrafficDetector class with the UDP socket
interfaces in the network service.

Bug: 811497
Change-Id: I0f0295f032684b0e6a32de222760cfeb409c7d21
Reviewed-on: https://chromium-review.googlesource.com/1127268Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatarHelen Li <xunjieli@chromium.org>
Commit-Queue: Lily Houghton <lilyhoughton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577225}
parent bcde09d4
...@@ -337,10 +337,10 @@ void PrivetNotificationService::OnNotificationsEnabledChanged() { ...@@ -337,10 +337,10 @@ void PrivetNotificationService::OnNotificationsEnabledChanged() {
StartLister(); StartLister();
} else if (*enable_privet_notification_member_) { } else if (*enable_privet_notification_member_) {
ReportPrivetUmaEvent(PRIVET_SERVICE_STARTED); ReportPrivetUmaEvent(PRIVET_SERVICE_STARTED);
traffic_detector_ = traffic_detector_ = base::MakeRefCounted<PrivetTrafficDetector>(
new PrivetTrafficDetector( net::ADDRESS_FAMILY_IPV4, profile_,
net::ADDRESS_FAMILY_IPV4, base::BindRepeating(&PrivetNotificationService::StartLister,
base::Bind(&PrivetNotificationService::StartLister, AsWeakPtr())); AsWeakPtr()));
traffic_detector_->Start(); traffic_detector_->Start();
} else { } else {
device_lister_.reset(); device_lister_.reset();
......
...@@ -15,16 +15,13 @@ ...@@ -15,16 +15,13 @@
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/storage_partition.h"
#include "net/base/ip_address.h" #include "net/base/ip_address.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/base/network_change_notifier.h"
#include "net/base/network_interfaces.h" #include "net/base/network_interfaces.h"
#include "net/dns/dns_protocol.h" #include "net/dns/dns_protocol.h"
#include "net/dns/dns_response.h"
#include "net/dns/mdns_client.h" #include "net/dns/mdns_client.h"
#include "net/log/net_log_source.h"
#include "net/socket/datagram_server_socket.h"
#include "net/socket/udp_server_socket.h"
namespace { namespace {
...@@ -67,13 +64,14 @@ namespace cloud_print { ...@@ -67,13 +64,14 @@ namespace cloud_print {
PrivetTrafficDetector::PrivetTrafficDetector( PrivetTrafficDetector::PrivetTrafficDetector(
net::AddressFamily address_family, net::AddressFamily address_family,
content::BrowserContext* profile,
const base::Closure& on_traffic_detected) const base::Closure& on_traffic_detected)
: on_traffic_detected_(on_traffic_detected), : on_traffic_detected_(on_traffic_detected),
callback_runner_(base::ThreadTaskRunnerHandle::Get()), callback_runner_(base::ThreadTaskRunnerHandle::Get()),
address_family_(address_family), address_family_(address_family),
io_buffer_(
new net::IOBufferWithSize(net::dns_protocol::kMaxMulticastSize)),
restart_attempts_(kMaxRestartAttempts), restart_attempts_(kMaxRestartAttempts),
receiver_binding_(this),
profile_(profile),
weak_ptr_factory_(this) {} weak_ptr_factory_(this) {}
PrivetTrafficDetector::~PrivetTrafficDetector() { PrivetTrafficDetector::~PrivetTrafficDetector() {
...@@ -96,15 +94,6 @@ void PrivetTrafficDetector::Stop() { ...@@ -96,15 +94,6 @@ void PrivetTrafficDetector::Stop() {
->RemoveNetworkConnectionObserver(this); ->RemoveNetworkConnectionObserver(this);
} }
void PrivetTrafficDetector::OnConnectionChanged(
network::mojom::ConnectionType type) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&PrivetTrafficDetector::HandleConnectionChanged,
weak_ptr_factory_.GetWeakPtr(), type));
}
void PrivetTrafficDetector::HandleConnectionChanged( void PrivetTrafficDetector::HandleConnectionChanged(
network::mojom::ConnectionType type) { network::mojom::ConnectionType type) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
...@@ -116,7 +105,7 @@ void PrivetTrafficDetector::HandleConnectionChanged( ...@@ -116,7 +105,7 @@ void PrivetTrafficDetector::HandleConnectionChanged(
void PrivetTrafficDetector::ScheduleRestart() { void PrivetTrafficDetector::ScheduleRestart() {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
socket_.reset(); ResetConnection();
weak_ptr_factory_.InvalidateWeakPtrs(); weak_ptr_factory_.InvalidateWeakPtrs();
base::PostDelayedTaskWithTraits( base::PostDelayedTaskWithTraits(
FROM_HERE, {base::TaskPriority::BACKGROUND, base::MayBlock()}, FROM_HERE, {base::TaskPriority::BACKGROUND, base::MayBlock()},
...@@ -129,33 +118,64 @@ void PrivetTrafficDetector::ScheduleRestart() { ...@@ -129,33 +118,64 @@ void PrivetTrafficDetector::ScheduleRestart() {
void PrivetTrafficDetector::Restart(const net::NetworkInterfaceList& networks) { void PrivetTrafficDetector::Restart(const net::NetworkInterfaceList& networks) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
networks_ = networks; networks_ = networks;
if (Bind() < net::OK || DoLoop(0) < net::OK) { Bind();
if ((restart_attempts_--) > 0)
ScheduleRestart();
} else {
// Reset on success.
restart_attempts_ = kMaxRestartAttempts;
}
} }
int PrivetTrafficDetector::Bind() { void PrivetTrafficDetector::Bind() {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (!start_time_.is_null()) { if (!start_time_.is_null()) {
base::TimeDelta time_delta = base::Time::Now() - start_time_; base::TimeDelta time_delta = base::Time::Now() - start_time_;
UMA_HISTOGRAM_LONG_TIMES("LocalDiscovery.DetectorRestartTime", time_delta); UMA_HISTOGRAM_LONG_TIMES("LocalDiscovery.DetectorRestartTime", time_delta);
} }
start_time_ = base::Time::Now(); start_time_ = base::Time::Now();
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
socket_.reset(new net::UDPServerSocket(NULL, net::NetLogSource())); network::mojom::UDPSocketReceiverPtr receiver_ptr;
network::mojom::UDPSocketReceiverRequest receiver_request =
mojo::MakeRequest(&receiver_ptr);
receiver_binding_.Bind(std::move(receiver_request));
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::BindOnce(&PrivetTrafficDetector::CreateUDPSocketOnUIThread, this,
mojo::MakeRequest(&socket_), std::move(receiver_ptr)));
net::IPEndPoint multicast_addr = net::GetMDnsIPEndPoint(address_family_); net::IPEndPoint multicast_addr = net::GetMDnsIPEndPoint(address_family_);
net::IPEndPoint bind_endpoint( net::IPEndPoint bind_endpoint(
net::IPAddress::AllZeros(multicast_addr.address().size()), net::IPAddress::AllZeros(multicast_addr.address().size()),
multicast_addr.port()); multicast_addr.port());
socket_->AllowAddressReuse();
int rv = socket_->Listen(bind_endpoint); network::mojom::UDPSocketOptionsPtr socket_options =
if (rv < net::OK) network::mojom::UDPSocketOptions::New();
return rv; socket_options->allow_address_reuse = true;
socket_->SetMulticastLoopbackMode(false); socket_options->multicast_loopback_mode = false;
return socket_->JoinGroup(multicast_addr.address());
socket_->Bind(bind_endpoint, std::move(socket_options),
base::BindOnce(&PrivetTrafficDetector::OnBindComplete, this,
multicast_addr));
}
void PrivetTrafficDetector::CreateUDPSocketOnUIThread(
network::mojom::UDPSocketRequest request,
network::mojom::UDPSocketReceiverPtr receiver_ptr) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
network::mojom::NetworkContext* network_context =
content::BrowserContext::GetDefaultStoragePartition(profile_)
->GetNetworkContext();
network_context->CreateUDPSocket(std::move(request), std::move(receiver_ptr));
}
void PrivetTrafficDetector::OnBindComplete(
net::IPEndPoint multicast_addr,
int rv,
const base::Optional<net::IPEndPoint>& ip_endpoint) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (rv != net::OK) {
if ((restart_attempts_--) > 0)
ScheduleRestart();
} else {
socket_->JoinGroup(
multicast_addr.address(),
base::BindOnce(&PrivetTrafficDetector::OnJoinGroupComplete, this));
}
} }
bool PrivetTrafficDetector::IsSourceAcceptable() const { bool PrivetTrafficDetector::IsSourceAcceptable() const {
...@@ -168,14 +188,15 @@ bool PrivetTrafficDetector::IsSourceAcceptable() const { ...@@ -168,14 +188,15 @@ bool PrivetTrafficDetector::IsSourceAcceptable() const {
return false; return false;
} }
bool PrivetTrafficDetector::IsPrivetPacket(int rv) const { bool PrivetTrafficDetector::IsPrivetPacket(
if (rv <= static_cast<int>(sizeof(net::dns_protocol::Header)) || base::span<const uint8_t> data) const {
if (data.size() <= sizeof(net::dns_protocol::Header) ||
!IsSourceAcceptable()) { !IsSourceAcceptable()) {
return false; return false;
} }
const char* buffer_begin = io_buffer_->data(); const char* buffer_begin = reinterpret_cast<const char*>(data.data());
const char* buffer_end = buffer_begin + rv; const char* buffer_end = buffer_begin + data.size();
const net::dns_protocol::Header* header = const net::dns_protocol::Header* header =
reinterpret_cast<const net::dns_protocol::Header*>(buffer_begin); reinterpret_cast<const net::dns_protocol::Header*>(buffer_begin);
// Check if response packet. // Check if response packet.
...@@ -189,30 +210,52 @@ bool PrivetTrafficDetector::IsPrivetPacket(int rv) const { ...@@ -189,30 +210,52 @@ bool PrivetTrafficDetector::IsPrivetPacket(int rv) const {
substring_end) != buffer_end; substring_end) != buffer_end;
} }
int PrivetTrafficDetector::DoLoop(int rv) { void PrivetTrafficDetector::OnJoinGroupComplete(int rv) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
do { if (rv != net::OK) {
if (IsPrivetPacket(rv)) { if ((restart_attempts_--) > 0)
socket_.reset(); ScheduleRestart();
callback_runner_->PostTask(FROM_HERE, on_traffic_detected_); } else {
base::TimeDelta time_delta = base::Time::Now() - start_time_; // Reset on success.
UMA_HISTOGRAM_LONG_TIMES("LocalDiscovery.DetectorTriggerTime", restart_attempts_ = kMaxRestartAttempts;
time_delta); socket_->ReceiveMoreWithBufferSize(1, net::dns_protocol::kMaxMulticastSize);
return net::OK;
} }
}
void PrivetTrafficDetector::ResetConnection() {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
socket_.reset();
receiver_binding_.Close();
}
rv = socket_->RecvFrom( void PrivetTrafficDetector::OnConnectionChanged(
io_buffer_.get(), network::mojom::ConnectionType type) {
io_buffer_->size(), DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
&recv_addr_, content::BrowserThread::PostTask(
base::Bind(base::IgnoreResult(&PrivetTrafficDetector::DoLoop), content::BrowserThread::IO, FROM_HERE,
base::Unretained(this))); base::BindOnce(&PrivetTrafficDetector::HandleConnectionChanged,
} while (rv > 0); weak_ptr_factory_.GetWeakPtr(), type));
}
if (rv != net::ERR_IO_PENDING) void PrivetTrafficDetector::OnReceived(
return rv; int32_t result,
const base::Optional<net::IPEndPoint>& src_addr,
base::Optional<base::span<const uint8_t>> data) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (result != net::OK)
return;
return net::OK; // |data| and |src_addr| are guaranteed to be non-null when |result| is
// net::OK
recv_addr_ = src_addr.value();
if (IsPrivetPacket(data.value())) {
ResetConnection();
callback_runner_->PostTask(FROM_HERE, on_traffic_detected_);
base::TimeDelta time_delta = base::Time::Now() - start_time_;
UMA_HISTOGRAM_LONG_TIMES("LocalDiscovery.DetectorTriggerTime", time_delta);
} else {
socket_->ReceiveMoreWithBufferSize(1, net::dns_protocol::kMaxMulticastSize);
}
} }
} // namespace cloud_print } // namespace cloud_print
...@@ -12,12 +12,13 @@ ...@@ -12,12 +12,13 @@
#include "base/macros.h" #include "base/macros.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_connection_tracker.h" #include "content/public/browser/network_connection_tracker.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/base/address_family.h" #include "net/base/address_family.h"
#include "net/base/ip_endpoint.h" #include "net/base/ip_endpoint.h"
#include "services/network/public/mojom/udp_socket.mojom.h"
namespace net { namespace content {
class DatagramServerSocket; class BrowserContext;
class IOBufferWithSize;
} }
namespace cloud_print { namespace cloud_print {
...@@ -30,9 +31,11 @@ class PrivetTrafficDetector ...@@ -30,9 +31,11 @@ class PrivetTrafficDetector
: public base::RefCountedThreadSafe< : public base::RefCountedThreadSafe<
PrivetTrafficDetector, PrivetTrafficDetector,
content::BrowserThread::DeleteOnIOThread>, content::BrowserThread::DeleteOnIOThread>,
private content::NetworkConnectionTracker::NetworkConnectionObserver { private content::NetworkConnectionTracker::NetworkConnectionObserver,
public network::mojom::UDPSocketReceiver {
public: public:
PrivetTrafficDetector(net::AddressFamily address_family, PrivetTrafficDetector(net::AddressFamily address_family,
content::BrowserContext* profile,
const base::Closure& on_traffic_detected); const base::Closure& on_traffic_detected);
void Start(); void Start();
...@@ -44,27 +47,49 @@ class PrivetTrafficDetector ...@@ -44,27 +47,49 @@ class PrivetTrafficDetector
friend class base::DeleteHelper<PrivetTrafficDetector>; friend class base::DeleteHelper<PrivetTrafficDetector>;
~PrivetTrafficDetector() override; ~PrivetTrafficDetector() override;
// content::NetworkConnectionTracker::NetworkConnectionObserver:
void OnConnectionChanged(network::mojom::ConnectionType type) override;
void HandleConnectionChanged(network::mojom::ConnectionType type); void HandleConnectionChanged(network::mojom::ConnectionType type);
void StartOnIOThread();
void ScheduleRestart(); void ScheduleRestart();
void Restart(const net::NetworkInterfaceList& networks); void Restart(const net::NetworkInterfaceList& networks);
int Bind(); void Bind();
void CreateUDPSocketOnUIThread(
network::mojom::UDPSocketRequest request,
network::mojom::UDPSocketReceiverPtr receiver_ptr);
void OnBindComplete(net::IPEndPoint multicast_addr,
int rv,
const base::Optional<net::IPEndPoint>& ip_address);
bool IsSourceAcceptable() const; bool IsSourceAcceptable() const;
bool IsPrivetPacket(int rv) const; bool IsPrivetPacket(base::span<const uint8_t> data) const;
int DoLoop(int rv); void OnJoinGroupComplete(int rv);
void ResetConnection();
// content::NetworkConnectionTracker::NetworkConnectionObserver:
void OnConnectionChanged(network::mojom::ConnectionType type) override;
// network::mojom::UDPSocketReceiver implementation
void OnReceived(int32_t result,
const base::Optional<net::IPEndPoint>& src_addr,
base::Optional<base::span<const uint8_t>> data) override;
base::Closure on_traffic_detected_; base::Closure on_traffic_detected_;
scoped_refptr<base::TaskRunner> callback_runner_; scoped_refptr<base::TaskRunner> callback_runner_;
net::NetworkInterfaceList networks_; net::NetworkInterfaceList networks_;
net::AddressFamily address_family_; net::AddressFamily address_family_;
net::IPEndPoint recv_addr_; net::IPEndPoint recv_addr_;
std::unique_ptr<net::DatagramServerSocket> socket_;
scoped_refptr<net::IOBufferWithSize> io_buffer_;
base::Time start_time_; base::Time start_time_;
int restart_attempts_; int restart_attempts_;
// Only accessed on the IO thread
network::mojom::UDPSocketPtr socket_;
// Implementation of socket receiver callback
mojo::Binding<network::mojom::UDPSocketReceiver> receiver_binding_;
// Only accessed on the UI thread
content::BrowserContext* const profile_;
base::WeakPtrFactory<PrivetTrafficDetector> weak_ptr_factory_; base::WeakPtrFactory<PrivetTrafficDetector> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PrivetTrafficDetector); DISALLOW_COPY_AND_ASSIGN(PrivetTrafficDetector);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment