Packages
thousand_island
1.0.0-pre.1
1.5.0
1.4.3
1.4.2
1.4.1
1.4.0
1.3.14
1.3.13
1.3.12
1.3.11
1.3.10
1.3.9
1.3.8
1.3.7
1.3.6
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.0
1.1.0
1.0.0
1.0.0-pre.7
1.0.0-pre.6
1.0.0-pre.5
1.0.0-pre.4
1.0.0-pre.3
1.0.0-pre.2
1.0.0-pre.1
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.17
0.5.16
0.5.15
0.5.14
0.5.13
0.5.12
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
A simple & modern pure Elixir socket server
Current section
Files
Jump to
Current section
Files
lib/thousand_island/transports/tcp.ex
defmodule ThousandIsland.Transports.TCP do
@moduledoc """
Defines a `ThousandIsland.Transport` implementation based on clear TCP sockets
as provided by Erlang's `:gen_tcp` module. For the most part, users of Thousand
Island will only ever need to deal with this module via `transport_options`
passed to `ThousandIsland` at startup time. A complete list of such options
is defined via the `t::gen_tcp.listen_option()` type. This list can be somewhat
difficult to decipher; by far the most common value to pass to this transport
is the following:
* `ip`: The IP to listen on. Can be specified as:
* `{1, 2, 3, 4}` for IPv4 addresses
* `{1, 2, 3, 4, 5, 6, 7, 8}` for IPv6 addresses
* `:loopback` for local loopback
* `:any` for all interfaces (ie: `0.0.0.0`)
* `{:local, "/path/to/socket"}` for a Unix domain socket. If this option is used, the `port`
option *must* be set to `0`.
Unless overridden, this module uses the following default options:
```elixir
backlog: 1024,
nodelay: true,
linger: {true, 30},
send_timeout: 30_000,
send_timeout_close: true,
reuseaddr: true
```
The following options are required for the proper operation of Thousand Island
and cannot be overridden:
```elixir
mode: :binary,
active: false
```
"""
@type options() :: [:gen_tcp.listen_option()]
@behaviour ThousandIsland.Transport
@hardcoded_options [mode: :binary, active: false]
@impl ThousandIsland.Transport
def listen(port, user_options) do
default_options = [
backlog: 1024,
nodelay: true,
linger: {true, 30},
send_timeout: 30_000,
send_timeout_close: true,
reuseaddr: true
]
resolved_options = @hardcoded_options ++ user_options ++ default_options
:gen_tcp.listen(port, resolved_options)
end
@impl ThousandIsland.Transport
defdelegate accept(listener_socket), to: :gen_tcp
@impl ThousandIsland.Transport
def handshake(socket), do: {:ok, socket}
@impl ThousandIsland.Transport
defdelegate controlling_process(socket, pid), to: :gen_tcp
@impl ThousandIsland.Transport
defdelegate recv(socket, length, timeout), to: :gen_tcp
@impl ThousandIsland.Transport
defdelegate send(socket, data), to: :gen_tcp
@impl ThousandIsland.Transport
def sendfile(socket, filename, offset, length) do
with {:ok, fd} <- :file.open(filename, [:raw]) do
:file.sendfile(fd, socket, offset, length, [])
end
end
@impl ThousandIsland.Transport
defdelegate getopts(socket, options), to: :inet
@impl ThousandIsland.Transport
defdelegate setopts(socket, options), to: :inet
@impl ThousandIsland.Transport
defdelegate shutdown(socket, way), to: :gen_tcp
@impl ThousandIsland.Transport
defdelegate close(socket), to: :gen_tcp
@impl ThousandIsland.Transport
def local_info(socket) do
case :inet.sockname(socket) do
{:ok, {:local, path}} -> %{address: {:local, path}, port: 0, ssl_cert: nil}
{:ok, {ip, port}} -> %{address: ip, port: port, ssl_cert: nil}
other -> other
end
end
@impl ThousandIsland.Transport
def peer_info(socket) do
{:ok, {ip, port}} = :inet.peername(socket)
%{address: ip, port: port, ssl_cert: nil}
end
@impl ThousandIsland.Transport
def secure?, do: false
@impl ThousandIsland.Transport
defdelegate getstat(socket), to: :inet
@impl ThousandIsland.Transport
def negotiated_protocol(_socket), do: {:error, :protocol_not_negotiated}
end