Packages

Wideact is an inter-lingual actor system, enabling different languages to communicate seamlessly over the network. It implements a very primitive protocol, capable of only transmiting messages to named actors. It also serves with semi-persistence, and will save messages for an actor until they ar...

Current section

Files

Jump to
wideact lib wideact.ex
Raw

lib/wideact.ex

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