Packages

A standalone Elixir implementation of the Libp2p networking stack

Current section

Files

Jump to
libp2p_elixir lib libp2p transport tcp.ex
Raw

lib/libp2p/transport/tcp.ex

defmodule Libp2p.Transport.Tcp do
@moduledoc """
TCP transport helpers for libp2p.
Uses `:gen_tcp` in passive mode (`active: false`) and raw packets.
"""
@type socket :: port()
@default_listen_opts [:binary, packet: :raw, active: false, reuseaddr: true, nodelay: true]
@default_dial_opts [:binary, packet: :raw, active: false, nodelay: true]
@spec listen(:inet.ip_address(), :inet.port_number(), keyword()) :: {:ok, socket()} | {:error, term()}
def listen(ip, port, opts \\ []) do
backlog = Keyword.get(opts, :backlog, 128)
tcp_opts = Keyword.get(opts, :tcp_opts, [])
:gen_tcp.listen(
port,
@default_listen_opts ++ tcp_opts ++ [ip: ip, backlog: backlog]
)
end
@spec accept(socket(), timeout()) :: {:ok, socket()} | {:error, term()}
def accept(listener, timeout \\ 5_000) do
:gen_tcp.accept(listener, timeout)
end
@spec dial(:inet.ip_address() | charlist(), :inet.port_number(), keyword()) :: {:ok, socket()} | {:error, term()}
def dial(host, port, opts \\ []) do
timeout = Keyword.get(opts, :timeout, 5_000)
tcp_opts = Keyword.get(opts, :tcp_opts, [])
:gen_tcp.connect(host, port, @default_dial_opts ++ tcp_opts, timeout)
end
@spec close(socket()) :: :ok
def close(sock), do: :gen_tcp.close(sock)
@spec send(socket(), iodata()) :: :ok | {:error, term()}
def send(sock, data), do: :gen_tcp.send(sock, data)
@spec recv(socket(), non_neg_integer(), timeout()) :: {:ok, binary()} | {:error, term()}
def recv(sock, len, timeout \\ 5_000), do: :gen_tcp.recv(sock, len, timeout)
@spec peername(socket()) :: {:ok, {:inet.ip_address(), :inet.port_number()}} | {:error, term()}
def peername(sock), do: :inet.peername(sock)
@spec sockname(socket()) :: {:ok, {:inet.ip_address(), :inet.port_number()}} | {:error, term()}
def sockname(sock), do: :inet.sockname(sock)
end