Current section
Files
Jump to
Current section
Files
lib/echo.ex
defmodule Modbus.Echo do
@moduledoc false
use GenServer
def start_link(opts \\ []) do
ip = Keyword.get(opts, :ip, {127, 0, 0, 1})
port = Keyword.get(opts, :port, 0)
GenServer.start_link(__MODULE__, {ip, port})
end
def init({ip, port}) do
opts = [:binary, ip: ip, packet: :raw, active: false]
case :gen_tcp.listen(port, opts) do
{:ok, listener} ->
spawn_link(fn -> accept(listener) end)
{:ok, {ip, port}} = :inet.sockname(listener)
{:ok,
%{
ip: ip,
port: port,
listener: listener
}}
{:error, reason} ->
{:stop, reason}
end
end
def stop(pid) do
# listener automatic close should
# close the accepting process which
# should close all client sockets
GenServer.stop(pid)
end
def endpoint(pid) do
GenServer.call(pid, :endpoint)
end
def handle_call(:endpoint, _from, state) do
{:reply, {state.ip, state.port}, state}
end
defp accept(listener) do
case :gen_tcp.accept(listener) do
{:ok, socket} ->
spawn(fn -> client(socket) end)
accept(listener)
{:error, reason} ->
Process.exit(self(), reason)
end
end
def client(socket) do
case :gen_tcp.recv(socket, 0) do
{:ok, data} ->
:gen_tcp.send(socket, data)
client(socket)
{:error, reason} ->
Process.exit(self(), reason)
end
end
end