View Source ThousandIsland.Transport behaviour (Thousand Island v1.0.0-pre.7)

This module describes the behaviour required for Thousand Island to interact with low-level sockets. It is largely internal to Thousand Island, however users are free to implement their own versions of this behaviour backed by whatever underlying transport they choose. Such a module can be used in Thousand Island by passing its name as the transport_module option when starting up a server, as described in ThousandIsland.

Summary

Types

A socket address

A listener socket options

A listener socket used to wait for connections

The return value from an accept/1 call

The return value from a close/1 call

The return value from a getopts/2 call

The return value from a handshake/1 call

The return value from a negotiated_protocol/1 call

The return value from a peercert/1 call

The return value from a peername/1 call

The return value from a recv/3 call

The return value from a send/2 call

The return value from a sendfile/4 call

The return value from a setopts/2 call

The return value from a shutdown/2 call

The return value from a sockname/1 call

A socket representing a client connection

Options which can be set on a socket via setopts/2 (or returned from getopts/1)

Information about an endpoint, either remote ('peer') or local

Options which can be set on a socket via setopts/2 (or returned from getopts/1)

Connection statistics for a given socket

The direction in which to shutdown a connection in advance of closing it

Callbacks

Wait for a client connection on the given listener socket. This call blocks until such a connection arrives, or an error occurs (such as the listener socket being closed).

Closes the given socket.

Transfers ownership of the given socket to the given process. This will always be called by the process which currently owns the socket.

Gets the given options on the socket.

Returns stats about the connection on the socket.

Performs an initial handshake on a new client connection (such as that done when negotiating an SSL connection). Transports which do not have such a handshake can simply pass the socket through unchanged.

Create and return a listener socket bound to the given port and configured per the provided options.

Returns the protocol negotiated as part of handshaking. Most typically this is via TLS' ALPN or NPN extensions. If the underlying transport does not support protocol negotiation (or if one was not negotiated), {:error, :protocol_not_negotiated} is returned

Returns the peer certificate for the given socket in the form of t:public_key.der_encoded(). If the socket is not secure, {:error, :not_secure} is returned.

Returns information in the form of t:socket_info() about the remote end of the socket.

Returns available bytes on the given socket. Up to num_bytes bytes will be returned (0 can be passed in to get the next 'available' bytes, typically the next packet). If insufficient bytes are available, the function can wait timeout milliseconds for data to arrive.

Returns whether or not this protocol is secure.

Sends the given data (specified as a binary or an IO list) on the given socket.

Sends the contents of the given file based on the provided offset & length

Sets the given options on the socket. Should disallow setting of options which are not compatible with Thousand Island

Shuts down the socket in the given direction.

Returns information in the form of t:socket_info() about the local end of the socket.

Types

@type address() ::
  :inet.ip_address()
  | :inet.local_address()
  | {:local, binary()}
  | :unspec
  | {:undefined, any()}

A socket address

@type listen_options() ::
  [:inet.inet_backend() | :gen_tcp.listen_option()] | [:ssl.tls_server_option()]

A listener socket options

@type listener_socket() :: :inet.socket() | :ssl.sslsocket()

A listener socket used to wait for connections

@type on_accept() ::
  {:ok, socket()} | {:error, on_accept_tcp_error() | on_accept_ssl_error()}

The return value from an accept/1 call

@type on_accept_ssl_error() :: :closed | :timeout | :ssl.error_alert()
@type on_accept_tcp_error() :: :closed | :system_limit | :inet.posix()
@type on_close() :: :ok | {:error, any()}

The return value from a close/1 call

@type on_getopts() :: {:ok, [:inet.socket_optval()]} | {:error, :inet.posix()}

The return value from a getopts/2 call

@type on_handshake() ::
  {:ok, socket()} | {:ok, socket(), any()} | {:error, on_handshake_ssl_error()}

The return value from a handshake/1 call

Link to this type

on_handshake_ssl_error()

View Source
@type on_handshake_ssl_error() :: :closed | :timeout | :ssl.error_alert()
Link to this type

on_negotiated_protocol()

View Source
@type on_negotiated_protocol() ::
  {:ok, binary()} | {:error, :protocol_not_negotiated | :closed}

The return value from a negotiated_protocol/1 call

@type on_peercert() :: {:ok, :public_key.der_encoded()} | {:error, reason :: any()}

The return value from a peercert/1 call

@type on_peername() :: {:ok, socket_info()} | {:error, :inet.posix()}

The return value from a peername/1 call

@type on_recv() :: {:ok, binary()} | {:error, :closed | :timeout | :inet.posix()}

The return value from a recv/3 call

@type on_send() ::
  :ok | {:error, :closed | {:timeout, rest_data :: binary()} | :inet.posix()}

The return value from a send/2 call

@type on_sendfile() ::
  {:ok, non_neg_integer()}
  | {:error, :inet.posix() | :closed | :badarg | :not_owner | :eof}

The return value from a sendfile/4 call

@type on_setopts() :: :ok | {:error, :inet.posix()}

The return value from a setopts/2 call

@type on_shutdown() :: :ok | {:error, :inet.posix()}

The return value from a shutdown/2 call

@type on_sockname() :: {:ok, socket_info()} | {:error, :inet.posix()}

The return value from a sockname/1 call

@type socket() :: :inet.socket() | :ssl.sslsocket()

A socket representing a client connection

@type socket_get_options() :: [:inet.socket_getopt()]

Options which can be set on a socket via setopts/2 (or returned from getopts/1)

Information about an endpoint, either remote ('peer') or local

@type socket_set_options() :: [:inet.socket_setopt()]

Options which can be set on a socket via setopts/2 (or returned from getopts/1)

@type socket_stats() ::
  {:ok, [{:inet.stat_option(), integer()}]} | {:error, :inet.posix()}

Connection statistics for a given socket

@type way() :: :read | :write | :read_write

The direction in which to shutdown a connection in advance of closing it

Callbacks

@callback accept(listener_socket()) :: on_accept()

Wait for a client connection on the given listener socket. This call blocks until such a connection arrives, or an error occurs (such as the listener socket being closed).

@callback close(socket() | listener_socket()) :: on_close()

Closes the given socket.

Link to this callback

controlling_process(socket, pid)

View Source
@callback controlling_process(socket(), pid()) ::
  :ok | {:error, :closed | :not_owner | :badarg | :inet.posix()}

Transfers ownership of the given socket to the given process. This will always be called by the process which currently owns the socket.

Link to this callback

getopts(socket, socket_get_options)

View Source
@callback getopts(socket(), socket_get_options()) :: on_getopts()

Gets the given options on the socket.

@callback getstat(socket()) :: socket_stats()

Returns stats about the connection on the socket.

@callback handshake(socket()) :: on_handshake()

Performs an initial handshake on a new client connection (such as that done when negotiating an SSL connection). Transports which do not have such a handshake can simply pass the socket through unchanged.

Link to this callback

listen(port_number, listen_options)

View Source
@callback listen(:inet.port_number(), listen_options()) ::
  {:ok, listener_socket()} | {:error, any()}

Create and return a listener socket bound to the given port and configured per the provided options.

Link to this callback

negotiated_protocol(socket)

View Source
@callback negotiated_protocol(socket()) :: on_negotiated_protocol()

Returns the protocol negotiated as part of handshaking. Most typically this is via TLS' ALPN or NPN extensions. If the underlying transport does not support protocol negotiation (or if one was not negotiated), {:error, :protocol_not_negotiated} is returned

@callback peercert(socket()) :: on_peercert()

Returns the peer certificate for the given socket in the form of t:public_key.der_encoded(). If the socket is not secure, {:error, :not_secure} is returned.

@callback peername(socket()) :: on_peername()

Returns information in the form of t:socket_info() about the remote end of the socket.

Link to this callback

recv(socket, num_bytes, timeout)

View Source
@callback recv(socket(), num_bytes :: non_neg_integer(), timeout :: timeout()) ::
  on_recv()

Returns available bytes on the given socket. Up to num_bytes bytes will be returned (0 can be passed in to get the next 'available' bytes, typically the next packet). If insufficient bytes are available, the function can wait timeout milliseconds for data to arrive.

@callback secure?() :: boolean()

Returns whether or not this protocol is secure.

@callback send(socket(), data :: iodata()) :: on_send()

Sends the given data (specified as a binary or an IO list) on the given socket.

Link to this callback

sendfile(socket, filename, offset, length)

View Source
@callback sendfile(
  socket(),
  filename :: String.t(),
  offset :: non_neg_integer(),
  length :: non_neg_integer()
) :: on_sendfile()

Sends the contents of the given file based on the provided offset & length

Link to this callback

setopts(socket, socket_set_options)

View Source
@callback setopts(socket(), socket_set_options()) :: on_setopts()

Sets the given options on the socket. Should disallow setting of options which are not compatible with Thousand Island

@callback shutdown(socket(), way()) :: on_shutdown()

Shuts down the socket in the given direction.

@callback sockname(socket() | listener_socket()) :: on_sockname()

Returns information in the form of t:socket_info() about the local end of the socket.