Commit f35977d9 authored by Helen Li's avatar Helen Li Committed by Commit Bot

Add TCP socket API to network service

This CL adds TCP socket API to network service.
This is partly based on mandoline implementation
(https://codereview.chromium.org/1873463003/)

Two TCP socket interfaces are added.
- TCPConnectedSocket
- TCPServerSocket

TBR=miu@chromium.org

Bug: 721401
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_mojo
Change-Id: I56e2702c02b9c86a72eba68c85391c3b017a4d64
Reviewed-on: https://chromium-review.googlesource.com/868711Reviewed-by: default avatarHelen Li <xunjieli@chromium.org>
Reviewed-by: default avatarMatt Menke <mmenke@chromium.org>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarRamin Halavati <rhalavati@chromium.org>
Commit-Queue: Helen Li <xunjieli@chromium.org>
Cr-Commit-Position: refs/heads/master@{#542606}
parent ffc26d97
...@@ -138,8 +138,21 @@ class MockNetworkContext final : public network::mojom::NetworkContext { ...@@ -138,8 +138,21 @@ class MockNetworkContext final : public network::mojom::NetworkContext {
std::move(receiver)); std::move(receiver));
OnUDPSocketCreated(); OnUDPSocketCreated();
} }
void CreateTCPServerSocket(
MockUdpSocket* udp_socket() const { return udp_socket_.get(); }; const net::IPEndPoint& local_addr,
uint32_t backlog,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
network::mojom::TCPServerSocketRequest request,
CreateTCPServerSocketCallback callback) override {}
void CreateTCPConnectedSocket(
const base::Optional<net::IPEndPoint>& local_addr,
const net::AddressList& remote_addr_list,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
network::mojom::TCPConnectedSocketRequest request,
network::mojom::TCPConnectedSocketObserverPtr observer,
CreateTCPConnectedSocketCallback callback) override {}
MockUdpSocket* udp_socket() const { return udp_socket_.get(); }
private: private:
mojo::Binding<network::mojom::NetworkContext> binding_; mojo::Binding<network::mojom::NetworkContext> binding_;
......
...@@ -52,6 +52,12 @@ component("network_service") { ...@@ -52,6 +52,12 @@ component("network_service") {
"resource_scheduler_client.h", "resource_scheduler_client.h",
"restricted_cookie_manager.cc", "restricted_cookie_manager.cc",
"restricted_cookie_manager.h", "restricted_cookie_manager.h",
"socket_factory.cc",
"socket_factory.h",
"tcp_connected_socket.cc",
"tcp_connected_socket.h",
"tcp_server_socket.cc",
"tcp_server_socket.h",
"throttling/network_conditions.cc", "throttling/network_conditions.cc",
"throttling/network_conditions.h", "throttling/network_conditions.h",
"throttling/throttling_controller.cc", "throttling/throttling_controller.cc",
...@@ -66,8 +72,6 @@ component("network_service") { ...@@ -66,8 +72,6 @@ component("network_service") {
"throttling/throttling_upload_data_stream.h", "throttling/throttling_upload_data_stream.h",
"udp_socket.cc", "udp_socket.cc",
"udp_socket.h", "udp_socket.h",
"udp_socket_factory.cc",
"udp_socket_factory.h",
"upload_progress_tracker.cc", "upload_progress_tracker.cc",
"upload_progress_tracker.h", "upload_progress_tracker.h",
"url_loader.cc", "url_loader.cc",
...@@ -139,11 +143,11 @@ source_set("tests") { ...@@ -139,11 +143,11 @@ source_set("tests") {
"proxy_resolving_client_socket_unittest.cc", "proxy_resolving_client_socket_unittest.cc",
"resource_scheduler_unittest.cc", "resource_scheduler_unittest.cc",
"restricted_cookie_manager_unittest.cc", "restricted_cookie_manager_unittest.cc",
"tcp_socket_unittest.cc",
"test/test_url_loader_factory_unittest.cc", "test/test_url_loader_factory_unittest.cc",
"test_chunked_data_pipe_getter.cc", "test_chunked_data_pipe_getter.cc",
"test_chunked_data_pipe_getter.h", "test_chunked_data_pipe_getter.h",
"throttling/throttling_controller_unittest.cc", "throttling/throttling_controller_unittest.cc",
"udp_socket_factory_unittest.cc",
"udp_socket_unittest.cc", "udp_socket_unittest.cc",
"upload_progress_tracker_unittest.cc", "upload_progress_tracker_unittest.cc",
"url_loader_unittest.cc", "url_loader_unittest.cc",
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "net/reporting/reporting_policy.h" #include "net/reporting/reporting_policy.h"
#include "net/ssl/channel_id_service.h" #include "net/ssl/channel_id_service.h"
#include "net/ssl/default_channel_id_store.h" #include "net/ssl/default_channel_id_store.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_builder.h" #include "net/url_request/url_request_context_builder.h"
#include "services/network/http_server_properties_pref_delegate.h" #include "services/network/http_server_properties_pref_delegate.h"
...@@ -49,7 +50,6 @@ ...@@ -49,7 +50,6 @@
#include "services/network/throttling/network_conditions.h" #include "services/network/throttling/network_conditions.h"
#include "services/network/throttling/throttling_controller.h" #include "services/network/throttling/throttling_controller.h"
#include "services/network/throttling/throttling_network_transaction_factory.h" #include "services/network/throttling/throttling_network_transaction_factory.h"
#include "services/network/udp_socket_factory.h"
#include "services/network/url_loader.h" #include "services/network/url_loader.h"
#include "services/network/url_loader_factory.h" #include "services/network/url_loader_factory.h"
#include "services/network/url_request_context_builder_mojo.h" #include "services/network/url_request_context_builder_mojo.h"
...@@ -92,7 +92,8 @@ NetworkContext::NetworkContext(NetworkService* network_service, ...@@ -92,7 +92,8 @@ NetworkContext::NetworkContext(NetworkService* network_service,
mojom::NetworkContextParamsPtr params) mojom::NetworkContextParamsPtr params)
: network_service_(network_service), : network_service_(network_service),
params_(std::move(params)), params_(std::move(params)),
binding_(this, std::move(request)) { binding_(this, std::move(request)),
socket_factory_(network_service_->net_log()) {
url_request_context_owner_ = MakeURLRequestContext(params_.get()); url_request_context_owner_ = MakeURLRequestContext(params_.get());
url_request_context_getter_ = url_request_context_getter_ =
url_request_context_owner_.url_request_context_getter; url_request_context_owner_.url_request_context_getter;
...@@ -115,7 +116,8 @@ NetworkContext::NetworkContext( ...@@ -115,7 +116,8 @@ NetworkContext::NetworkContext(
std::unique_ptr<URLRequestContextBuilderMojo> builder) std::unique_ptr<URLRequestContextBuilderMojo> builder)
: network_service_(network_service), : network_service_(network_service),
params_(std::move(params)), params_(std::move(params)),
binding_(this, std::move(request)) { binding_(this, std::move(request)),
socket_factory_(network_service_->net_log()) {
url_request_context_owner_ = ApplyContextParamsToBuilder( url_request_context_owner_ = ApplyContextParamsToBuilder(
builder.get(), params_.get(), network_service->quic_disabled(), builder.get(), params_.get(), network_service->quic_disabled(),
network_service->net_log()); network_service->net_log());
...@@ -136,8 +138,9 @@ NetworkContext::NetworkContext( ...@@ -136,8 +138,9 @@ NetworkContext::NetworkContext(
url_request_context_getter_(std::move(url_request_context_getter)), url_request_context_getter_(std::move(url_request_context_getter)),
binding_(this, std::move(request)), binding_(this, std::move(request)),
cookie_manager_(std::make_unique<CookieManager>( cookie_manager_(std::make_unique<CookieManager>(
url_request_context_getter_->GetURLRequestContext() url_request_context_getter_->GetURLRequestContext()->cookie_store())),
->cookie_store())) { socket_factory_(network_service_ ? network_service_->net_log()
: nullptr) {
// May be nullptr in tests. // May be nullptr in tests.
if (network_service_) if (network_service_)
network_service_->RegisterNetworkContext(this); network_service_->RegisterNetworkContext(this);
...@@ -222,7 +225,10 @@ void NetworkContext::Cleanup() { ...@@ -222,7 +225,10 @@ void NetworkContext::Cleanup() {
} }
NetworkContext::NetworkContext(mojom::NetworkContextParamsPtr params) NetworkContext::NetworkContext(mojom::NetworkContextParamsPtr params)
: network_service_(nullptr), params_(std::move(params)), binding_(this) { : network_service_(nullptr),
params_(std::move(params)),
binding_(this),
socket_factory_(network_service_->net_log()) {
url_request_context_owner_ = MakeURLRequestContext(params_.get()); url_request_context_owner_ = MakeURLRequestContext(params_.get());
url_request_context_getter_ = url_request_context_getter_ =
url_request_context_owner_.url_request_context_getter; url_request_context_owner_.url_request_context_getter;
...@@ -486,9 +492,32 @@ void NetworkContext::SetNetworkConditions( ...@@ -486,9 +492,32 @@ void NetworkContext::SetNetworkConditions(
void NetworkContext::CreateUDPSocket(mojom::UDPSocketRequest request, void NetworkContext::CreateUDPSocket(mojom::UDPSocketRequest request,
mojom::UDPSocketReceiverPtr receiver) { mojom::UDPSocketReceiverPtr receiver) {
if (!udp_socket_factory_) socket_factory_.CreateUDPSocket(std::move(request), std::move(receiver));
udp_socket_factory_ = std::make_unique<UDPSocketFactory>(); }
udp_socket_factory_->CreateUDPSocket(std::move(request), std::move(receiver));
void NetworkContext::CreateTCPServerSocket(
const net::IPEndPoint& local_addr,
uint32_t backlog,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
mojom::TCPServerSocketRequest request,
CreateTCPServerSocketCallback callback) {
socket_factory_.CreateTCPServerSocket(
local_addr, backlog,
static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
std::move(request), std::move(callback));
}
void NetworkContext::CreateTCPConnectedSocket(
const base::Optional<net::IPEndPoint>& local_addr,
const net::AddressList& remote_addr_list,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
mojom::TCPConnectedSocketRequest request,
mojom::TCPConnectedSocketObserverPtr observer,
CreateTCPConnectedSocketCallback callback) {
socket_factory_.CreateTCPConnectedSocket(
local_addr, remote_addr_list,
static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
std::move(request), std::move(observer), std::move(callback));
} }
void NetworkContext::AddHSTSForTesting(const std::string& host, void NetworkContext::AddHSTSForTesting(const std::string& host,
......
...@@ -20,8 +20,10 @@ ...@@ -20,8 +20,10 @@
#include "services/network/cookie_manager.h" #include "services/network/cookie_manager.h"
#include "services/network/http_cache_data_remover.h" #include "services/network/http_cache_data_remover.h"
#include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/tcp_socket.mojom.h"
#include "services/network/public/mojom/udp_socket.mojom.h" #include "services/network/public/mojom/udp_socket.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/socket_factory.h"
#include "services/network/url_request_context_owner.h" #include "services/network/url_request_context_owner.h"
namespace net { namespace net {
...@@ -33,7 +35,6 @@ namespace network { ...@@ -33,7 +35,6 @@ namespace network {
class NetworkService; class NetworkService;
class ResourceScheduler; class ResourceScheduler;
class ResourceSchedulerClient; class ResourceSchedulerClient;
class UDPSocketFactory;
class URLRequestContextBuilderMojo; class URLRequestContextBuilderMojo;
// A NetworkContext creates and manages access to a URLRequestContext. // A NetworkContext creates and manages access to a URLRequestContext.
...@@ -112,6 +113,19 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ...@@ -112,6 +113,19 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
mojom::NetworkConditionsPtr conditions) override; mojom::NetworkConditionsPtr conditions) override;
void CreateUDPSocket(mojom::UDPSocketRequest request, void CreateUDPSocket(mojom::UDPSocketRequest request,
mojom::UDPSocketReceiverPtr receiver) override; mojom::UDPSocketReceiverPtr receiver) override;
void CreateTCPServerSocket(
const net::IPEndPoint& local_addr,
uint32_t backlog,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
mojom::TCPServerSocketRequest request,
CreateTCPServerSocketCallback callback) override;
void CreateTCPConnectedSocket(
const base::Optional<net::IPEndPoint>& local_addr,
const net::AddressList& remote_addr_list,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
mojom::TCPConnectedSocketRequest request,
mojom::TCPConnectedSocketObserverPtr observer,
CreateTCPConnectedSocketCallback callback) override;
void AddHSTSForTesting(const std::string& host, void AddHSTSForTesting(const std::string& host,
base::Time expiry, base::Time expiry,
bool include_subdomains, bool include_subdomains,
...@@ -169,7 +183,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ...@@ -169,7 +183,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
std::unique_ptr<CookieManager> cookie_manager_; std::unique_ptr<CookieManager> cookie_manager_;
std::unique_ptr<UDPSocketFactory> udp_socket_factory_; SocketFactory socket_factory_;
std::vector<std::unique_ptr<HttpCacheDataRemover>> http_cache_data_removers_; std::vector<std::unique_ptr<HttpCacheDataRemover>> http_cache_data_removers_;
......
...@@ -70,6 +70,7 @@ mojom("mojom") { ...@@ -70,6 +70,7 @@ mojom("mojom") {
"proxy_config_with_annotation.mojom", "proxy_config_with_annotation.mojom",
"request_context_frame_type.mojom", "request_context_frame_type.mojom",
"restricted_cookie_manager.mojom", "restricted_cookie_manager.mojom",
"tcp_socket.mojom",
"url_loader.mojom", "url_loader.mojom",
"url_loader_factory.mojom", "url_loader_factory.mojom",
] ]
......
...@@ -6,12 +6,15 @@ module network.mojom; ...@@ -6,12 +6,15 @@ module network.mojom;
import "mojo/common/file_path.mojom"; import "mojo/common/file_path.mojom";
import "mojo/common/time.mojom"; import "mojo/common/time.mojom";
import "net/interfaces/address_list.mojom";
import "net/interfaces/ip_endpoint.mojom"; import "net/interfaces/ip_endpoint.mojom";
import "services/network/public/mojom/cookie_manager.mojom"; import "services/network/public/mojom/cookie_manager.mojom";
import "services/network/public/mojom/mutable_network_traffic_annotation_tag.mojom";
import "services/network/public/mojom/network_change_manager.mojom"; import "services/network/public/mojom/network_change_manager.mojom";
import "services/network/public/mojom/proxy_config.mojom"; import "services/network/public/mojom/proxy_config.mojom";
import "services/network/public/mojom/proxy_config_with_annotation.mojom"; import "services/network/public/mojom/proxy_config_with_annotation.mojom";
import "services/network/public/mojom/restricted_cookie_manager.mojom"; import "services/network/public/mojom/restricted_cookie_manager.mojom";
import "services/network/public/mojom/tcp_socket.mojom";
import "services/network/public/mojom/udp_socket.mojom"; import "services/network/public/mojom/udp_socket.mojom";
import "services/network/public/mojom/url_loader.mojom"; import "services/network/public/mojom/url_loader.mojom";
import "services/network/public/mojom/url_loader_factory.mojom"; import "services/network/public/mojom/url_loader_factory.mojom";
...@@ -187,8 +190,46 @@ interface NetworkContext { ...@@ -187,8 +190,46 @@ interface NetworkContext {
// is not interested in incoming data. // is not interested in incoming data.
// Any sockets that are created but are yet to be destroyed will be destroyed // Any sockets that are created but are yet to be destroyed will be destroyed
// when NetworkContext goes away. // when NetworkContext goes away.
CreateUDPSocket(network.mojom.UDPSocket& request, CreateUDPSocket(UDPSocket& request, UDPSocketReceiver? receiver);
network.mojom.UDPSocketReceiver? receiver);
// Creates a TCP server socket that listens on |local_addr|. The socket
// created can only be used for the purpose specified in |traffic_annotation|,
// and cannot be re-used for other purposes. Caller must specify an address
// family in |local_addr| to be either IPv4 or IPv6. If port in |local_addr|
// is 0, the OS will pick an available port. If address bytes are 0, the OS
// will pick a local address of the specified address family. |backlog| will
// be passed to the OS to set the size of accept queue.
// On success, the resulting local address will be written to |local_addr_out|
// and |result| is net::OK. On failure, |result| is a network error code.
//
// Any sockets that are created but are yet to be destroyed will be destroyed
// when NetworkContext goes away.
CreateTCPServerSocket(net.interfaces.IPEndPoint local_addr,
uint32 backlog,
MutableNetworkTrafficAnnotationTag traffic_annotation,
TCPServerSocket& socket)
=> (int32 result, net.interfaces.IPEndPoint? local_addr_out);
// Creates a TCP socket connected to |remote_addr|. |observer| will be used
// to listen for any network connection error on the newly established
// connection. The socket created can only be used for the purpose specified
// in |traffic_annotation|, and cannot be re-used for other purposes.
// |local_addr| should be set to null unless the caller wants to bind the
// socket to a specific address and port. On success, |result| is net::OK.
// Caller is to use |send_stream| to send data and |receive_stream| to receive
// data over the connection. On failure, |result| is a network error code.
//
// Any sockets that are created but are yet to be destroyed will be destroyed
// when NetworkContext goes away.
CreateTCPConnectedSocket(
net.interfaces.IPEndPoint? local_addr,
net.interfaces.AddressList remote_addr_list,
MutableNetworkTrafficAnnotationTag traffic_annotation,
TCPConnectedSocket& socket,
TCPConnectedSocketObserver observer)
=> (int32 result,
handle<data_pipe_consumer>? receive_stream,
handle<data_pipe_producer>? send_stream);
[Sync] [Sync]
// Adds explicitly-specified data as if it was processed from an // Adds explicitly-specified data as if it was processed from an
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module network.mojom;
import "net/interfaces/ip_endpoint.mojom";
// Represents a connected TCP socket. Writes and Reads are through the data
// pipes supplied upon construction. Consumer should use
// TCPConnectedSocketObserver interface to get notified about any error occurred
// during reading or writing to data pipes. Consumer can close the socket by
// destroying the interface pointer.
interface TCPConnectedSocket {
// Gets the local address of this connected socket. On success, |net_error| is
// net::OK and |local_addr| contains the local address of the socket. On
// failure, |local_addr| is null and |net_error| is a net error code.
GetLocalAddress() => (int32 net_error, net.interfaces.IPEndPoint? local_addr);
};
// Interface to listen for network connection error on a TCPConnectedSocket.
// Because data pipe doesn't surface any network connection error, if a network
// error happens during a read or a write, consumer can find out about it by
// implementing this interface.
interface TCPConnectedSocketObserver {
// Called when an error occurs during reading from the network. The producer
// side of |receive_stream| will be closed.
OnReadError(int32 net_error);
// Called when an error occurs during sending to the network. The consumer
// side of |send_stream| will be closed.
OnWriteError(int32 net_error);
};
// Represents a TCP server socket that has been successfully bound to a local
// address. Caller can close the socket by destroying the interface pointer.
interface TCPServerSocket {
// Waits for an incoming connection request. On success, returns net::OK,
// |remote_addr| represents the peer address, |connected_socket| is the new
// connection established. Caller uses |send_stream| to send data and
// |receive_stream| for receiving data over the new connection. On failure,
// |net_error| is a net error code and other fields are null.
// Up to |backlog| Accept()s can be pending at a time. |backlog| is a
// number that is specified when requesting TCPServerSocket. If more than
// |backlog| number of Accept()s are outstanding,
// net::ERR_INSUFFICIENT_RESOUCES will be returned.
Accept(TCPConnectedSocketObserver observer)
=> (int32 net_error,
net.interfaces.IPEndPoint? remote_addr,
TCPConnectedSocket? connected_socket,
handle<data_pipe_consumer>? send_stream,
handle<data_pipe_producer>? receive_stream);
};
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/socket_factory.h"
#include <utility>
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_errors.h"
#include "net/log/net_log.h"
#include "services/network/tcp_connected_socket.h"
#include "services/network/udp_socket.h"
namespace network {
SocketFactory::SocketFactory(net::NetLog* net_log) : net_log_(net_log) {}
SocketFactory::~SocketFactory() {}
void SocketFactory::CreateUDPSocket(mojom::UDPSocketRequest request,
mojom::UDPSocketReceiverPtr receiver) {
udp_socket_bindings_.AddBinding(
std::make_unique<UDPSocket>(std::move(receiver), net_log_),
std::move(request));
}
void SocketFactory::CreateTCPServerSocket(
const net::IPEndPoint& local_addr,
int backlog,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
mojom::TCPServerSocketRequest request,
mojom::NetworkContext::CreateTCPServerSocketCallback callback) {
auto socket =
std::make_unique<TCPServerSocket>(this, net_log_, traffic_annotation);
net::IPEndPoint local_addr_out;
int result = socket->Listen(local_addr, backlog, &local_addr_out);
if (result != net::OK) {
std::move(callback).Run(result, base::nullopt);
return;
}
tcp_server_socket_bindings_.AddBinding(std::move(socket), std::move(request));
std::move(callback).Run(result, local_addr_out);
}
void SocketFactory::CreateTCPConnectedSocket(
const base::Optional<net::IPEndPoint>& local_addr,
const net::AddressList& remote_addr_list,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
mojom::TCPConnectedSocketRequest request,
mojom::TCPConnectedSocketObserverPtr observer,
mojom::NetworkContext::CreateTCPConnectedSocketCallback callback) {
auto socket = std::make_unique<TCPConnectedSocket>(
std::move(observer), net_log_, traffic_annotation);
TCPConnectedSocket* socket_raw = socket.get();
tcp_connected_socket_bindings_.AddBinding(std::move(socket),
std::move(request));
socket_raw->Connect(local_addr, remote_addr_list, std::move(callback));
}
void SocketFactory::OnAccept(std::unique_ptr<TCPConnectedSocket> socket,
mojom::TCPConnectedSocketRequest request) {
tcp_connected_socket_bindings_.AddBinding(std::move(socket),
std::move(request));
}
} // namespace network
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_NETWORK_SOCKET_FACTORY_H_
#define SERVICES_NETWORK_SOCKET_FACTORY_H_
#include <memory>
#include <vector>
#include "base/component_export.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/strong_binding_set.h"
#include "net/socket/tcp_socket.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/tcp_socket.mojom.h"
#include "services/network/public/mojom/udp_socket.mojom.h"
#include "services/network/tcp_server_socket.h"
namespace net {
class NetLog;
} // namespace net
namespace network {
class UDPSocket;
class TCPConnectedSocket;
// Helper class that handles UDPSocketRequest. It takes care of destroying the
// UDPSocket implementation instances when mojo pipes are broken.
class COMPONENT_EXPORT(NETWORK_SERVICE) SocketFactory
: public TCPServerSocket::Delegate {
public:
// Constructs a SocketFactory. If |net_log| is non-null, it is used to
// log NetLog events when logging is enabled. |net_log| used to must outlive
// |this|.
explicit SocketFactory(net::NetLog* net_log);
virtual ~SocketFactory();
void CreateUDPSocket(mojom::UDPSocketRequest request,
mojom::UDPSocketReceiverPtr receiver);
void CreateTCPServerSocket(
const net::IPEndPoint& local_addr,
int backlog,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
mojom::TCPServerSocketRequest request,
mojom::NetworkContext::CreateTCPServerSocketCallback callback);
void CreateTCPConnectedSocket(
const base::Optional<net::IPEndPoint>& local_addr,
const net::AddressList& remote_addr_list,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
mojom::TCPConnectedSocketRequest request,
mojom::TCPConnectedSocketObserverPtr observer,
mojom::NetworkContext::CreateTCPConnectedSocketCallback callback);
private:
// TCPServerSocket::Delegate implementation:
void OnAccept(std::unique_ptr<TCPConnectedSocket> socket,
mojom::TCPConnectedSocketRequest request) override;
void OnConnectCompleted(int result);
net::NetLog* net_log_;
mojo::StrongBindingSet<mojom::UDPSocket> udp_socket_bindings_;
mojo::StrongBindingSet<mojom::TCPServerSocket> tcp_server_socket_bindings_;
mojo::StrongBindingSet<mojom::TCPConnectedSocket>
tcp_connected_socket_bindings_;
DISALLOW_COPY_AND_ASSIGN(SocketFactory);
};
} // namespace network
#endif // SERVICES_NETWORK_SOCKET_FACTORY_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/tcp_connected_socket.h"
#include <utility>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
#include "base/optional.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/log/net_log.h"
namespace network {
TCPConnectedSocket::TCPConnectedSocket(
mojom::TCPConnectedSocketObserverPtr observer,
net::NetLog* net_log,
const net::NetworkTrafficAnnotationTag& traffic_annotation)
: observer_(std::move(observer)),
net_log_(net_log),
readable_handle_watcher_(FROM_HERE,
mojo::SimpleWatcher::ArmingPolicy::MANUAL),
writable_handle_watcher_(FROM_HERE,
mojo::SimpleWatcher::ArmingPolicy::MANUAL),
traffic_annotation_(traffic_annotation) {
// TODO(xunjieli): Consider supporting null |observer_|, if there are
// consumers who do not care about read/write errors.
DCHECK(observer_);
}
TCPConnectedSocket::TCPConnectedSocket(
mojom::TCPConnectedSocketObserverPtr observer,
std::unique_ptr<net::StreamSocket> socket,
mojo::ScopedDataPipeProducerHandle receive_pipe_handle,
mojo::ScopedDataPipeConsumerHandle send_pipe_handle,
const net::NetworkTrafficAnnotationTag& traffic_annotation)
: observer_(std::move(observer)),
net_log_(nullptr),
socket_(std::move(socket)),
send_stream_(std::move(send_pipe_handle)),
readable_handle_watcher_(FROM_HERE,
mojo::SimpleWatcher::ArmingPolicy::MANUAL),
receive_stream_(std::move(receive_pipe_handle)),
writable_handle_watcher_(FROM_HERE,
mojo::SimpleWatcher::ArmingPolicy::MANUAL),
traffic_annotation_(traffic_annotation) {
StartWatching();
}
TCPConnectedSocket::~TCPConnectedSocket() {}
void TCPConnectedSocket::Connect(
const base::Optional<net::IPEndPoint>& local_addr,
const net::AddressList& remote_addr_list,
mojom::NetworkContext::CreateTCPConnectedSocketCallback callback) {
DCHECK(!socket_);
DCHECK(callback);
auto socket = std::make_unique<net::TCPClientSocket>(
remote_addr_list, nullptr /*socket_performance_watcher*/, net_log_,
net::NetLogSource());
connect_callback_ = std::move(callback);
int result = net::OK;
if (local_addr)
result = socket->Bind(local_addr.value());
if (result == net::OK) {
result = socket->Connect(base::BindRepeating(
&TCPConnectedSocket::OnConnectCompleted, base::Unretained(this)));
}
socket_ = std::move(socket);
if (result == net::ERR_IO_PENDING)
return;
OnConnectCompleted(result);
}
void TCPConnectedSocket::GetLocalAddress(GetLocalAddressCallback callback) {
DCHECK(socket_);
net::IPEndPoint local_addr;
int result = socket_->GetLocalAddress(&local_addr);
if (result != net::OK) {
std::move(callback).Run(result, base::nullopt);
return;
}
std::move(callback).Run(result, local_addr);
}
void TCPConnectedSocket::OnConnectCompleted(int result) {
DCHECK(!connect_callback_.is_null());
DCHECK(!receive_stream_.is_valid());
DCHECK(!send_stream_.is_valid());
if (result != net::OK) {
std::move(connect_callback_)
.Run(result, mojo::ScopedDataPipeConsumerHandle(),
mojo::ScopedDataPipeProducerHandle());
return;
}
mojo::DataPipe send_pipe;
mojo::DataPipe receive_pipe;
receive_stream_ = std::move(receive_pipe.producer_handle);
send_stream_ = std::move(send_pipe.consumer_handle);
StartWatching();
std::move(connect_callback_)
.Run(net::OK, std::move(receive_pipe.consumer_handle),
std::move(send_pipe.producer_handle));
}
void TCPConnectedSocket::StartWatching() {
readable_handle_watcher_.Watch(
send_stream_.get(),
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
base::BindRepeating(&TCPConnectedSocket::OnSendStreamReadable,
base::Unretained(this)));
writable_handle_watcher_.Watch(
receive_stream_.get(),
MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
base::BindRepeating(&TCPConnectedSocket::OnReceiveStreamWritable,
base::Unretained(this)));
ReceiveMore();
SendMore();
}
void TCPConnectedSocket::ReceiveMore() {
DCHECK(receive_stream_.is_valid());
DCHECK(!pending_receive_);
uint32_t num_bytes;
MojoResult result = NetToMojoPendingBuffer::BeginWrite(
&receive_stream_, &pending_receive_, &num_bytes);
if (result == MOJO_RESULT_SHOULD_WAIT) {
writable_handle_watcher_.ArmOrNotify();
return;
}
if (result != MOJO_RESULT_OK) {
ShutdownReceive();
return;
}
DCHECK_EQ(MOJO_RESULT_OK, result);
DCHECK(pending_receive_);
scoped_refptr<net::IOBuffer> buf(
new NetToMojoIOBuffer(pending_receive_.get()));
int read_result = socket_->Read(
buf.get(), base::saturated_cast<int>(num_bytes),
base::BindRepeating(&TCPConnectedSocket::OnNetworkReadCompleted,
base::Unretained(this)));
if (read_result == net::ERR_IO_PENDING)
return;
OnNetworkReadCompleted(read_result);
}
void TCPConnectedSocket::OnReceiveStreamWritable(MojoResult result) {
if (result != MOJO_RESULT_OK) {
ShutdownReceive();
return;
}
ReceiveMore();
}
void TCPConnectedSocket::OnNetworkReadCompleted(int bytes_read) {
DCHECK(pending_receive_);
if (bytes_read < 0)
observer_->OnReadError(bytes_read);
if (bytes_read <= 0) {
ShutdownReceive();
return;
}
if (bytes_read > 0) {
receive_stream_ = pending_receive_->Complete(bytes_read);
pending_receive_ = nullptr;
ReceiveMore();
}
}
void TCPConnectedSocket::ShutdownReceive() {
writable_handle_watcher_.Cancel();
pending_receive_ = nullptr;
receive_stream_.reset();
}
void TCPConnectedSocket::SendMore() {
DCHECK(send_stream_.is_valid());
DCHECK(!pending_send_);
uint32_t num_bytes = 0;
MojoResult result = MojoToNetPendingBuffer::BeginRead(
&send_stream_, &pending_send_, &num_bytes);
if (result == MOJO_RESULT_SHOULD_WAIT) {
readable_handle_watcher_.ArmOrNotify();
return;
}
if (result != MOJO_RESULT_OK) {
ShutdownSend();
return;
}
DCHECK_EQ(MOJO_RESULT_OK, result);
DCHECK(pending_send_);
scoped_refptr<net::IOBuffer> buf(
new net::WrappedIOBuffer(pending_send_->buffer()));
int write_result = socket_->Write(
buf.get(), static_cast<int>(num_bytes),
base::BindRepeating(&TCPConnectedSocket::OnNetworkWriteCompleted,
base::Unretained(this)),
traffic_annotation_);
if (write_result == net::ERR_IO_PENDING)
return;
OnNetworkWriteCompleted(write_result);
}
void TCPConnectedSocket::OnSendStreamReadable(MojoResult result) {
if (result != MOJO_RESULT_OK) {
ShutdownSend();
return;
}
SendMore();
}
void TCPConnectedSocket::OnNetworkWriteCompleted(int bytes_written) {
DCHECK(pending_send_);
if (bytes_written < 0)
observer_->OnWriteError(bytes_written);
if (bytes_written <= 0) {
ShutdownSend();
return;
}
if (bytes_written > 0) {
// Partial write is possible.
pending_send_->CompleteRead(bytes_written);
send_stream_ = pending_send_->ReleaseHandle();
pending_send_ = nullptr;
SendMore();
}
}
void TCPConnectedSocket::ShutdownSend() {
readable_handle_watcher_.Cancel();
pending_send_ = nullptr;
send_stream_.reset();
}
} // namespace network
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_NETWORK_TCP_CONNECTED_SOCKET_H_
#define SERVICES_NETWORK_TCP_CONNECTED_SOCKET_H_
#include <memory>
#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/address_family.h"
#include "net/base/completion_callback.h"
#include "net/base/ip_endpoint.h"
#include "net/interfaces/address_family.mojom.h"
#include "net/interfaces/ip_endpoint.mojom.h"
#include "net/socket/tcp_client_socket.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/net_adapters.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/tcp_socket.mojom.h"
namespace net {
class NetLog;
class StreamSocket;
} // namespace net
namespace network {
class COMPONENT_EXPORT(NETWORK_SERVICE) TCPConnectedSocket
: public mojom::TCPConnectedSocket {
public:
TCPConnectedSocket(
mojom::TCPConnectedSocketObserverPtr observer,
net::NetLog* net_log,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
TCPConnectedSocket(
mojom::TCPConnectedSocketObserverPtr observer,
std::unique_ptr<net::StreamSocket> socket,
mojo::ScopedDataPipeProducerHandle receive_pipe_handle,
mojo::ScopedDataPipeConsumerHandle send_pipe_handle,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
~TCPConnectedSocket() override;
void Connect(
const base::Optional<net::IPEndPoint>& local_addr,
const net::AddressList& remote_addr_list,
mojom::NetworkContext::CreateTCPConnectedSocketCallback callback);
// mojom::TCPConnectedSocket implementation.
void GetLocalAddress(GetLocalAddressCallback callback) override;
private:
// Invoked when net::TCPClientSocket::Connect() completes.
void OnConnectCompleted(int net_result);
// Helper to start watching |send_stream_| and |receive_stream_|.
void StartWatching();
// "Receiving" in this context means reading from |socket_| and writing to
// the Mojo |receive_stream_|.
void ReceiveMore();
void OnReceiveStreamWritable(MojoResult result);
void OnNetworkReadCompleted(int result);
void ShutdownReceive();
// "Writing" is reading from the Mojo |send_stream_| and writing to the
// |socket_|.
void SendMore();
void OnSendStreamReadable(MojoResult result);
void OnNetworkWriteCompleted(int result);
void ShutdownSend();
mojom::TCPConnectedSocketObserverPtr observer_;
net::NetLog* net_log_;
std::unique_ptr<net::StreamSocket> socket_;
mojom::NetworkContext::CreateTCPConnectedSocketCallback connect_callback_;
// The *stream handles will be null while there is an in-progress transation
// between net and mojo. During this time, the handle will be owned by the
// *PendingBuffer.
// For reading from the Mojo pipe and writing to the network.
mojo::ScopedDataPipeConsumerHandle send_stream_;
scoped_refptr<MojoToNetPendingBuffer> pending_send_;
mojo::SimpleWatcher readable_handle_watcher_;
// For reading from the network and writing to Mojo pipe.
mojo::ScopedDataPipeProducerHandle receive_stream_;
scoped_refptr<NetToMojoPendingBuffer> pending_receive_;
mojo::SimpleWatcher writable_handle_watcher_;
net::NetworkTrafficAnnotationTag traffic_annotation_;
DISALLOW_COPY_AND_ASSIGN(TCPConnectedSocket);
};
} // namespace network
#endif // SERVICES_NETWORK_TCP_CONNECTED_SOCKET_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/tcp_server_socket.h"
#include <utility>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
#include "base/optional.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/log/net_log.h"
#include "net/socket/tcp_server_socket.h"
#include "services/network/tcp_connected_socket.h"
namespace network {
TCPServerSocket::TCPServerSocket(
Delegate* delegate,
net::NetLog* net_log,
const net::NetworkTrafficAnnotationTag& traffic_annotation)
: delegate_(delegate),
socket_(
std::make_unique<net::TCPServerSocket>(net_log, net::NetLogSource())),
backlog_(0),
traffic_annotation_(traffic_annotation),
weak_factory_(this) {}
TCPServerSocket::~TCPServerSocket() {}
int TCPServerSocket::Listen(const net::IPEndPoint& local_addr,
int backlog,
net::IPEndPoint* local_addr_out) {
if (backlog == 0) {
// SocketPosix::Listen and TCPSocketWin::Listen DCHECKs on backlog > 0.
return net::ERR_INVALID_ARGUMENT;
}
backlog_ = backlog;
int net_error = socket_->Listen(local_addr, backlog);
if (net_error == net::OK)
socket_->GetLocalAddress(local_addr_out);
return net_error;
}
void TCPServerSocket::Accept(mojom::TCPConnectedSocketObserverPtr observer,
AcceptCallback callback) {
if (pending_accepts_queue_.size() >= static_cast<size_t>(backlog_)) {
std::move(callback).Run(net::ERR_INSUFFICIENT_RESOURCES, base::nullopt,
nullptr, mojo::ScopedDataPipeConsumerHandle(),
mojo::ScopedDataPipeProducerHandle());
return;
}
pending_accepts_queue_.push_back(std::make_unique<PendingAccept>(
std::move(callback), std::move(observer)));
if (pending_accepts_queue_.size() == 1)
ProcessNextAccept();
}
void TCPServerSocket::SetSocketForTest(
std::unique_ptr<net::ServerSocket> socket) {
socket_ = std::move(socket);
}
TCPServerSocket::PendingAccept::PendingAccept(
AcceptCallback callback,
mojom::TCPConnectedSocketObserverPtr observer)
: callback(std::move(callback)), observer(std::move(observer)) {}
TCPServerSocket::PendingAccept::~PendingAccept() {}
void TCPServerSocket::OnAcceptCompleted(int result) {
DCHECK_NE(net::ERR_IO_PENDING, result);
DCHECK(!pending_accepts_queue_.empty());
auto pending_accept = std::move(pending_accepts_queue_.front());
pending_accepts_queue_.erase(pending_accepts_queue_.begin());
net::IPEndPoint peer_addr;
if (result == net::OK) {
DCHECK(accepted_socket_);
result = accepted_socket_->GetPeerAddress(&peer_addr);
}
if (result == net::OK) {
mojo::DataPipe send_pipe;
mojo::DataPipe receive_pipe;
mojom::TCPConnectedSocketPtr socket;
auto connected_socket = std::make_unique<TCPConnectedSocket>(
std::move(pending_accept->observer),
base::WrapUnique(accepted_socket_.release()),
std::move(receive_pipe.producer_handle),
std::move(send_pipe.consumer_handle), traffic_annotation_);
delegate_->OnAccept(std::move(connected_socket),
mojo::MakeRequest(&socket));
std::move(pending_accept->callback)
.Run(result, peer_addr, std::move(socket),
std::move(receive_pipe.consumer_handle),
std::move(send_pipe.producer_handle));
} else {
std::move(pending_accept->callback)
.Run(result, base::nullopt, nullptr,
mojo::ScopedDataPipeConsumerHandle(),
mojo::ScopedDataPipeProducerHandle());
}
ProcessNextAccept();
}
void TCPServerSocket::ProcessNextAccept() {
if (pending_accepts_queue_.empty())
return;
int result =
socket_->Accept(&accepted_socket_,
base::BindRepeating(&TCPServerSocket::OnAcceptCompleted,
base::Unretained(this)));
if (result == net::ERR_IO_PENDING)
return;
OnAcceptCompleted(result);
}
} // namespace network
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_NETWORK_TCP_SERVER_SOCKET_H_
#define SERVICES_NETWORK_TCP_SERVER_SOCKET_H_
#include <memory>
#include <vector>
#include "base/component_export.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/base/ip_endpoint.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/mojom/tcp_socket.mojom.h"
namespace net {
class NetLog;
class ServerSocket;
class StreamSocket;
} // namespace net
namespace network {
class TCPConnectedSocket;
class COMPONENT_EXPORT(NETWORK_SERVICE) TCPServerSocket
: public mojom::TCPServerSocket {
public:
// A delegate interface that is notified when new connections are established.
class Delegate {
public:
Delegate() {}
~Delegate() {}
// Invoked when a new connection is accepted. The delegate should take
// ownership of |socket| and set up binding for |request|.
virtual void OnAccept(std::unique_ptr<TCPConnectedSocket> socket,
mojom::TCPConnectedSocketRequest request) = 0;
};
// Constructs a TCPServerSocket. |delegate| must outlive |this|. When a new
// connection is accepted, |delegate| will be notified to take ownership of
// the connection.
TCPServerSocket(Delegate* delegate,
net::NetLog* net_log,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
~TCPServerSocket() override;
int Listen(const net::IPEndPoint& local_addr,
int backlog,
net::IPEndPoint* local_addr_out);
// TCPServerSocket implementation.
void Accept(mojom::TCPConnectedSocketObserverPtr observer,
AcceptCallback callback) override;
// Replaces the underlying socket implementation with |socket| in tests.
void SetSocketForTest(std::unique_ptr<net::ServerSocket> socket);
private:
struct PendingAccept {
PendingAccept(AcceptCallback callback,
mojom::TCPConnectedSocketObserverPtr observer);
~PendingAccept();
AcceptCallback callback;
mojom::TCPConnectedSocketObserverPtr observer;
};
// Invoked when socket_->Accept() completes.
void OnAcceptCompleted(int result);
// Process the next Accept() from |pending_accepts_queue_|.
void ProcessNextAccept();
Delegate* delegate_;
std::unique_ptr<net::ServerSocket> socket_;
int backlog_;
std::vector<std::unique_ptr<PendingAccept>> pending_accepts_queue_;
std::unique_ptr<net::StreamSocket> accepted_socket_;
net::NetworkTrafficAnnotationTag traffic_annotation_;
base::WeakPtrFactory<TCPServerSocket> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(TCPServerSocket);
};
} // namespace network
#endif // SERVICES_NETWORK_TCP_SERVER_SOCKET_H_
This diff is collapsed.
...@@ -137,22 +137,15 @@ UDPSocket::PendingSendRequest::PendingSendRequest() {} ...@@ -137,22 +137,15 @@ UDPSocket::PendingSendRequest::PendingSendRequest() {}
UDPSocket::PendingSendRequest::~PendingSendRequest() {} UDPSocket::PendingSendRequest::~PendingSendRequest() {}
UDPSocket::UDPSocket(mojom::UDPSocketRequest request, UDPSocket::UDPSocket(mojom::UDPSocketReceiverPtr receiver, net::NetLog* net_log)
mojom::UDPSocketReceiverPtr receiver) : net_log_(net_log),
: is_bound_(false), is_bound_(false),
is_connected_(false), is_connected_(false),
receiver_(std::move(receiver)), receiver_(std::move(receiver)),
remaining_recv_slots_(0), remaining_recv_slots_(0) {}
binding_(this) {
binding_.Bind(std::move(request));
}
UDPSocket::~UDPSocket() {} UDPSocket::~UDPSocket() {}
void UDPSocket::set_connection_error_handler(base::OnceClosure handler) {
binding_.set_connection_error_handler(std::move(handler));
}
void UDPSocket::Connect(const net::IPEndPoint& remote_addr, void UDPSocket::Connect(const net::IPEndPoint& remote_addr,
mojom::UDPSocketOptionsPtr options, mojom::UDPSocketOptionsPtr options,
ConnectCallback callback) { ConnectCallback callback) {
...@@ -295,7 +288,7 @@ std::unique_ptr<UDPSocket::SocketWrapper> UDPSocket::CreateSocketWrapper() ...@@ -295,7 +288,7 @@ std::unique_ptr<UDPSocket::SocketWrapper> UDPSocket::CreateSocketWrapper()
const { const {
return std::make_unique<SocketWrapperImpl>( return std::make_unique<SocketWrapperImpl>(
net::DatagramSocket::RANDOM_BIND, base::BindRepeating(&base::RandInt), net::DatagramSocket::RANDOM_BIND, base::BindRepeating(&base::RandInt),
nullptr, net::NetLogSource()); net_log_, net::NetLogSource());
} }
bool UDPSocket::IsConnectedOrBound() const { bool UDPSocket::IsConnectedOrBound() const {
......
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
#include "base/containers/span.h" #include "base/containers/span.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/base/address_family.h" #include "net/base/address_family.h"
#include "net/base/completion_callback.h" #include "net/base/completion_callback.h"
#include "net/base/ip_endpoint.h" #include "net/base/ip_endpoint.h"
...@@ -26,6 +24,7 @@ ...@@ -26,6 +24,7 @@
namespace net { namespace net {
class IOBuffer; class IOBuffer;
class IOBufferWithSize; class IOBufferWithSize;
class NetLog;
} // namespace net } // namespace net
namespace network { namespace network {
...@@ -70,13 +69,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocket : public mojom::UDPSocket { ...@@ -70,13 +69,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocket : public mojom::UDPSocket {
const net::CompletionCallback& callback) = 0; const net::CompletionCallback& callback) = 0;
}; };
UDPSocket(mojom::UDPSocketRequest request, UDPSocket(mojom::UDPSocketReceiverPtr receiver, net::NetLog* net_log);
mojom::UDPSocketReceiverPtr receiver);
~UDPSocket() override; ~UDPSocket() override;
// Sets connection error handler.
void set_connection_error_handler(base::OnceClosure handler);
// UDPSocket implementation. // UDPSocket implementation.
void Connect(const net::IPEndPoint& remote_addr, void Connect(const net::IPEndPoint& remote_addr,
mojom::UDPSocketOptionsPtr options, mojom::UDPSocketOptionsPtr options,
...@@ -137,6 +132,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocket : public mojom::UDPSocket { ...@@ -137,6 +132,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocket : public mojom::UDPSocket {
void OnRecvFromCompleted(uint32_t buffer_size, int net_result); void OnRecvFromCompleted(uint32_t buffer_size, int net_result);
void OnSendToCompleted(int net_result); void OnSendToCompleted(int net_result);
net::NetLog* net_log_;
// Whether a Bind() has been successfully executed. // Whether a Bind() has been successfully executed.
bool is_bound_; bool is_bound_;
...@@ -166,8 +163,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocket : public mojom::UDPSocket { ...@@ -166,8 +163,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocket : public mojom::UDPSocket {
base::circular_deque<std::unique_ptr<PendingSendRequest>> base::circular_deque<std::unique_ptr<PendingSendRequest>>
pending_send_requests_; pending_send_requests_;
mojo::Binding<mojom::UDPSocket> binding_;
DISALLOW_COPY_AND_ASSIGN(UDPSocket); DISALLOW_COPY_AND_ASSIGN(UDPSocket);
}; };
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/udp_socket_factory.h"
#include <utility>
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "net/base/net_errors.h"
#include "services/network/udp_socket.h"
namespace network {
UDPSocketFactory::UDPSocketFactory() {}
UDPSocketFactory::~UDPSocketFactory() {}
void UDPSocketFactory::CreateUDPSocket(mojom::UDPSocketRequest request,
mojom::UDPSocketReceiverPtr receiver) {
auto socket =
std::make_unique<UDPSocket>(std::move(request), std::move(receiver));
// base::Unretained is safe as the destruction of |this| will also destroy
// |udp_sockets_| which owns this socket.
socket->set_connection_error_handler(
base::BindOnce(&UDPSocketFactory::OnPipeBroken, base::Unretained(this),
base::Unretained(socket.get())));
udp_sockets_.push_back(std::move(socket));
}
void UDPSocketFactory::OnPipeBroken(UDPSocket* socket) {
udp_sockets_.erase(
std::find_if(udp_sockets_.begin(), udp_sockets_.end(),
[socket](const std::unique_ptr<network::UDPSocket>& ptr) {
return ptr.get() == socket;
}));
}
} // namespace network
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_NETWORK_UDP_SOCKET_FACTORY_H_
#define SERVICES_NETWORK_UDP_SOCKET_FACTORY_H_
#include <memory>
#include <vector>
#include "base/component_export.h"
#include "base/macros.h"
#include "services/network/public/mojom/udp_socket.mojom.h"
namespace network {
class UDPSocket;
// Helper class that handles UDPSocketRequest. It takes care of destroying the
// UDPSocket implementation instances when mojo pipes are broken.
class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocketFactory {
public:
UDPSocketFactory();
virtual ~UDPSocketFactory();
void CreateUDPSocket(mojom::UDPSocketRequest request,
mojom::UDPSocketReceiverPtr receiver);
protected:
// Handles connection errors. This is virtual for testing.
virtual void OnPipeBroken(UDPSocket* client);
private:
std::vector<std::unique_ptr<UDPSocket>> udp_sockets_;
DISALLOW_COPY_AND_ASSIGN(UDPSocketFactory);
};
} // namespace network
#endif // SERVICES_NETWORK_UDP_SOCKET_FACTORY_H_
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <utility>
#include "services/network/udp_socket_factory.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "net/base/net_errors.h"
#include "services/network/public/mojom/udp_socket.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
class UDPSocketFactoryTest : public testing::Test {
public:
UDPSocketFactoryTest() {}
~UDPSocketFactoryTest() override {}
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
DISALLOW_COPY_AND_ASSIGN(UDPSocketFactoryTest);
};
class TestUDPSocketFactory : public UDPSocketFactory {
public:
TestUDPSocketFactory() {}
~TestUDPSocketFactory() override {}
void WaitUntilPipeBroken() { run_loop_.Run(); }
private:
// UDPSocketFactory implementation:
void OnPipeBroken(UDPSocket* client) override {
UDPSocketFactory::OnPipeBroken(client);
run_loop_.Quit();
}
base::RunLoop run_loop_;
};
// Tests that when client end of the pipe is closed, the factory implementation
// cleans up the server side of the pipe.
TEST_F(UDPSocketFactoryTest, ConnectionError) {
TestUDPSocketFactory factory;
mojom::UDPSocketReceiverPtr receiver_interface_ptr;
mojom::UDPSocketPtr socket_ptr;
factory.CreateUDPSocket(mojo::MakeRequest(&socket_ptr),
std::move(receiver_interface_ptr));
// Close client side of the pipe.
socket_ptr.reset();
factory.WaitUntilPipeBroken();
}
} // namespace network
This diff is collapsed.
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