defmodule Frajtano.Listener do require Logger use Task def start_link(path) do Task.start_link(__MODULE__, :run, [path]) end def run(path) do Logger.info("Serving on path #{path}") File.rm(path) {:ok, sock} = :gen_tcp.listen(0, [:binary, active: false, packet: :raw, ifaddr: {:local, path}]) loop(sock) end def loop(sock) do Logger.info("Accepting connections on #{inspect sock}") {:ok, conn} = :gen_tcp.accept(sock) Frajtano.ClientHandler.start(conn) loop(sock) end end defmodule Frajtano.ClientHandler do alias Frajtano.Proto require Logger def start(conn) do Logger.info("Got connection: #{inspect conn}") Task.Supervisor.start_child(Frajtano.ClientSupervisor, fn -> :gen_tcp.controlling_process(conn, self()) handle(conn, <<>>) end) end defp handle(conn, buffer) do Logger.info("Handling connection: #{inspect conn}, buffer: #{inspect buffer}") case Proto.decode(buffer) do {nil, buffer} -> Logger.debug("Need more data") case :gen_tcp.recv(conn, 0) do {:ok, msg} -> Logger.debug("Got more data: #{inspect msg}") handle(conn, buffer <> msg) {:error, :closed} -> nil {:error, error} -> Logger.warning("Got network error: #{inspect error}") end {packet, buffer} -> :gen_tcp.send(conn, Proto.encode(handle_packet(packet))) handle(conn, buffer) end end defp handle_packet({:agentc_request_identities, nil}) do Logger.info("Got identities request") case Frajtano.Agent.identities() do {:ok, identities} -> {:agent_identities_answer, identities} {:error, error} -> Logger.warning("Error fetching identities: #{error}") {:agent_failure, nil} end end defp handle_packet({:agentc_sign_request, request}) do case Frajtano.Agent.sign(request) do {:ok, signature} -> {:agent_sign_response, signature} {:error, error} -> Logger.warning("Error signing: #{error}") {:agent_failure, nil} end end defp handle_packet({type, body}) do Logger.warning("Can't handle #{type} packet with body #{inspect body}") {:agent_failure, nil} end end