blob: ca732c0501d0074cbbf3fbee94945210bcf03172 [file] [log] [blame]
// 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_DATA_PUMP_H_
#define SERVICES_NETWORK_SOCKET_DATA_PUMP_H_
#include <memory>
#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/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/address_family.h"
#include "net/base/ip_endpoint.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 StreamSocket;
} // namespace net
namespace network {
// This class handles reading/writing logic between a network socket and a mojo
// pipe. Specifically, it (1) reads from the network socket and writes to a mojo
// producer pipe, and (2) reads from a mojo consumer pipe and writes to the
// network socket. On network read/write errors, it (3) also notifies the
// mojom::SocketObserverPtr appropriately.
class COMPONENT_EXPORT(NETWORK_SERVICE) SocketDataPump {
public:
// Interface to notify a consumer that about network errors and whether both
// data pipes have been shut down from the client side.
class Delegate {
public:
Delegate() {}
~Delegate() {}
// Called when SocketDataPump detects a network read error.
virtual void OnNetworkReadError(int net_error) = 0;
// Called when SocketDataPump detects a network write error.
virtual void OnNetworkWriteError(int net_error) = 0;
// Called when SocketDataPump detects both send and receive pipes have shut
// down.
virtual void OnShutdown() = 0;
};
// Constructs a data pump that pumps data between |socket| and mojo data
// pipe handles. Data are read from |send_pipe_handle| and sent to |socket|.
// Data are read from |socket| and written to |receive_pipe_handle|.
// |traffic_annotation| is attached to all writes to |socket|. Note that
// |socket| must outlive |this|.
SocketDataPump(net::StreamSocket* socket,
Delegate* delegate,
mojo::ScopedDataPipeProducerHandle receive_pipe_handle,
mojo::ScopedDataPipeConsumerHandle send_pipe_handle,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
~SocketDataPump();
private:
// Maybe notifies |delegate_| of the shutdown if both pipes are closed.
void MaybeNotifyDelegate();
// "Receiving" in this context means reading from |socket_| and writing to
// the Mojo |receive_stream_|.
void ReceiveMore();
void OnReceiveStreamWritable(MojoResult result);
void OnReceiveStreamClosed(MojoResult result);
void OnNetworkReadIfReadyCompleted(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();
net::StreamSocket* const socket_;
Delegate* const delegate_;
// The *stream handles will be null when there's a pending read from |socket_|
// to |pending_receive_buffer_|, or while there is a pending write from
// |pending_send_buffer_| to |socket_|. During this time, the handles will
// be owned by the *PendingBuffer.
//
// The watchers need to be declared after the corresponding handle, so they
// can be cleaned up before the handles are.
// For reading from the network and writing to Mojo pipe.
mojo::ScopedDataPipeProducerHandle receive_stream_;
mojo::SimpleWatcher receive_stream_watcher_;
// A separate watcher is needed to observe |receive_stream_|'s close event, so
// that when the client shuts down their end of the pipe for
// TCPConnectedSocket::UpgradeToTLS() during the waiting of the async callback
// of ReadIfReady, |this| can be notified of the shutdown.
mojo::SimpleWatcher receive_stream_close_watcher_;
bool read_if_ready_pending_ = false;
// For reading from the Mojo pipe and writing to the network.
mojo::ScopedDataPipeConsumerHandle send_stream_;
scoped_refptr<MojoToNetPendingBuffer> pending_send_buffer_;
mojo::SimpleWatcher send_stream_watcher_;
const net::NetworkTrafficAnnotationTag traffic_annotation_;
base::WeakPtrFactory<SocketDataPump> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SocketDataPump);
};
} // namespace network
#endif // SERVICES_NETWORK_SOCKET_DATA_PUMP_H_