Sovite.Listener (sovite v0.2.0)

Copy Markdown View Source

A TCP listener with an acceptor pool and connection limits.

Each accepted connection is served by its own process, started from a Sovite.Listener.Handler module under the listener's connection supervisor. Connections over a limit are refused: the handler's optional reject/3 callback can send a protocol-level refusal first.

children = [
  {Sovite.Listener, port: 2525, handler: MyHandler, handler_opts: []}
]

IPv4-mapped IPv6 peer addresses are reported as IPv4. IPv6 listeners are IPv6-only, so 0.0.0.0 and :: can listen on the same port.

Options

  • :port - TCP port, 0 for any free port. Required.
  • :ip - address to listen on. Defaults to {0, 0, 0, 0}.
  • :handler - a Sovite.Listener.Handler module. Required.
  • :handler_opts - passed to the handler. Defaults to [].
  • :id - label in telemetry metadata and connection info. Defaults to "<ip>:<port>".
  • :name - registered name of the listener supervisor.
  • :acceptors - number of acceptor processes. Defaults to 10.
  • :max_connections - concurrent connections. Defaults to 1000.
  • :max_connections_per_ip - concurrent connections from one remote address, or nil for no limit. Defaults to nil.

Telemetry

  • [:sovite, :listener, :connection, :start] - %{system_time}, %{listener, remote_ip, remote_port}
  • [:sovite, :listener, :connection, :stop] - %{duration}, same metadata
  • [:sovite, :listener, :connection, :rejected] - %{}, %{listener, remote_ip, reason}

Summary

Types

Passed to the handler's start_link/2.

Why a connection was refused.

Functions

Returns the number of open connections.

Waits until the listener has handed the socket in info over to the calling connection process. Call it before using the socket.

Returns the address and port the listener is bound to.

Starts the listener. See the module docs for options.

Types

connection_info()

@type connection_info() :: %{
  listener: String.t(),
  socket: :gen_tcp.socket(),
  remote_ip: :inet.ip_address(),
  remote_port: :inet.port_number(),
  local_ip: :inet.ip_address(),
  local_port: :inet.port_number()
}

Passed to the handler's start_link/2.

reject_reason()

@type reject_reason() :: :max_connections | :max_connections_per_ip

Why a connection was refused.

Functions

connection_count(listener)

@spec connection_count(Supervisor.supervisor()) :: non_neg_integer()

Returns the number of open connections.

handshake(map, timeout \\ 5000)

@spec handshake(connection_info(), timeout()) :: :ok | {:error, :timeout}

Waits until the listener has handed the socket in info over to the calling connection process. Call it before using the socket.

sockname(listener)

@spec sockname(Supervisor.supervisor()) ::
  {:ok, {:inet.ip_address(), :inet.port_number()}} | {:error, term()}

Returns the address and port the listener is bound to.

start_link(opts)

@spec start_link(keyword()) :: Supervisor.on_start()

Starts the listener. See the module docs for options.