Current section

Files

Jump to
ace lib ace socket.ex
Raw

lib/ace/socket.ex

defmodule Ace.Socket do
@moduledoc """
Wrapper to normalise interactions with tcp or tls sockets.
NOTE: tls sockets use the `:ssl` module and are identified with `:ssl` atom
"""
@typedoc """
Wrapped tcp socket or tls socket.
"""
@type t :: {:tcp, :inet.socket()} | {:ssl, :"ssl.SslSocket"}
@typedoc """
Wrapped listen socket.
"""
@type listen_socket :: {:ssl, :"ssl.ListenSocket"} | {:tcp, :inet.socket()}
def accept({:tcp, listen_socket}) do
case :gen_tcp.accept(listen_socket) do
{:ok, socket} ->
{:ok, {:tcp, socket}}
{:error, reason} ->
{:error, reason}
end
end
def accept({:ssl, listen_socket}) do
case :ssl.transport_accept(listen_socket) do
{:ok, socket} ->
case :ssl.ssl_accept(socket) do
:ok ->
{:ok, {:ssl, socket}}
{:error, :closed} ->
{:error, :econnaborted}
{:error, reason} ->
{:error, reason}
end
{:error, reason} ->
{:error, reason}
end
end
def port({:tcp, socket}) do
:inet.port(socket)
end
def port({:ssl, socket}) do
{:ok, {_, port}} = :ssl.sockname(socket)
{:ok, port}
end
def negotiated_protocol({:tcp, _socket}) do
:http1
end
def negotiated_protocol({:ssl, socket}) do
case :ssl.negotiated_protocol(socket) do
{:ok, "h2"} ->
:http2
{:ok, "http/1.1"} ->
:http1
{:error, :protocol_not_negotiated} ->
:http1
end
end
def set_active({:tcp, socket}) do
:inet.setopts(socket, active: :once)
end
def set_active({:ssl, socket}) do
:ssl.setopts(socket, active: :once)
end
def send({:tcp, socket}, message) do
:gen_tcp.send(socket, message)
end
def send({:ssl, socket}, message) do
:ssl.send(socket, message)
end
end