Current section

Files

Jump to
tortoise lib tortoise transport ssl.ex
Raw

lib/tortoise/transport/ssl.ex

defmodule Tortoise.Transport.SSL do
@moduledoc false
@behaviour Tortoise.Transport
alias Tortoise.Transport
@default_opts [verify: :verify_peer]
@impl true
def new(opts) do
{host, opts} = Keyword.pop(opts, :host)
{port, opts} = Keyword.pop(opts, :port)
host = coerce_host(host)
opts = Keyword.merge(@default_opts, opts)
opts = [:binary, {:packet, :raw}, {:active, false} | opts]
%Transport{type: __MODULE__, host: host, port: port, opts: opts}
end
defp coerce_host(host) when is_binary(host) do
String.to_charlist(host)
end
defp coerce_host(otherwise) do
otherwise
end
@impl true
def connect(host, port, opts, timeout) do
# [:binary, active: false, packet: :raw]
:ssl.connect(host, port, opts, timeout)
end
@impl true
def recv(socket, length, timeout) do
:ssl.recv(socket, length, timeout)
end
@impl true
def send(socket, data) do
:ssl.send(socket, data)
end
@impl true
def setopts(socket, opts) do
:ssl.setopts(socket, opts)
end
@impl true
def getopts(socket, opts) do
:ssl.getopts(socket, opts)
end
@impl true
def getstat(socket) do
:ssl.getstat(socket)
end
@impl true
def getstat(socket, opt_names) do
:ssl.getstat(socket, opt_names)
end
@impl true
def controlling_process(socket, pid) do
:ssl.controlling_process(socket, pid)
end
@impl true
def peername(socket) do
:ssl.peername(socket)
end
@impl true
def sockname(socket) do
:ssl.sockname(socket)
end
@impl true
def shutdown(socket, mode) when mode in [:read, :write, :read_write] do
:ssl.shutdown(socket, mode)
end
@impl true
def close(socket) do
:ssl.close(socket)
end
@impl true
def listen(opts) do
case Keyword.has_key?(opts, :cert) do
true ->
:ssl.listen(0, opts)
false ->
throw("Please specify the cert key for the SSL transport")
end
end
@impl true
def accept(listen_socket, timeout) do
:ssl.transport_accept(listen_socket, timeout)
end
@impl true
def accept_ack(client_socket, timeout) do
case :ssl.ssl_accept(client_socket, timeout) do
:ok ->
:ok
# abnormal data sent to socket
{:error, {:tls_alert, _}} ->
:ok = close(client_socket)
exit(:normal)
# Socket most likely stopped responding, don't error out.
{:error, reason} when reason in [:timeout, :closed] ->
:ok = close(client_socket)
exit(:normal)
{:error, reason} ->
:ok = close(client_socket)
throw(reason)
end
end
end