Current section
Files
Jump to
Current section
Files
lib/tcp.ex
defmodule Sonix.Tcp do
@moduledoc """
TCP Connection Layer for Sonix
"""
use Connection
def start_link(host, port, opts, timeout \\ 5000) do
Connection.start_link(__MODULE__, {host, port, opts, timeout})
end
@doc """
Send any Command to Sonic
## Examples
iex> Sonix.send(conn, "PING")
:ok
"""
def send(conn, data), do: Connection.call(conn, {:send, data<>"\n"})
@doc """
Recieve response from Sonic
## Examples
iex> Sonix.recv(conn)
PONG
"""
def recv(conn, bytes \\ 0, timeout \\ 3000) do
{:ok, x} = Connection.call(conn, {:recv, bytes, timeout})
x = x |> String.slice(0..-2)
case x do
"ERR " <> reason -> raise reason
_-> x
end
end
def close(conn), do: Connection.call(conn, :close)
def init({host, port, opts, timeout}) do
s = %{host: host, port: port, opts: opts, timeout: timeout, sock: nil}
{:connect, :init, s}
end
def connect(_, %{sock: nil, host: host, port: port, opts: opts,
timeout: timeout} = s) do
case :gen_tcp.connect(host, port, [active: false] ++ opts, timeout) do
{:ok, sock} ->
{:ok, %{s | sock: sock}}
{:error, _} ->
{:backoff, 1000, s}
end
end
def disconnect(info, %{sock: sock} = s) do
:ok = :gen_tcp.close(sock)
case info do
{:close, from} ->
Connection.reply(from, :ok)
{:error, :closed} ->
:error_logger.format("Connection closed~n", [])
{:error, reason} ->
reason = :inet.format_error(reason)
:error_logger.format("Connection error: ~s~n", [reason])
end
{:connect, :reconnect, %{s | sock: nil}}
end
def handle_call(_, _, %{sock: nil} = s) do
{:reply, {:error, :closed}, s}
end
def handle_call({:send, data}, _, %{sock: sock} = s) do
case :gen_tcp.send(sock, data) do
:ok ->
{:reply, :ok, s}
{:error, _} = error ->
{:disconnect, error, error, s}
end
end
def handle_call({:recv, bytes, timeout}, _, %{sock: sock} = s) do
case :gen_tcp.recv(sock, bytes, timeout) do
{:ok, _} = ok ->
{:reply, ok, s}
{:error, :timeout} = timeout ->
{:reply, timeout, s}
{:error, _} = error ->
{:disconnect, error, error, s}
end
end
def handle_call(:close, from, s) do
{:disconnect, {:close, from}, s}
end
end