Commit 32c4f747 authored by Trent Apted's avatar Trent Apted Committed by Commit Bot

Revert "Add TCP socket API to network service"

This reverts commit f35977d9.

Reason for revert: causes TCPSocketTest.ReadAndWriteMultiple to flake (timeout)

Bug: 821232

Original change's description:
> 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/868711
> Reviewed-by: Helen Li <xunjieli@chromium.org>
> Reviewed-by: Matt Menke <mmenke@chromium.org>
> Reviewed-by: Tom Sepez <tsepez@chromium.org>
> Reviewed-by: Ramin Halavati <rhalavati@chromium.org>
> Commit-Queue: Helen Li <xunjieli@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#542606}

TBR=miu@chromium.org,mmenke@chromium.org,tsepez@chromium.org,xunjieli@chromium.org,rhalavati@chromium.org

Change-Id: Id31caa2f5cc54993735586555e68bd3c345600bb
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 721401
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_mojo
Reviewed-on: https://chromium-review.googlesource.com/958943Reviewed-by: default avatarTrent Apted <tapted@chromium.org>
Commit-Queue: Trent Apted <tapted@chromium.org>
Cr-Commit-Position: refs/heads/master@{#542696}
parent 74662183
...@@ -138,21 +138,8 @@ class MockNetworkContext final : public network::mojom::NetworkContext { ...@@ -138,21 +138,8 @@ class MockNetworkContext final : public network::mojom::NetworkContext {
std::move(receiver)); std::move(receiver));
OnUDPSocketCreated(); OnUDPSocketCreated();
} }
void CreateTCPServerSocket(
const net::IPEndPoint& local_addr, MockUdpSocket* udp_socket() const { return udp_socket_.get(); };
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,12 +52,6 @@ component("network_service") { ...@@ -52,12 +52,6 @@ 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",
...@@ -72,6 +66,8 @@ component("network_service") { ...@@ -72,6 +66,8 @@ 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",
...@@ -143,11 +139,11 @@ source_set("tests") { ...@@ -143,11 +139,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,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#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"
...@@ -50,6 +49,7 @@ ...@@ -50,6 +49,7 @@
#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,8 +92,7 @@ NetworkContext::NetworkContext(NetworkService* network_service, ...@@ -92,8 +92,7 @@ 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;
...@@ -116,8 +115,7 @@ NetworkContext::NetworkContext( ...@@ -116,8 +115,7 @@ 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());
...@@ -138,9 +136,8 @@ NetworkContext::NetworkContext( ...@@ -138,9 +136,8 @@ 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()->cookie_store())), url_request_context_getter_->GetURLRequestContext()
socket_factory_(network_service_ ? network_service_->net_log() ->cookie_store())) {
: 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);
...@@ -225,10 +222,7 @@ void NetworkContext::Cleanup() { ...@@ -225,10 +222,7 @@ void NetworkContext::Cleanup() {
} }
NetworkContext::NetworkContext(mojom::NetworkContextParamsPtr params) NetworkContext::NetworkContext(mojom::NetworkContextParamsPtr params)
: network_service_(nullptr), : network_service_(nullptr), params_(std::move(params)), binding_(this) {
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;
...@@ -492,32 +486,9 @@ void NetworkContext::SetNetworkConditions( ...@@ -492,32 +486,9 @@ void NetworkContext::SetNetworkConditions(
void NetworkContext::CreateUDPSocket(mojom::UDPSocketRequest request, void NetworkContext::CreateUDPSocket(mojom::UDPSocketRequest request,
mojom::UDPSocketReceiverPtr receiver) { mojom::UDPSocketReceiverPtr receiver) {
socket_factory_.CreateUDPSocket(std::move(request), std::move(receiver)); if (!udp_socket_factory_)
} 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,10 +20,8 @@ ...@@ -20,10 +20,8 @@
#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 {
...@@ -35,6 +33,7 @@ namespace network { ...@@ -35,6 +33,7 @@ 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.
...@@ -113,19 +112,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ...@@ -113,19 +112,6 @@ 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,
...@@ -183,7 +169,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ...@@ -183,7 +169,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
std::unique_ptr<CookieManager> cookie_manager_; std::unique_ptr<CookieManager> cookie_manager_;
SocketFactory socket_factory_; std::unique_ptr<UDPSocketFactory> udp_socket_factory_;
std::vector<std::unique_ptr<HttpCacheDataRemover>> http_cache_data_removers_; std::vector<std::unique_ptr<HttpCacheDataRemover>> http_cache_data_removers_;
......
...@@ -70,7 +70,6 @@ mojom("mojom") { ...@@ -70,7 +70,6 @@ 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,15 +6,12 @@ module network.mojom; ...@@ -6,15 +6,12 @@ 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";
...@@ -190,46 +187,8 @@ interface NetworkContext { ...@@ -190,46 +187,8 @@ 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(UDPSocket& request, UDPSocketReceiver? receiver); CreateUDPSocket(network.mojom.UDPSocket& request,
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_
// 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 <stdint.h>
#include <utility>
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread.h"
#include "mojo/common/data_pipe_utils.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/completion_callback.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/socket/server_socket.h"
#include "net/socket/socket_test_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/udp_socket.mojom.h"
#include "services/network/socket_factory.h"
#include "services/network/tcp_connected_socket.h"
#include "services/network/tcp_server_socket.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
namespace {
// A mock ServerSocket that completes Accept() using a specified result.
class MockServerSocket : public net::ServerSocket {
public:
MockServerSocket() {}
~MockServerSocket() override {}
// net::ServerSocket implementation.
int Listen(const net::IPEndPoint& address, int backlog) override {
return net::OK;
}
int GetLocalAddress(net::IPEndPoint* address) const override {
return net::OK;
}
int Accept(std::unique_ptr<net::StreamSocket>* socket,
const net::CompletionCallback& callback) override {
DCHECK(accept_callback_.is_null());
if (accept_result_ == net::OK && mode_ == net::SYNCHRONOUS)
*socket = CreateMockAcceptSocket();
if (mode_ == net::ASYNC || accept_result_ == net::ERR_IO_PENDING) {
accept_socket_ = socket;
accept_callback_ = callback;
}
run_loop_.Quit();
if (mode_ == net::ASYNC) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&MockServerSocket::CompleteAccept,
base::Unretained(this), accept_result_));
return net::ERR_IO_PENDING;
}
return accept_result_;
}
void SetAcceptResult(net::IoMode mode, int result) {
// It doesn't make sense to return net::ERR_IO_PENDING asynchronously.
DCHECK(!(mode == net::ASYNC && result == net::ERR_IO_PENDING));
mode_ = mode;
accept_result_ = result;
}
void WaitForFirstAccept() { run_loop_.Run(); }
void CompleteAccept(int result) {
DCHECK(!accept_callback_.is_null());
DCHECK_NE(net::ERR_IO_PENDING, result);
*accept_socket_ = CreateMockAcceptSocket();
accept_socket_ = nullptr;
base::ResetAndReturn(&accept_callback_).Run(result);
}
private:
// Must live longer than all SocketDataProviders.
const net::MockRead kReads[1] = {
net::MockRead(net::ASYNC, net::ERR_IO_PENDING)};
std::unique_ptr<net::StreamSocket> CreateMockAcceptSocket() {
auto data_provider = std::make_unique<net::StaticSocketDataProvider>(
kReads, arraysize(kReads), nullptr, 0);
data_provider->set_connect_data(
net::MockConnect(net::SYNCHRONOUS, net::OK));
auto mock_socket = std::make_unique<net::MockTCPClientSocket>(
net::AddressList(), nullptr /*netlog*/, data_provider.get());
data_providers_.push_back(std::move(data_provider));
EXPECT_EQ(net::OK, mock_socket->Connect(base::DoNothing()));
return std::move(mock_socket);
}
net::IoMode mode_ = net::SYNCHRONOUS;
int accept_result_ = net::OK;
net::CompletionCallback accept_callback_;
std::unique_ptr<net::StreamSocket>* accept_socket_;
base::RunLoop run_loop_;
std::vector<std::unique_ptr<net::StaticSocketDataProvider>> data_providers_;
};
class TestTCPConnectedSocketObserver
: public mojom::TCPConnectedSocketObserver {
public:
TestTCPConnectedSocketObserver() : binding_(this) {}
~TestTCPConnectedSocketObserver() override {
EXPECT_EQ(net::OK, read_error_);
EXPECT_EQ(net::OK, write_error_);
}
// Returns a mojo pointer. This can only be called once.
mojom::TCPConnectedSocketObserverPtr GetObserverPtr() {
DCHECK(!binding_);
mojom::TCPConnectedSocketObserverPtr ptr;
binding_.Bind(mojo::MakeRequest(&ptr));
return ptr;
}
// Waits for Read and Write error. Returns the error observed.
int WaitForReadError() {
read_loop_.Run();
int error = read_error_;
read_error_ = net::OK;
return error;
}
int WaitForWriteError() {
write_loop_.Run();
int error = write_error_;
write_error_ = net::OK;
return error;
}
private:
// mojom::TCPConnectedSocketObserver implementation.
void OnReadError(int net_error) override {
read_error_ = net_error;
read_loop_.Quit();
}
void OnWriteError(int net_error) override {
write_error_ = net_error;
write_loop_.Quit();
}
int read_error_ = net::OK;
int write_error_ = net::OK;
base::RunLoop read_loop_;
base::RunLoop write_loop_;
mojo::Binding<mojom::TCPConnectedSocketObserver> binding_;
DISALLOW_COPY_AND_ASSIGN(TestTCPConnectedSocketObserver);
};
// A server implemented using mojom::TCPServerSocket. It owns the server socket
// pointer and as well as the latest client connection,
// mojom::TCPConnectedSocket.
class TestServer {
public:
TestServer()
: TestServer(net::IPEndPoint(net::IPAddress::IPv6Localhost(), 0)) {}
explicit TestServer(const net::IPEndPoint& server_addr)
: factory_(nullptr),
readable_handle_watcher_(FROM_HERE,
mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC),
server_addr_(server_addr) {}
~TestServer() {}
void Start(uint32_t backlog) {
int net_error = net::ERR_FAILED;
base::RunLoop run_loop;
factory_.CreateTCPServerSocket(
server_addr_, backlog, TRAFFIC_ANNOTATION_FOR_TESTS,
mojo::MakeRequest(&server_socket_),
base::BindOnce(
[](base::RunLoop* run_loop, int* result_out,
net::IPEndPoint* local_addr_out, int result,
const base::Optional<net::IPEndPoint>& local_addr) {
*result_out = result;
if (local_addr)
*local_addr_out = local_addr.value();
run_loop->Quit();
},
base::Unretained(&run_loop), base::Unretained(&net_error),
base::Unretained(&server_addr_)));
run_loop.Run();
EXPECT_EQ(net::OK, net_error);
}
// Accepts one connection. Upon successful completion, |callback| will be
// invoked.
void AcceptOneConnection(net::CompletionOnceCallback callback) {
observer_ = std::make_unique<TestTCPConnectedSocketObserver>();
server_socket_->Accept(
observer_->GetObserverPtr(),
base::BindOnce(&TestServer::OnAccept, base::Unretained(this),
std::move(callback)));
}
// Sends data over the most recent connection that is established.
void SendData(const std::string& msg) {
EXPECT_TRUE(
mojo::common::BlockingCopyFromString(msg, server_socket_send_handle_));
}
// Starts reading. Can be called multiple times. It cancels any previous
// StartReading(). Once |expected_contents| is read, |callback| will be
// invoked. If an error occurs or the pipe is broken before read can
// complete, |callback| will be run, but ADD_FAILURE() will be called.
void StartReading(const std::string& expected_contents,
base::OnceClosure callback) {
readable_handle_watcher_.Cancel();
received_contents_.clear();
expected_contents_ = expected_contents;
read_callback_ = std::move(callback);
readable_handle_watcher_.Watch(
server_socket_receive_handle_.get(),
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
base::BindRepeating(&TestServer::OnReadable, base::Unretained(this)));
}
void DestroyServerSocket() { server_socket_.reset(); }
const net::IPEndPoint& server_addr() { return server_addr_; }
private:
void OnAccept(net::CompletionOnceCallback callback,
int result,
const base::Optional<net::IPEndPoint>& remote_addr,
mojom::TCPConnectedSocketPtr connected_socket,
mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
connected_socket_ = std::move(connected_socket);
server_socket_receive_handle_ = std::move(receive_pipe_handle);
server_socket_send_handle_ = std::move(send_pipe_handle);
std::move(callback).Run(result);
}
void OnReadable(MojoResult result) {
if (result != MOJO_RESULT_OK) {
ADD_FAILURE() << "Unexpected broken pipe with error: " << result;
EXPECT_EQ(expected_contents_, received_contents_);
std::move(read_callback_).Run();
return;
}
char buffer[16];
uint32_t read_size = sizeof(buffer);
result = server_socket_receive_handle_->ReadData(buffer, &read_size,
MOJO_READ_DATA_FLAG_NONE);
if (result == MOJO_RESULT_SHOULD_WAIT)
return;
if (result != MOJO_RESULT_OK) {
ADD_FAILURE() << "Unexpected read error: " << result;
EXPECT_EQ(expected_contents_, received_contents_);
std::move(read_callback_).Run();
return;
}
received_contents_.append(buffer, read_size);
if (received_contents_.size() == expected_contents_.size()) {
EXPECT_EQ(expected_contents_, received_contents_);
std::move(read_callback_).Run();
}
}
SocketFactory factory_;
mojom::TCPServerSocketPtr server_socket_;
mojom::TCPConnectedSocketPtr connected_socket_;
std::unique_ptr<TestTCPConnectedSocketObserver> observer_;
mojo::ScopedDataPipeConsumerHandle server_socket_receive_handle_;
mojo::ScopedDataPipeProducerHandle server_socket_send_handle_;
mojo::SimpleWatcher readable_handle_watcher_;
net::IPEndPoint server_addr_;
std::string expected_contents_;
base::OnceClosure read_callback_;
std::string received_contents_;
};
} // namespace
class TCPSocketTest : public testing::Test {
public:
TCPSocketTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::IO),
factory_(nullptr /*net_log*/) {}
~TCPSocketTest() override {}
// Reads |num_bytes| from |handle| or reads until an error occurs. Returns the
// bytes read as a string.
std::string Read(mojo::ScopedDataPipeConsumerHandle* handle,
size_t num_bytes) {
std::string received_contents;
while (received_contents.size() < num_bytes) {
base::RunLoop().RunUntilIdle();
std::vector<char> buffer(num_bytes);
uint32_t read_size = static_cast<uint32_t>(num_bytes);
MojoResult result = handle->get().ReadData(buffer.data(), &read_size,
MOJO_READ_DATA_FLAG_NONE);
if (result == MOJO_RESULT_SHOULD_WAIT)
continue;
if (result != MOJO_RESULT_OK)
return received_contents;
received_contents.append(buffer.data(), read_size);
}
return received_contents;
}
// Creates a TCPServerSocket with the mock server socket, |socket|.
void CreateServerSocketWithMockSocket(
uint32_t backlog,
mojom::TCPServerSocketRequest request,
std::unique_ptr<net::ServerSocket> socket) {
auto server_socket_impl = std::make_unique<TCPServerSocket>(
&factory_, nullptr /*netlog*/, TRAFFIC_ANNOTATION_FOR_TESTS);
server_socket_impl->SetSocketForTest(std::move(socket));
net::IPEndPoint local_addr;
EXPECT_EQ(net::OK,
server_socket_impl->Listen(local_addr, backlog, &local_addr));
tcp_server_socket_bindings_.AddBinding(std::move(server_socket_impl),
std::move(request));
}
// Creates a TCPConnectedSocket with a mock client socket, |socket|.
// This can be only called once.
void CreateConnectedSocketWithMockSocket(
mojom::TCPConnectedSocketRequest request,
mojo::ScopedDataPipeProducerHandle receive_pipe_handle,
mojo::ScopedDataPipeConsumerHandle send_pipe_handle,
std::unique_ptr<net::MockTCPClientSocket> socket) {
net::TestCompletionCallback dummy_callback;
EXPECT_EQ(net::OK, socket->Connect(dummy_callback.callback()));
auto socket_impl = std::make_unique<TCPConnectedSocket>(
test_observer_.GetObserverPtr(), std::move(socket),
std::move(receive_pipe_handle), std::move(send_pipe_handle),
TRAFFIC_ANNOTATION_FOR_TESTS);
tcp_connected_socket_bindings_.AddBinding(std::move(socket_impl),
std::move(request));
}
int CreateTCPConnectedSocketSync(
mojom::TCPConnectedSocketRequest request,
mojom::TCPConnectedSocketObserverPtr observer,
const base::Optional<net::IPEndPoint>& local_addr,
const net::IPEndPoint& remote_addr,
mojo::ScopedDataPipeConsumerHandle* receive_pipe_handle_out,
mojo::ScopedDataPipeProducerHandle* send_pipe_handle_out) {
net::AddressList remote_addr_list(remote_addr);
base::RunLoop run_loop;
int net_error = net::ERR_FAILED;
factory_.CreateTCPConnectedSocket(
local_addr, remote_addr_list, TRAFFIC_ANNOTATION_FOR_TESTS,
std::move(request), std::move(observer),
base::BindOnce(
[](base::RunLoop* run_loop, int* result_out,
mojo::ScopedDataPipeConsumerHandle* consumer_handle,
mojo::ScopedDataPipeProducerHandle* producer_handle, int result,
mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
*result_out = result;
*consumer_handle = std::move(receive_pipe_handle);
*producer_handle = std::move(send_pipe_handle);
run_loop->Quit();
},
base::Unretained(&run_loop), base::Unretained(&net_error),
receive_pipe_handle_out, send_pipe_handle_out));
run_loop.Run();
return net_error;
}
TestTCPConnectedSocketObserver* observer() { return &test_observer_; }
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
SocketFactory factory_;
TestTCPConnectedSocketObserver test_observer_;
mojo::StrongBindingSet<mojom::TCPServerSocket> tcp_server_socket_bindings_;
mojo::StrongBindingSet<mojom::TCPConnectedSocket>
tcp_connected_socket_bindings_;
DISALLOW_COPY_AND_ASSIGN(TCPSocketTest);
};
TEST_F(TCPSocketTest, ReadAndWrite) {
const struct TestData {
base::Optional<net::IPEndPoint> client_addr;
net::IPEndPoint server_addr;
} kTestCases[] = {
{base::nullopt, net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0)},
{base::nullopt, net::IPEndPoint(net::IPAddress::IPv6Localhost(), 0)},
{net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0),
net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0)},
{net::IPEndPoint(net::IPAddress::IPv6Localhost(), 0),
net::IPEndPoint(net::IPAddress::IPv6Localhost(), 0)},
};
for (auto test : kTestCases) {
TestServer server(test.server_addr);
server.Start(1 /*backlog*/);
net::TestCompletionCallback accept_callback;
server.AcceptOneConnection(accept_callback.callback());
mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle;
mojo::ScopedDataPipeProducerHandle client_socket_send_handle;
mojom::TCPConnectedSocketPtr client_socket;
TestTCPConnectedSocketObserver observer;
EXPECT_EQ(net::OK,
CreateTCPConnectedSocketSync(
mojo::MakeRequest(&client_socket), observer.GetObserverPtr(),
test.client_addr, server.server_addr(),
&client_socket_receive_handle, &client_socket_send_handle));
ASSERT_EQ(net::OK, accept_callback.WaitForResult());
// Test sending data from server to client.
const char kTestMsg[] = "hello";
server.SendData(kTestMsg);
EXPECT_EQ(kTestMsg,
Read(&client_socket_receive_handle, arraysize(kTestMsg) - 1));
// Test sending data from client to server.
base::RunLoop read_run_loop;
server.StartReading(kTestMsg, read_run_loop.QuitClosure());
EXPECT_TRUE(mojo::common::BlockingCopyFromString(
kTestMsg, client_socket_send_handle));
read_run_loop.Run();
}
}
TEST_F(TCPSocketTest, CannotConnectToWrongInterface) {
const struct TestData {
net::IPEndPoint client_addr;
net::IPEndPoint server_addr;
} kTestCases[] = {
{net::IPEndPoint(net::IPAddress::IPv6Localhost(), 0),
net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0)},
{net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0),
net::IPEndPoint(net::IPAddress::IPv6Localhost(), 0)},
};
for (auto test : kTestCases) {
mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle;
mojo::ScopedDataPipeProducerHandle client_socket_send_handle;
TestTCPConnectedSocketObserver observer;
TestServer server(test.server_addr);
server.Start(1 /*backlog*/);
net::TestCompletionCallback accept_callback;
server.AcceptOneConnection(accept_callback.callback());
mojom::TCPConnectedSocketPtr client_socket;
int result = CreateTCPConnectedSocketSync(
mojo::MakeRequest(&client_socket), observer.GetObserverPtr(),
test.client_addr, server.server_addr(), &client_socket_receive_handle,
&client_socket_send_handle);
// Both net::ERR_INVALID_ARGUMENT and net::ERR_ADDRESS_UNREACHABLE can be
// returned. On Linux, for eample, the former is returned when talking ipv4
// to a ipv6 remote, and the latter is returned when talking ipv6 to a ipv4
// remote. net::ERR_CONNECTION_FAILED is returned on Windows.
EXPECT_TRUE(result == net::ERR_CONNECTION_FAILED ||
result == net::ERR_INVALID_ARGUMENT ||
result == net::ERR_ADDRESS_UNREACHABLE)
<< "actual result: " << result;
}
}
TEST_F(TCPSocketTest, ReadAndWriteMultiple) {
SocketFactory factory(nullptr /*net_log*/);
TestServer server;
server.Start(1 /*backlog*/);
net::TestCompletionCallback accept_callback;
server.AcceptOneConnection(accept_callback.callback());
mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle;
mojo::ScopedDataPipeProducerHandle client_socket_send_handle;
TestTCPConnectedSocketObserver observer;
mojom::TCPConnectedSocketPtr client_socket;
EXPECT_EQ(net::OK,
CreateTCPConnectedSocketSync(
mojo::MakeRequest(&client_socket), observer.GetObserverPtr(),
base::nullopt /*local_addr*/, server.server_addr(),
&client_socket_receive_handle, &client_socket_send_handle));
ASSERT_EQ(net::OK, accept_callback.WaitForResult());
// Test sending data multiple times from the server to client.
const char kTestMsg[] = "01234567890";
// Loop 3 times to test that writes can follow reads, and reads can follow
// writes.
for (int j = 0; j < 3; ++j) {
for (size_t i = 0; i < arraysize(kTestMsg); ++i) {
std::string data(1, kTestMsg[i]);
server.SendData(data);
EXPECT_EQ(data, Read(&client_socket_receive_handle, 1));
}
// Test sending data from client to server.
base::RunLoop read_run_loop;
server.StartReading(kTestMsg, read_run_loop.QuitClosure());
// Test sending data multiple times from the client to server.
for (size_t i = 0; i < arraysize(kTestMsg); ++i) {
mojo::common::BlockingCopyFromString(std::string(1, kTestMsg[i]),
client_socket_send_handle);
// Flush the 1 byte write.
base::RunLoop().RunUntilIdle();
}
read_run_loop.Run();
}
}
TEST_F(TCPSocketTest, ServerReceivesMultipleAccept) {
uint32_t backlog = 10;
TestServer server;
server.Start(backlog);
std::vector<std::unique_ptr<net::TestCompletionCallback>> accept_callbacks;
// Issue |backlog| Accepts(), so the queue is filled up.
for (size_t i = 0; i < backlog; ++i) {
auto callback = std::make_unique<net::TestCompletionCallback>();
server.AcceptOneConnection(callback->callback());
accept_callbacks.push_back(std::move(callback));
}
// Accept() beyond the queue size should fail immediately.
net::TestCompletionCallback callback;
server.AcceptOneConnection(callback.callback());
EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES, callback.WaitForResult());
// After handling incoming connections, all callbacks should now complete.
for (size_t i = 0; i < backlog; ++i) {
TestTCPConnectedSocketObserver observer;
mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle;
mojo::ScopedDataPipeProducerHandle client_socket_send_handle;
mojom::TCPConnectedSocketPtr client_socket;
EXPECT_EQ(net::OK,
CreateTCPConnectedSocketSync(
mojo::MakeRequest(&client_socket), observer.GetObserverPtr(),
base::nullopt /*local_addr*/, server.server_addr(),
&client_socket_receive_handle, &client_socket_send_handle));
}
for (const auto& callback : accept_callbacks) {
EXPECT_EQ(net::OK, callback->WaitForResult());
}
}
// Tests that if a socket is closed, the other side can observe that the pipes
// are broken.
TEST_F(TCPSocketTest, SocketClosed) {
mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle;
mojo::ScopedDataPipeProducerHandle client_socket_send_handle;
mojom::TCPConnectedSocketPtr client_socket;
TestTCPConnectedSocketObserver observer;
const char kTestMsg[] = "hello";
auto server = std::make_unique<TestServer>();
server->Start(1 /*backlog*/);
net::TestCompletionCallback accept_callback;
server->AcceptOneConnection(accept_callback.callback());
EXPECT_EQ(net::OK,
CreateTCPConnectedSocketSync(
mojo::MakeRequest(&client_socket), observer.GetObserverPtr(),
base::nullopt /*local_addr*/, server->server_addr(),
&client_socket_receive_handle, &client_socket_send_handle));
ASSERT_EQ(net::OK, accept_callback.WaitForResult());
// Send some data from server to client.
server->SendData(kTestMsg);
EXPECT_EQ(kTestMsg,
Read(&client_socket_receive_handle, arraysize(kTestMsg) - 1));
// Resetting the |server| destroys the TCPConnectedSocket ptr owned by the
// server.
server = nullptr;
// Read should return EOF.
EXPECT_EQ("", Read(&client_socket_receive_handle, 1));
// Read from |client_socket_receive_handle| again should return that the pipe
// is broken.
char buffer[16];
uint32_t read_size = sizeof(buffer);
MojoResult mojo_result = client_socket_receive_handle->ReadData(
buffer, &read_size, MOJO_READ_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, mojo_result);
EXPECT_TRUE(client_socket_receive_handle->QuerySignalsState().peer_closed());
// Send pipe should be closed.
while (true) {
base::RunLoop().RunUntilIdle();
uint32_t size = arraysize(kTestMsg);
MojoResult r = client_socket_send_handle->WriteData(
kTestMsg, &size, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
if (r == MOJO_RESULT_SHOULD_WAIT)
continue;
if (r == MOJO_RESULT_FAILED_PRECONDITION)
break;
}
EXPECT_TRUE(client_socket_send_handle->QuerySignalsState().peer_closed());
int result = observer.WaitForWriteError();
EXPECT_TRUE(result == net::ERR_CONNECTION_RESET ||
result == net::ERR_CONNECTION_ABORTED)
<< "actual result: " << result;
}
TEST_F(TCPSocketTest, ReadPipeClosed) {
TestTCPConnectedSocketObserver observer;
const char kTestMsg[] = "hello";
TestServer server;
server.Start(1 /*backlog*/);
net::TestCompletionCallback accept_callback;
server.AcceptOneConnection(accept_callback.callback());
mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle;
mojo::ScopedDataPipeProducerHandle client_socket_send_handle;
mojom::TCPConnectedSocketPtr client_socket;
EXPECT_EQ(net::OK,
CreateTCPConnectedSocketSync(
mojo::MakeRequest(&client_socket), observer.GetObserverPtr(),
base::nullopt /*local_addr*/, server.server_addr(),
&client_socket_receive_handle, &client_socket_send_handle));
ASSERT_EQ(net::OK, accept_callback.WaitForResult());
// Close |client_socket_receive_handle|. The socket should remain open.
client_socket_receive_handle.reset();
// Send should proceed as normal.
base::RunLoop read_run_loop;
server.StartReading(kTestMsg, read_run_loop.QuitClosure());
EXPECT_TRUE(mojo::common::BlockingCopyFromString(kTestMsg,
client_socket_send_handle));
read_run_loop.Run();
}
TEST_F(TCPSocketTest, WritePipeClosed) {
TestTCPConnectedSocketObserver observer;
const char kTestMsg[] = "hello";
TestServer server;
server.Start(1 /*backlog*/);
net::TestCompletionCallback accept_callback;
server.AcceptOneConnection(accept_callback.callback());
mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle;
mojo::ScopedDataPipeProducerHandle client_socket_send_handle;
mojom::TCPConnectedSocketPtr client_socket;
EXPECT_EQ(net::OK,
CreateTCPConnectedSocketSync(
mojo::MakeRequest(&client_socket), observer.GetObserverPtr(),
base::nullopt /*local_addr*/, server.server_addr(),
&client_socket_receive_handle, &client_socket_send_handle));
ASSERT_EQ(net::OK, accept_callback.WaitForResult());
// Close |client_socket_send_handle|. The socket should remain open.
client_socket_send_handle.reset();
// Receive should proceed as normal.
server.SendData(kTestMsg);
EXPECT_EQ(kTestMsg,
Read(&client_socket_receive_handle, arraysize(kTestMsg) - 1));
}
// Tests that if the server socket is destroyed, any connected sockets that it
// handed out remain alive.
TEST_F(TCPSocketTest, ServerSocketClosedAcceptedSocketAlive) {
mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle;
mojo::ScopedDataPipeProducerHandle client_socket_send_handle;
TestTCPConnectedSocketObserver observer;
const char kTestMsg[] = "hello";
TestServer server;
server.Start(1 /*backlog*/);
net::TestCompletionCallback accept_callback;
server.AcceptOneConnection(accept_callback.callback());
mojom::TCPConnectedSocketPtr client_socket;
EXPECT_EQ(net::OK,
CreateTCPConnectedSocketSync(
mojo::MakeRequest(&client_socket), observer.GetObserverPtr(),
base::nullopt /*local_addr*/, server.server_addr(),
&client_socket_receive_handle, &client_socket_send_handle));
ASSERT_EQ(net::OK, accept_callback.WaitForResult());
// Now destroys the server socket.
server.DestroyServerSocket();
base::RunLoop().RunUntilIdle();
// Sending and receiving should still work.
server.SendData(kTestMsg);
EXPECT_EQ(kTestMsg,
Read(&client_socket_receive_handle, arraysize(kTestMsg) - 1));
base::RunLoop read_run_loop;
server.StartReading(kTestMsg, read_run_loop.QuitClosure());
EXPECT_TRUE(mojo::common::BlockingCopyFromString(kTestMsg,
client_socket_send_handle));
read_run_loop.Run();
}
// Tests both async and sync cases.
class TCPSocketWithMockSocketTest
: public TCPSocketTest,
public ::testing::WithParamInterface<net::IoMode> {};
INSTANTIATE_TEST_CASE_P(/* no prefix */,
TCPSocketWithMockSocketTest,
testing::Values(net::SYNCHRONOUS, net::ASYNC));
// Tests that a server socket handles Accept() correctly when the underlying
// implementation completes Accept() in sync and async mode.
TEST_P(TCPSocketWithMockSocketTest,
ServerAcceptClientConnectionWithMockSocket) {
net::IoMode mode = GetParam();
auto mock_server_socket = std::make_unique<MockServerSocket>();
MockServerSocket* mock_server_socket_raw = mock_server_socket.get();
mojom::TCPServerSocketPtr server_socket;
uint32_t kBacklog = 10;
// Use a mock socket to control net::ServerSocket::Accept() behavior.
CreateServerSocketWithMockSocket(kBacklog, mojo::MakeRequest(&server_socket),
std::move(mock_server_socket));
// Complete first Accept() using manual completion via CompleteAccept().
mock_server_socket_raw->SetAcceptResult(net::SYNCHRONOUS,
net::ERR_IO_PENDING);
std::vector<std::unique_ptr<net::TestCompletionCallback>> accept_callbacks;
for (size_t i = 0; i < kBacklog; ++i) {
auto callback = std::make_unique<net::TestCompletionCallback>();
TestTCPConnectedSocketObserver observer;
server_socket->Accept(
observer.GetObserverPtr(),
base::BindOnce(
[](net::CompletionOnceCallback callback, int result,
const base::Optional<net::IPEndPoint>& remote_addr,
mojom::TCPConnectedSocketPtr connected_socket,
mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
std::move(callback).Run(result);
},
std::move(callback->callback())));
accept_callbacks.push_back(std::move(callback));
}
mock_server_socket_raw->WaitForFirstAccept();
mock_server_socket_raw->SetAcceptResult(mode, net::OK);
mock_server_socket_raw->CompleteAccept(net::OK);
// First net::ServerSocket::Accept() will complete asynchronously
// internally. Other queued Accept() will complete
// synchronously/asynchronously depending on |mode| internally.
for (const auto& callback : accept_callbacks) {
EXPECT_EQ(net::OK, callback->WaitForResult());
}
// New Accept() should complete synchronously internally. Make sure this is
// okay.
auto callback = std::make_unique<net::TestCompletionCallback>();
TestTCPConnectedSocketObserver observer;
server_socket->Accept(
observer.GetObserverPtr(),
base::BindOnce(
[](net::CompletionOnceCallback callback, int result,
const base::Optional<net::IPEndPoint>& remote_addr,
mojom::TCPConnectedSocketPtr connected_socket,
mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
std::move(callback).Run(result);
},
std::move(callback->callback())));
EXPECT_EQ(net::OK, callback->WaitForResult());
}
TEST_P(TCPSocketWithMockSocketTest, ReadAndWriteMultipleWithMockClientSocket) {
mojo::DataPipe send_pipe;
mojo::DataPipe receive_pipe;
mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle =
std::move(receive_pipe.consumer_handle);
mojo::ScopedDataPipeProducerHandle client_socket_send_handle =
std::move(send_pipe.producer_handle);
mojom::TCPConnectedSocketPtr client_socket;
const char kTestMsg[] = "abcdefghij";
const size_t kMsgSize = arraysize(kTestMsg) - 1;
const int kNumIterations = 3;
std::vector<net::MockRead> reads;
std::vector<net::MockWrite> writes;
int sequence_number = 0;
net::IoMode mode = GetParam();
for (int j = 0; j < kNumIterations; ++j) {
for (size_t i = 0; i < kMsgSize; ++i) {
reads.push_back(net::MockRead(mode, &kTestMsg[i], 1, sequence_number++));
}
if (j == kNumIterations - 1) {
reads.push_back(net::MockRead(mode, net::OK, sequence_number++));
}
for (size_t i = 0; i < kMsgSize; ++i) {
writes.push_back(
net::MockWrite(mode, &kTestMsg[i], 1, sequence_number++));
}
}
net::StaticSocketDataProvider data_provider(reads.data(), reads.size(),
writes.data(), writes.size());
data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK));
auto mock_socket = std::make_unique<net::MockTCPClientSocket>(
net::AddressList(), nullptr /*netlog*/, &data_provider);
CreateConnectedSocketWithMockSocket(mojo::MakeRequest(&client_socket),
std::move(receive_pipe.producer_handle),
std::move(send_pipe.consumer_handle),
std::move(mock_socket));
// Loop kNumIterations times to test that writes can follow reads, and reads
// can follow writes.
for (int j = 0; j < kNumIterations; ++j) {
// Reading kMsgSize should coalesce the 1-byte mock reads.
EXPECT_EQ(kTestMsg, Read(&client_socket_receive_handle, kMsgSize));
// Write multiple times.
for (size_t i = 0; i < kMsgSize; ++i) {
std::string data(1, kTestMsg[i]);
uint32_t num_bytes = 1;
EXPECT_EQ(MOJO_RESULT_OK,
client_socket_send_handle->WriteData(
&kTestMsg[i], &num_bytes, MOJO_WRITE_DATA_FLAG_NONE));
// Flush the 1 byte write.
base::RunLoop().RunUntilIdle();
}
}
EXPECT_TRUE(data_provider.AllReadDataConsumed());
EXPECT_TRUE(data_provider.AllWriteDataConsumed());
}
TEST_P(TCPSocketWithMockSocketTest, PartialStreamSocketWrite) {
mojo::DataPipe send_pipe;
mojo::DataPipe receive_pipe;
mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle =
std::move(receive_pipe.consumer_handle);
mojo::ScopedDataPipeProducerHandle client_socket_send_handle =
std::move(send_pipe.producer_handle);
mojom::TCPConnectedSocketPtr client_socket;
const char kTestMsg[] = "abcdefghij";
const size_t kMsgSize = arraysize(kTestMsg) - 1;
const int kNumIterations = 3;
std::vector<net::MockRead> reads;
std::vector<net::MockWrite> writes;
int sequence_number = 0;
net::IoMode mode = GetParam();
for (int j = 0; j < kNumIterations; ++j) {
for (size_t i = 0; i < kMsgSize; ++i) {
reads.push_back(net::MockRead(mode, &kTestMsg[i], 1, sequence_number++));
}
if (j == kNumIterations - 1) {
reads.push_back(net::MockRead(mode, net::OK, sequence_number++));
}
for (size_t i = 0; i < kMsgSize; ++i) {
writes.push_back(
net::MockWrite(mode, &kTestMsg[i], 1, sequence_number++));
}
}
net::StaticSocketDataProvider data_provider(reads.data(), reads.size(),
writes.data(), writes.size());
data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK));
auto mock_socket = std::make_unique<net::MockTCPClientSocket>(
net::AddressList(), nullptr /*netlog*/, &data_provider);
CreateConnectedSocketWithMockSocket(mojo::MakeRequest(&client_socket),
std::move(receive_pipe.producer_handle),
std::move(send_pipe.consumer_handle),
std::move(mock_socket));
// Loop kNumIterations times to test that writes can follow reads, and reads
// can follow writes.
for (int j = 0; j < kNumIterations; ++j) {
// Reading kMsgSize should coalesce the 1-byte mock reads.
EXPECT_EQ(kTestMsg, Read(&client_socket_receive_handle, kMsgSize));
// Write twice, each with kMsgSize/2 bytes which is bigger than the 1-byte
// MockWrite(). This is to exercise that StreamSocket::Write() can do
// partial write.
uint32_t first_write_size = kMsgSize / 2;
EXPECT_EQ(MOJO_RESULT_OK,
client_socket_send_handle->WriteData(
&kTestMsg[0], &first_write_size, MOJO_WRITE_DATA_FLAG_NONE));
// Flush the kMsgSize/2 byte write.
base::RunLoop().RunUntilIdle();
uint32_t second_write_size = kMsgSize - first_write_size;
EXPECT_EQ(MOJO_RESULT_OK,
client_socket_send_handle->WriteData(&kTestMsg[first_write_size],
&second_write_size,
MOJO_WRITE_DATA_FLAG_NONE));
// Flush the kMsgSize/2 byte write.
base::RunLoop().RunUntilIdle();
}
EXPECT_TRUE(data_provider.AllReadDataConsumed());
EXPECT_TRUE(data_provider.AllWriteDataConsumed());
}
TEST_P(TCPSocketWithMockSocketTest, ReadError) {
mojo::DataPipe send_pipe;
mojo::DataPipe receive_pipe;
mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle =
std::move(receive_pipe.consumer_handle);
mojo::ScopedDataPipeProducerHandle client_socket_send_handle =
std::move(send_pipe.producer_handle);
mojom::TCPConnectedSocketPtr client_socket;
net::IoMode mode = GetParam();
net::MockRead reads[] = {net::MockRead(mode, net::ERR_FAILED)};
const char kTestMsg[] = "hello!";
net::MockWrite writes[] = {
net::MockWrite(mode, kTestMsg, arraysize(kTestMsg) - 1, 0)};
net::StaticSocketDataProvider data_provider(reads, arraysize(reads), writes,
arraysize(writes));
data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK));
auto mock_socket = std::make_unique<net::MockTCPClientSocket>(
net::AddressList(), nullptr /*netlog*/, &data_provider);
CreateConnectedSocketWithMockSocket(mojo::MakeRequest(&client_socket),
std::move(receive_pipe.producer_handle),
std::move(send_pipe.consumer_handle),
std::move(mock_socket));
EXPECT_EQ("", Read(&client_socket_receive_handle, 1));
EXPECT_EQ(net::ERR_FAILED, observer()->WaitForReadError());
// Writes can proceed even though there is a read error.
uint32_t num_bytes = arraysize(kTestMsg) - 1;
EXPECT_EQ(MOJO_RESULT_OK,
client_socket_send_handle->WriteData(&kTestMsg, &num_bytes,
MOJO_WRITE_DATA_FLAG_NONE));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(data_provider.AllReadDataConsumed());
EXPECT_TRUE(data_provider.AllWriteDataConsumed());
}
TEST_P(TCPSocketWithMockSocketTest, WriteError) {
mojo::DataPipe send_pipe;
mojo::DataPipe receive_pipe;
mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle =
std::move(receive_pipe.consumer_handle);
mojo::ScopedDataPipeProducerHandle client_socket_send_handle =
std::move(send_pipe.producer_handle);
mojom::TCPConnectedSocketPtr client_socket;
net::IoMode mode = GetParam();
const char kTestMsg[] = "hello!";
net::MockRead reads[] = {
net::MockRead(mode, kTestMsg, arraysize(kTestMsg) - 1, 0),
net::MockRead(mode, net::OK)};
net::MockWrite writes[] = {net::MockWrite(mode, net::ERR_FAILED)};
net::StaticSocketDataProvider data_provider(reads, arraysize(reads), writes,
arraysize(writes));
data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK));
auto mock_socket = std::make_unique<net::MockTCPClientSocket>(
net::AddressList(), nullptr /*netlog*/, &data_provider);
CreateConnectedSocketWithMockSocket(mojo::MakeRequest(&client_socket),
std::move(receive_pipe.producer_handle),
std::move(send_pipe.consumer_handle),
std::move(mock_socket));
uint32_t num_bytes = arraysize(kTestMsg) - 1;
EXPECT_EQ(MOJO_RESULT_OK,
client_socket_send_handle->WriteData(&kTestMsg, &num_bytes,
MOJO_WRITE_DATA_FLAG_NONE));
EXPECT_EQ(net::ERR_FAILED, observer()->WaitForWriteError());
// Reads can proceed even though there is a read error.
EXPECT_EQ(kTestMsg, Read(&client_socket_receive_handle, arraysize(kTestMsg)));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(data_provider.AllReadDataConsumed());
EXPECT_TRUE(data_provider.AllWriteDataConsumed());
}
} // namespace network
...@@ -137,15 +137,22 @@ UDPSocket::PendingSendRequest::PendingSendRequest() {} ...@@ -137,15 +137,22 @@ UDPSocket::PendingSendRequest::PendingSendRequest() {}
UDPSocket::PendingSendRequest::~PendingSendRequest() {} UDPSocket::PendingSendRequest::~PendingSendRequest() {}
UDPSocket::UDPSocket(mojom::UDPSocketReceiverPtr receiver, net::NetLog* net_log) UDPSocket::UDPSocket(mojom::UDPSocketRequest request,
: net_log_(net_log), mojom::UDPSocketReceiverPtr receiver)
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) {
...@@ -288,7 +295,7 @@ std::unique_ptr<UDPSocket::SocketWrapper> UDPSocket::CreateSocketWrapper() ...@@ -288,7 +295,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),
net_log_, net::NetLogSource()); nullptr, net::NetLogSource());
} }
bool UDPSocket::IsConnectedOrBound() const { bool UDPSocket::IsConnectedOrBound() const {
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#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"
...@@ -24,7 +26,6 @@ ...@@ -24,7 +26,6 @@
namespace net { namespace net {
class IOBuffer; class IOBuffer;
class IOBufferWithSize; class IOBufferWithSize;
class NetLog;
} // namespace net } // namespace net
namespace network { namespace network {
...@@ -69,9 +70,13 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocket : public mojom::UDPSocket { ...@@ -69,9 +70,13 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocket : public mojom::UDPSocket {
const net::CompletionCallback& callback) = 0; const net::CompletionCallback& callback) = 0;
}; };
UDPSocket(mojom::UDPSocketReceiverPtr receiver, net::NetLog* net_log); UDPSocket(mojom::UDPSocketRequest request,
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,
...@@ -132,8 +137,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocket : public mojom::UDPSocket { ...@@ -132,8 +137,6 @@ 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_;
...@@ -163,6 +166,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) UDPSocket : public mojom::UDPSocket { ...@@ -163,6 +166,8 @@ 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
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/mojom/udp_socket.mojom.h" #include "services/network/public/mojom/udp_socket.mojom.h"
#include "services/network/socket_factory.h"
#include "services/network/udp_socket_test_util.h" #include "services/network/udp_socket_test_util.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -200,9 +199,8 @@ class UDPSocketTest : public testing::Test { ...@@ -200,9 +199,8 @@ class UDPSocketTest : public testing::Test {
}; };
TEST_F(UDPSocketTest, Settings) { TEST_F(UDPSocketTest, Settings) {
SocketFactory factory(nullptr /*net_log*/);
mojom::UDPSocketPtr socket_ptr; mojom::UDPSocketPtr socket_ptr;
factory.CreateUDPSocket(mojo::MakeRequest(&socket_ptr), nullptr); UDPSocket impl(mojo::MakeRequest(&socket_ptr), nullptr);
net::IPEndPoint server_addr; net::IPEndPoint server_addr;
net::IPEndPoint any_port(GetLocalHostWithAnyPort()); net::IPEndPoint any_port(GetLocalHostWithAnyPort());
...@@ -219,9 +217,8 @@ TEST_F(UDPSocketTest, Settings) { ...@@ -219,9 +217,8 @@ TEST_F(UDPSocketTest, Settings) {
// Tests that Send() is used after Bind() is not supported. Send() should only // Tests that Send() is used after Bind() is not supported. Send() should only
// be used after Connect(). // be used after Connect().
TEST_F(UDPSocketTest, TestSendWithBind) { TEST_F(UDPSocketTest, TestSendWithBind) {
SocketFactory factory(nullptr /*net_log*/);
mojom::UDPSocketPtr socket_ptr; mojom::UDPSocketPtr socket_ptr;
factory.CreateUDPSocket(mojo::MakeRequest(&socket_ptr), nullptr); UDPSocket impl(mojo::MakeRequest(&socket_ptr), nullptr);
net::IPEndPoint server_addr(GetLocalHostWithAnyPort()); net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
...@@ -238,7 +235,6 @@ TEST_F(UDPSocketTest, TestSendWithBind) { ...@@ -238,7 +235,6 @@ TEST_F(UDPSocketTest, TestSendWithBind) {
// Tests that when SendTo() is used after Connect() is not supported. SendTo() // Tests that when SendTo() is used after Connect() is not supported. SendTo()
// should only be used after Bind(). // should only be used after Bind().
TEST_F(UDPSocketTest, TestSendToWithConnect) { TEST_F(UDPSocketTest, TestSendToWithConnect) {
SocketFactory factory(nullptr /*net_log*/);
// Create a server socket to listen for incoming datagrams. // Create a server socket to listen for incoming datagrams.
test::UDPSocketReceiverImpl receiver; test::UDPSocketReceiverImpl receiver;
mojo::Binding<mojom::UDPSocketReceiver> receiver_binding(&receiver); mojo::Binding<mojom::UDPSocketReceiver> receiver_binding(&receiver);
...@@ -246,8 +242,8 @@ TEST_F(UDPSocketTest, TestSendToWithConnect) { ...@@ -246,8 +242,8 @@ TEST_F(UDPSocketTest, TestSendToWithConnect) {
receiver_binding.Bind(mojo::MakeRequest(&receiver_interface_ptr)); receiver_binding.Bind(mojo::MakeRequest(&receiver_interface_ptr));
mojom::UDPSocketPtr server_socket; mojom::UDPSocketPtr server_socket;
factory.CreateUDPSocket(mojo::MakeRequest(&server_socket), UDPSocket impl(mojo::MakeRequest(&server_socket),
std::move(receiver_interface_ptr)); std::move(receiver_interface_ptr));
net::IPEndPoint server_addr(GetLocalHostWithAnyPort()); net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
test::UDPSocketTestHelper helper(&server_socket); test::UDPSocketTestHelper helper(&server_socket);
...@@ -255,7 +251,7 @@ TEST_F(UDPSocketTest, TestSendToWithConnect) { ...@@ -255,7 +251,7 @@ TEST_F(UDPSocketTest, TestSendToWithConnect) {
// Create a client socket to send datagrams. // Create a client socket to send datagrams.
mojom::UDPSocketPtr client_socket; mojom::UDPSocketPtr client_socket;
factory.CreateUDPSocket(mojo::MakeRequest(&client_socket), nullptr); UDPSocket client_impl(mojo::MakeRequest(&client_socket), nullptr);
net::IPEndPoint client_addr(GetLocalHostWithAnyPort()); net::IPEndPoint client_addr(GetLocalHostWithAnyPort());
test::UDPSocketTestHelper client_helper(&client_socket); test::UDPSocketTestHelper client_helper(&client_socket);
ASSERT_EQ(net::OK, ASSERT_EQ(net::OK,
...@@ -269,9 +265,8 @@ TEST_F(UDPSocketTest, TestSendToWithConnect) { ...@@ -269,9 +265,8 @@ TEST_F(UDPSocketTest, TestSendToWithConnect) {
// Tests that the sequence of calling Bind()/Connect() and setters is // Tests that the sequence of calling Bind()/Connect() and setters is
// important. // important.
TEST_F(UDPSocketTest, TestUnexpectedSequences) { TEST_F(UDPSocketTest, TestUnexpectedSequences) {
SocketFactory factory(nullptr /*net_log*/);
mojom::UDPSocketPtr socket_ptr; mojom::UDPSocketPtr socket_ptr;
factory.CreateUDPSocket(mojo::MakeRequest(&socket_ptr), nullptr); UDPSocket impl(mojo::MakeRequest(&socket_ptr), nullptr);
test::UDPSocketTestHelper helper(&socket_ptr); test::UDPSocketTestHelper helper(&socket_ptr);
net::IPEndPoint local_addr(GetLocalHostWithAnyPort()); net::IPEndPoint local_addr(GetLocalHostWithAnyPort());
...@@ -296,9 +291,7 @@ TEST_F(UDPSocketTest, TestUnexpectedSequences) { ...@@ -296,9 +291,7 @@ TEST_F(UDPSocketTest, TestUnexpectedSequences) {
// ERR_IO_PENDING, udp_socket.cc doesn't free the send buffer. // ERR_IO_PENDING, udp_socket.cc doesn't free the send buffer.
TEST_F(UDPSocketTest, TestBufferValid) { TEST_F(UDPSocketTest, TestBufferValid) {
mojom::UDPSocketPtr socket_ptr; mojom::UDPSocketPtr socket_ptr;
UDPSocket impl(nullptr /*receiver*/, nullptr /*net_log*/); UDPSocket impl(mojo::MakeRequest(&socket_ptr), nullptr);
mojo::Binding<mojom::UDPSocket> binding(&impl);
binding.Bind(mojo::MakeRequest(&socket_ptr));
net::IPEndPoint server_addr(GetLocalHostWithAnyPort()); net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
test::UDPSocketTestHelper helper(&socket_ptr); test::UDPSocketTestHelper helper(&socket_ptr);
...@@ -336,9 +329,7 @@ TEST_F(UDPSocketTest, TestBufferValid) { ...@@ -336,9 +329,7 @@ TEST_F(UDPSocketTest, TestBufferValid) {
// ERR_INSUFFICIENT_RESOURCES is returned appropriately. // ERR_INSUFFICIENT_RESOURCES is returned appropriately.
TEST_F(UDPSocketTest, TestInsufficientResources) { TEST_F(UDPSocketTest, TestInsufficientResources) {
mojom::UDPSocketPtr socket_ptr; mojom::UDPSocketPtr socket_ptr;
UDPSocket impl(nullptr /*receiver*/, nullptr /*net_log*/); UDPSocket impl(mojo::MakeRequest(&socket_ptr), nullptr);
mojo::Binding<mojom::UDPSocket> binding(&impl);
binding.Bind(mojo::MakeRequest(&socket_ptr));
const size_t kQueueSize = UDPSocket::kMaxPendingSendRequests; const size_t kQueueSize = UDPSocket::kMaxPendingSendRequests;
...@@ -385,9 +376,8 @@ TEST_F(UDPSocketTest, TestReceiveMoreOverflow) { ...@@ -385,9 +376,8 @@ TEST_F(UDPSocketTest, TestReceiveMoreOverflow) {
receiver_binding.Bind(mojo::MakeRequest(&receiver_interface_ptr)); receiver_binding.Bind(mojo::MakeRequest(&receiver_interface_ptr));
mojom::UDPSocketPtr server_socket; mojom::UDPSocketPtr server_socket;
UDPSocket impl(std::move(receiver_interface_ptr), nullptr /*net_log*/); UDPSocket impl(mojo::MakeRequest(&server_socket),
mojo::Binding<mojom::UDPSocket> binding(&impl); std::move(receiver_interface_ptr));
binding.Bind(mojo::MakeRequest(&server_socket));
net::IPEndPoint server_addr(GetLocalHostWithAnyPort()); net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
test::UDPSocketTestHelper helper(&server_socket); test::UDPSocketTestHelper helper(&server_socket);
...@@ -402,7 +392,6 @@ TEST_F(UDPSocketTest, TestReceiveMoreOverflow) { ...@@ -402,7 +392,6 @@ TEST_F(UDPSocketTest, TestReceiveMoreOverflow) {
} }
TEST_F(UDPSocketTest, TestReadSend) { TEST_F(UDPSocketTest, TestReadSend) {
SocketFactory factory(nullptr /*net_log*/);
// Create a server socket to listen for incoming datagrams. // Create a server socket to listen for incoming datagrams.
test::UDPSocketReceiverImpl receiver; test::UDPSocketReceiverImpl receiver;
mojo::Binding<mojom::UDPSocketReceiver> receiver_binding(&receiver); mojo::Binding<mojom::UDPSocketReceiver> receiver_binding(&receiver);
...@@ -410,8 +399,8 @@ TEST_F(UDPSocketTest, TestReadSend) { ...@@ -410,8 +399,8 @@ TEST_F(UDPSocketTest, TestReadSend) {
receiver_binding.Bind(mojo::MakeRequest(&receiver_interface_ptr)); receiver_binding.Bind(mojo::MakeRequest(&receiver_interface_ptr));
mojom::UDPSocketPtr server_socket; mojom::UDPSocketPtr server_socket;
factory.CreateUDPSocket(mojo::MakeRequest(&server_socket), UDPSocket impl(mojo::MakeRequest(&server_socket),
std::move(receiver_interface_ptr)); std::move(receiver_interface_ptr));
net::IPEndPoint server_addr(GetLocalHostWithAnyPort()); net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
test::UDPSocketTestHelper helper(&server_socket); test::UDPSocketTestHelper helper(&server_socket);
...@@ -419,7 +408,7 @@ TEST_F(UDPSocketTest, TestReadSend) { ...@@ -419,7 +408,7 @@ TEST_F(UDPSocketTest, TestReadSend) {
// Create a client socket to send datagrams. // Create a client socket to send datagrams.
mojom::UDPSocketPtr client_socket; mojom::UDPSocketPtr client_socket;
factory.CreateUDPSocket(mojo::MakeRequest(&client_socket), nullptr); UDPSocket client_impl(mojo::MakeRequest(&client_socket), nullptr);
net::IPEndPoint client_addr(GetLocalHostWithAnyPort()); net::IPEndPoint client_addr(GetLocalHostWithAnyPort());
test::UDPSocketTestHelper client_helper(&client_socket); test::UDPSocketTestHelper client_helper(&client_socket);
ASSERT_EQ(net::OK, ASSERT_EQ(net::OK,
...@@ -472,10 +461,9 @@ TEST_F(UDPSocketTest, TestReadSend) { ...@@ -472,10 +461,9 @@ TEST_F(UDPSocketTest, TestReadSend) {
} }
TEST_F(UDPSocketTest, TestReadSendTo) { TEST_F(UDPSocketTest, TestReadSendTo) {
SocketFactory factory(nullptr /*net_log*/);
// Create a server socket to send data. // Create a server socket to send data.
mojom::UDPSocketPtr server_socket; mojom::UDPSocketPtr server_socket;
factory.CreateUDPSocket(mojo::MakeRequest(&server_socket), nullptr); UDPSocket impl(mojo::MakeRequest(&server_socket), nullptr);
net::IPEndPoint server_addr(GetLocalHostWithAnyPort()); net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
test::UDPSocketTestHelper helper(&server_socket); test::UDPSocketTestHelper helper(&server_socket);
...@@ -488,8 +476,8 @@ TEST_F(UDPSocketTest, TestReadSendTo) { ...@@ -488,8 +476,8 @@ TEST_F(UDPSocketTest, TestReadSendTo) {
receiver_binding.Bind(mojo::MakeRequest(&client_receiver_ptr)); receiver_binding.Bind(mojo::MakeRequest(&client_receiver_ptr));
mojom::UDPSocketPtr client_socket; mojom::UDPSocketPtr client_socket;
factory.CreateUDPSocket(mojo::MakeRequest(&client_socket), UDPSocket client_impl(mojo::MakeRequest(&client_socket),
std::move(client_receiver_ptr)); std::move(client_receiver_ptr));
net::IPEndPoint client_addr(GetLocalHostWithAnyPort()); net::IPEndPoint client_addr(GetLocalHostWithAnyPort());
test::UDPSocketTestHelper client_helper(&client_socket); test::UDPSocketTestHelper client_helper(&client_socket);
ASSERT_EQ(net::OK, ASSERT_EQ(net::OK,
...@@ -539,7 +527,6 @@ TEST_F(UDPSocketTest, TestReadSendTo) { ...@@ -539,7 +527,6 @@ TEST_F(UDPSocketTest, TestReadSendTo) {
} }
TEST_F(UDPSocketTest, TestReceiveMoreWithBufferSize) { TEST_F(UDPSocketTest, TestReceiveMoreWithBufferSize) {
SocketFactory factory(nullptr /*net_log*/);
// Create a server socket to listen for incoming datagrams. // Create a server socket to listen for incoming datagrams.
test::UDPSocketReceiverImpl receiver; test::UDPSocketReceiverImpl receiver;
mojo::Binding<mojom::UDPSocketReceiver> receiver_binding(&receiver); mojo::Binding<mojom::UDPSocketReceiver> receiver_binding(&receiver);
...@@ -547,8 +534,8 @@ TEST_F(UDPSocketTest, TestReceiveMoreWithBufferSize) { ...@@ -547,8 +534,8 @@ TEST_F(UDPSocketTest, TestReceiveMoreWithBufferSize) {
receiver_binding.Bind(mojo::MakeRequest(&receiver_interface_ptr)); receiver_binding.Bind(mojo::MakeRequest(&receiver_interface_ptr));
mojom::UDPSocketPtr server_socket; mojom::UDPSocketPtr server_socket;
factory.CreateUDPSocket(mojo::MakeRequest(&server_socket), UDPSocket impl(mojo::MakeRequest(&server_socket),
std::move(receiver_interface_ptr)); std::move(receiver_interface_ptr));
net::IPEndPoint server_addr(GetLocalHostWithAnyPort()); net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
test::UDPSocketTestHelper helper(&server_socket); test::UDPSocketTestHelper helper(&server_socket);
...@@ -556,7 +543,7 @@ TEST_F(UDPSocketTest, TestReceiveMoreWithBufferSize) { ...@@ -556,7 +543,7 @@ TEST_F(UDPSocketTest, TestReceiveMoreWithBufferSize) {
// Create a client socket to send datagrams. // Create a client socket to send datagrams.
mojom::UDPSocketPtr client_socket; mojom::UDPSocketPtr client_socket;
factory.CreateUDPSocket(mojo::MakeRequest(&client_socket), nullptr); UDPSocket client_impl(mojo::MakeRequest(&client_socket), nullptr);
net::IPEndPoint client_addr(GetLocalHostWithAnyPort()); net::IPEndPoint client_addr(GetLocalHostWithAnyPort());
test::UDPSocketTestHelper client_helper(&client_socket); test::UDPSocketTestHelper client_helper(&client_socket);
ASSERT_EQ(net::OK, ASSERT_EQ(net::OK,
...@@ -591,9 +578,8 @@ TEST_F(UDPSocketTest, TestReceiveMoreWithBufferSize) { ...@@ -591,9 +578,8 @@ TEST_F(UDPSocketTest, TestReceiveMoreWithBufferSize) {
// Make sure passing an invalid net::IPEndPoint will be detected by // Make sure passing an invalid net::IPEndPoint will be detected by
// serialization/deserialization in mojo. // serialization/deserialization in mojo.
TEST_F(UDPSocketTest, TestSendToInvalidAddress) { TEST_F(UDPSocketTest, TestSendToInvalidAddress) {
SocketFactory factory(nullptr /*net_log*/);
mojom::UDPSocketPtr server_socket; mojom::UDPSocketPtr server_socket;
factory.CreateUDPSocket(mojo::MakeRequest(&server_socket), nullptr); UDPSocket impl(mojo::MakeRequest(&server_socket), nullptr);
net::IPEndPoint server_addr(GetLocalHostWithAnyPort()); net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
test::UDPSocketTestHelper helper(&server_socket); test::UDPSocketTestHelper helper(&server_socket);
...@@ -625,9 +611,8 @@ TEST_F(UDPSocketTest, TestReadZeroByte) { ...@@ -625,9 +611,8 @@ TEST_F(UDPSocketTest, TestReadZeroByte) {
receiver_binding.Bind(mojo::MakeRequest(&receiver_interface_ptr)); receiver_binding.Bind(mojo::MakeRequest(&receiver_interface_ptr));
mojom::UDPSocketPtr socket_ptr; mojom::UDPSocketPtr socket_ptr;
UDPSocket impl(std::move(receiver_interface_ptr), nullptr /*net_log*/); UDPSocket impl(mojo::MakeRequest(&socket_ptr),
mojo::Binding<mojom::UDPSocket> binding(&impl); std::move(receiver_interface_ptr));
binding.Bind(mojo::MakeRequest(&socket_ptr));
net::IPEndPoint server_addr(GetLocalHostWithAnyPort()); net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
test::UDPSocketTestHelper helper(&socket_ptr); test::UDPSocketTestHelper helper(&socket_ptr);
...@@ -655,7 +640,6 @@ TEST_F(UDPSocketTest, TestReadZeroByte) { ...@@ -655,7 +640,6 @@ TEST_F(UDPSocketTest, TestReadZeroByte) {
#define MAYBE_JoinMulticastGroup JoinMulticastGroup #define MAYBE_JoinMulticastGroup JoinMulticastGroup
#endif // defined(OS_ANDROID) #endif // defined(OS_ANDROID)
TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) { TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) {
SocketFactory factory(nullptr /*net_log*/);
const char kGroup[] = "237.132.100.17"; const char kGroup[] = "237.132.100.17";
net::IPAddress group_ip; net::IPAddress group_ip;
...@@ -665,8 +649,7 @@ TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) { ...@@ -665,8 +649,7 @@ TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) {
test::UDPSocketReceiverImpl receiver; test::UDPSocketReceiverImpl receiver;
mojo::Binding<mojom::UDPSocketReceiver> receiver_binding(&receiver); mojo::Binding<mojom::UDPSocketReceiver> receiver_binding(&receiver);
receiver_binding.Bind(mojo::MakeRequest(&receiver_ptr)); receiver_binding.Bind(mojo::MakeRequest(&receiver_ptr));
factory.CreateUDPSocket(mojo::MakeRequest(&socket_ptr), UDPSocket impl(mojo::MakeRequest(&socket_ptr), std::move(receiver_ptr));
std::move(receiver_ptr));
test::UDPSocketTestHelper helper(&socket_ptr); test::UDPSocketTestHelper helper(&socket_ptr);
...@@ -702,7 +685,7 @@ TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) { ...@@ -702,7 +685,7 @@ TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) {
// Create a second socket to send a packet to multicast group. // Create a second socket to send a packet to multicast group.
mojom::UDPSocketPtr second_socket_ptr; mojom::UDPSocketPtr second_socket_ptr;
factory.CreateUDPSocket(mojo::MakeRequest(&second_socket_ptr), nullptr); UDPSocket second_socket_impl(mojo::MakeRequest(&second_socket_ptr), nullptr);
test::UDPSocketTestHelper second_socket_helper(&second_socket_ptr); test::UDPSocketTestHelper second_socket_helper(&second_socket_ptr);
net::IPEndPoint second_socket_address(bind_ip_address, 0); net::IPEndPoint second_socket_address(bind_ip_address, 0);
ASSERT_EQ(net::OK, ASSERT_EQ(net::OK,
...@@ -733,16 +716,15 @@ TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) { ...@@ -733,16 +716,15 @@ TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) {
} }
TEST_F(UDPSocketTest, ErrorHappensDuringSocketOptionsConfiguration) { TEST_F(UDPSocketTest, ErrorHappensDuringSocketOptionsConfiguration) {
SocketFactory factory(nullptr /*net_log*/);
mojom::UDPSocketPtr server_socket_ptr; mojom::UDPSocketPtr server_socket_ptr;
factory.CreateUDPSocket(mojo::MakeRequest(&server_socket_ptr), nullptr); UDPSocket server_impl(mojo::MakeRequest(&server_socket_ptr), nullptr);
test::UDPSocketTestHelper server_helper(&server_socket_ptr); test::UDPSocketTestHelper server_helper(&server_socket_ptr);
net::IPEndPoint server_addr(GetLocalHostWithAnyPort()); net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
ASSERT_EQ(net::OK, ASSERT_EQ(net::OK,
server_helper.BindSync(server_addr, nullptr, &server_addr)); server_helper.BindSync(server_addr, nullptr, &server_addr));
mojom::UDPSocketPtr socket_ptr; mojom::UDPSocketPtr socket_ptr;
factory.CreateUDPSocket(mojo::MakeRequest(&socket_ptr), nullptr); UDPSocket impl(mojo::MakeRequest(&socket_ptr), nullptr);
test::UDPSocketTestHelper helper(&socket_ptr); test::UDPSocketTestHelper helper(&socket_ptr);
// Invalid options. // Invalid options.
......
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