defmodule Exkad.Node.Gateway do alias Exkad.Node alias Exkad.Node.Descriptor, as: ND defp make_id(nil) do :crypto.hash(:md5, UUID.uuid4()) |> :erlang.bitstring_to_list |> Enum.map(&(:io_lib.format("~2.16.0b", [&1]))) |> List.flatten |> :erlang.list_to_bitstring end defp make_id(id), do: id def make_bind(:http, binding), do: binding def make_bind(_, _), do: :self def get_client(:self), do: Exkad.Backends.Simple def get_client(:http), do: Exkad.Backends.HTTP.Client def get_server(:self, :self, nd), do: nd def get_server(:http, bind, %ND{id: id, loc: pid} = nd) do backend = Exkad.Backends.HTTP.Server port = String.split(bind, ":") |> Enum.at(2) |> String.to_integer {:ok, _} = Plug.Adapters.Cowboy.http( backend, [node: nd], port: port, ref: id ) %ND{id: id, loc: bind} end def build_node(id \\ nil, seed \\ nil, protocol \\ :self, port \\ nil) do id = make_id(id) bind = make_bind(protocol, port) client = get_client(protocol) {:ok, node_pid} = Node.start_link([id: id, seed: seed, tx: client, bind: bind]) nd = %ND{id: id, loc: node_pid} nd = get_server(protocol, bind, nd) {node_pid, nd} end def dump(pid) do GenServer.call(pid, :dump) end def describe(pid) do GenServer.call(pid, :describe) end def get(pid, key) do case GenServer.call(pid, {:rget, key}) do {:value, {:ok, value}} -> value = :base64.decode(value) |> :erlang.binary_to_term {:value, {:ok, value}} err -> err end end def put(pid, value, meta \\ %{}) do bin = :erlang.term_to_binary(value) |> :base64.encode GenServer.call(pid, {:rput, bin, meta}) end def search(pid, term) do GenServer.call(pid, {:rsearch, term}) end def ping(pid, to) do GenServer.call(pid, {:make_ping, to}) end end