defmodule Wideact do use Application def start() do start(0, 0) end def start(_type, _args) do import Supervisor.Spec Process.register(spawn(StaleMail, :start, []), :stalemail) children = [ supervisor(Task.Supervisor, [[ name: Wideact.TaskSupervisor ]]), worker(Task, [ Wideact, :accept, [ 40444 ]]) ] opts = [ strategy: :one_for_one, name: Wideact.Supervisor ] Supervisor.start_link(children, opts) end def accept(port) do { :ok, socket } = :gen_tcp.listen(port, [ :binary, packet: :line, active: false, reuseaddr: true, send_timeout: 40 ]) loop_acceptor(socket) end def loop_acceptor(socket) do { :ok, client } = :gen_tcp.accept(socket) { :ok, pid } = Task.Supervisor.start_child(Wideact.TaskSupervisor, fn -> setup(client) end) :gen_tcp.controlling_process(client, pid) loop_acceptor(socket) end def recvloop(client, name) do receive do { :received_message, sender, message } -> case :gen_tcp.send(client, "MESSAGE #{sender} #{message}\n") do :ok -> send :stalemail, { :got_mail, name } { :error, _reason } -> exit(:normal) end _ -> exit(:normal) after 10 -> send :stalemail, { :new_mail, name, self() } end recvloop(client, name) end def setup(socket) do case :gen_tcp.recv(socket, 0) do { :ok, data } -> case data |> String.split(" ", parts: 2) do [ "CONNECT", name ] -> send :stalemail, { :new_mailbox, name, self() } spawn(fn -> recvloop(socket, name) end) serve(socket, name) _ -> :gen_tcp.close(socket) exit(:normal) end _ -> :gen_tcp.close(socket) exit(:normal) end end def serve(socket, name) do case :gen_tcp.recv(socket, 0) do { :ok, data } -> case data |> String.split(" ", parts: 3) do [ "MESSAGE", receiver, message ] -> send :stalemail, { :pass_message, receiver, message, name } [ "PING", receiver ] -> send :stalemail, { :new_mail, receiver, self() } end { :error, _reason } -> nil end serve(socket, name) end end