Packages
thousand_island
0.4.3
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/acceptor.ex
defmodule ThousandIsland.Acceptor do
@moduledoc false
use Task, restart: :transient
alias ThousandIsland.{AcceptorSupervisor, Connection, Listener, Server, ServerConfig}
def start_link(arg) do
Task.start_link(__MODULE__, :run, [arg])
end
def run({server_pid, parent_pid, %ServerConfig{} = config}) do
listener_pid = Server.listener_pid(server_pid)
{:ok, listener_socket} = Listener.listener_socket(listener_pid)
acceptor_info = %{
acceptor_id: unique_id(),
listener_socket: listener_socket,
connection_sup_pid: AcceptorSupervisor.connection_sup_pid(parent_pid),
server_config: config
}
telemetry(:start, %{}, acceptor_info)
accept(acceptor_info)
end
defp accept(
%{
acceptor_id: acceptor_id,
listener_socket: listener_socket,
connection_sup_pid: connection_sup_pid,
server_config: %ServerConfig{transport_module: transport_module} = server_config
} = acceptor_info
) do
start = System.monotonic_time()
case transport_module.accept(listener_socket) do
{:ok, socket} ->
wakeup = System.monotonic_time()
Connection.start(connection_sup_pid, socket, acceptor_id, server_config)
complete = System.monotonic_time()
wait_time = wakeup - start
startup_time = complete - wakeup
telemetry(:accept, %{wait_time: wait_time, startup_time: startup_time}, acceptor_info)
accept(acceptor_info)
{:error, reason} ->
wakeup = System.monotonic_time()
wait_time = wakeup - start
telemetry(:shutdown, %{wait_time: wait_time, shutdown_reason: reason}, acceptor_info)
# Reasons other than closed are unexpected, so raise up and let our supervisor take care of things
if !(reason in [:closed]) do
raise "Unexpected error in accept: #{inspect(reason)}"
end
end
end
defp telemetry(subevent, measurement, acceptor_info) do
acceptor_info = Map.take(acceptor_info, [:acceptor_id, :server_config])
:telemetry.execute([:acceptor] ++ [subevent], measurement, acceptor_info)
end
defp unique_id, do: Base.encode16(:crypto.strong_rand_bytes(6))
end