chromium/services/network/public/mojom/tcp_socket.mojom

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

module network.mojom;

import "services/network/public/mojom/address_list.mojom";
import "services/network/public/mojom/ip_endpoint.mojom";
import "services/network/public/mojom/optional_bool.mojom";
import "services/network/public/mojom/ssl_config.mojom";
import "services/network/public/mojom/tls_socket.mojom";
import "services/network/public/mojom/network_param.mojom";
import "services/network/public/mojom/mutable_network_traffic_annotation_tag.mojom";
import "services/network/public/mojom/socket_connection_tracker.mojom";

struct TCPKeepAliveOptions {
  // Enable/disable TCP Keep-Alive.
  bool enable = false;

  // Keep-Alive delay in seconds.
  uint16 delay = 0;
};

struct TCPConnectedSocketOptions {
  // Sets the OS send buffer size (in bytes) for the socket. This is the
  // SO_SNDBUF socket option. If 0, the default size is used. The value will
  // be clamped to a reasonable range.
  int32 send_buffer_size = 0;

  // Sets the OS receive buffer size (in bytes) for the socket. This is the
  // SO_RCVBUF socket option. If 0, the default size is used. The value will
  // be clamped to a reasonable range.
  int32 receive_buffer_size = 0;

  // This function enables/disables buffering in the kernel. By default, on
  // Linux, TCP sockets will wait up to 200ms for more data to complete a packet
  // before transmitting. The network service, however, overrides the default
  // setting all socket, so the kernel will not wait unless this is set to
  // false. See TCP_NODELAY in `man 7 tcp`. On Windows, the Nagle implementation
  // is governed by RFC 896.
  bool no_delay = true;

  // This entry enables/disables the TCP Keep-Alive and sets SO_KEEPALIVE on the
  // socket to the specified delay in seconds. If not supplied, then default
  // socket settings will be applied, which may vary by platform.
  TCPKeepAliveOptions? keep_alive_options;
};

struct TCPServerSocketOptions {
  // Sets the size of the OS accept queue. Should be greater than 0.
  uint32 backlog;

  // Sets IPV6_V6ONLY on the socket to enable/disable dual stack mode.
  // |true| restricts incoming connections to IPv6 only; |false| allows both
  // IPv4/IPv6 connections. Leaving this value unset results in platform default
  // being applied (|true| on Windows, |false| on Posix).
  // TODO(crbug.com/40262165): Investigate the possibility of replacing optional
  // with a platform-agnostic default.
  OptionalBool ipv6_only;

  [EnableIf=is_chromeos]
  // The caller may choose to supply a |connection_tracker| if they lack access
  // to the endpoints of the actual connection but would like to get informed
  // when it shuts down.
  pending_remote<SocketConnectionTracker>? connection_tracker;
};

// Represents a bound TCP socket. Once a call succeeds, cannot be reused.
interface TCPBoundSocket {
  // Starts listening on the socket. |net_error| is set to net::OK on success,
  // or a network error code on failure. Works just like
  // NetworkContext::CreateServerSocket, except it operates on an already bound
  // socket. The TCPBoundSocket will be destroyed on completion, whether the
  // call succeeds or not.
  Listen(uint32 backlog, pending_receiver<TCPServerSocket> socket)
      => (int32 net_error);

  // Attempts to connect the socket to |remote_addr_list|. |net_error| is set to
  // net::OK on success, or a network error code on failure.  Works just like
  // NetworkContext::CreateTCPConnectedSocket(), except it operates on an
  // already bound socket. The TCPBoundSocket will be destroyed on completion,
  // whether the call succeeds or not.
  Connect(
      AddressList remote_addr_list,
      TCPConnectedSocketOptions? tcp_connected_socket_options,
      pending_receiver<TCPConnectedSocket> socket,
      pending_remote<SocketObserver>? observer)
      => (int32 net_error,
          IPEndPoint? local_addr,
          IPEndPoint? peer_addr,
          handle<data_pipe_consumer>? receive_stream,
          handle<data_pipe_producer>? send_stream);
};

// Represents a connected TCP socket. Writes and Reads are through the data
// pipes supplied upon construction. Consumer should use
// SocketObserver 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 {
  // Upgrades a TCP socket to a TLS client socket. Caller can optionally specify
  // a TLSClientSocketOptions to configure the connection.
  // IMPORTANT: Caller needs close the previous send and receive pipes before
  // this method can complete asynchronously.
  //
  // On success, |net_error| 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.
  // |ssl_info| is only returned if |options::unsafely_skip_cert_verification|
  // is true.
  UpgradeToTLS(HostPortPair host_port_pair,
               TLSClientSocketOptions? options,
               MutableNetworkTrafficAnnotationTag traffic_annotation,
               pending_receiver<TLSClientSocket> receiver,
               pending_remote<SocketObserver>? observer)
      => (int32 net_error,
          handle<data_pipe_consumer>? receive_stream,
          handle<data_pipe_producer>? send_stream,
          SSLInfo? ssl_info);

  // Socket options:
  // Note that an implementation can apply default socket options suitable for
  // the platform. Consumers do not need to set these themselves unless they
  // want to change the default settings.

  // These set the send / receive buffer sizes on the connected socket. See the
  // corresponding values in TCPConnectedSocketOptions for descriptions,
  // though note that passing in "0" here will set the size to the minimum
  // value, instead of restoring the default. Consumers should prefer setting
  // these values on creation, as some platforms may not respect changes to
  // these values on a connected socket, even if the method succeeds. These are
  // present mostly for legacy consumers that expose the behavior to
  // non-Chrome code.
  // A network error code is returned on completion.
  SetSendBufferSize(int32 send_buffer_size) => (int32 net_error);
  SetReceiveBufferSize(int32 receive_buffer_size) => (int32 net_error);

  // Enables / disables TCP_NODELAY on the connected socket. See
  // TCPConnectedSocketOptions::no_delay for more details.
  // Returns whether the operation was successful.
  //
  // Should not be called and will always fail until the socket has connected
  // successfully (signalled by a successful result from a
  // CreateTCPConnectedSocket() callback).
  SetNoDelay(bool no_delay) => (bool success);

  // Enables or disables TCP Keep-Alive. This sets SO_KEEPALIVE on the socket.
  // |delay_secs| specifies the amount of time to delay in seconds.
  // Returns whether the operation is successful.
  //
  // Should not be called and will always fail until the socket has connected
  // successfully (signalled by a successful result from a
  // CreateTCPConnectedSocket() callback).
  SetKeepAlive(bool enable, int32 delay_secs) => (bool success);
};

// Interface to listen for network connection error on a TCPConnectedSocket or
// a TLSClientSocket. 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 SocketObserver {
  // Called when a network read fails. Called with net::OK if the socket was
  // closed gracefully. The producer side of |receive_stream| will be closed.
  OnReadError(int32 net_error);

  // Called when a network write fails. 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. |observer| if non-null will be
  // used to listen for any network connection error on the newly established
  // connection. 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.
  //
  // Accepted sockets may not be upgraded to TLS by invoking UpgradeToTLS, as
  // UpgradeToTLS only supports the client part of the TLS handshake.
  Accept(pending_remote<SocketObserver>? observer)
      => (int32 net_error,
          IPEndPoint? remote_addr,
          pending_remote<TCPConnectedSocket>? connected_socket,
          handle<data_pipe_consumer>? send_stream,
          handle<data_pipe_producer>? receive_stream);
};