aboutsummaryrefslogtreecommitdiff
path: root/lib/net/manager.ex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/net/manager.ex')
-rw-r--r--lib/net/manager.ex60
1 files changed, 60 insertions, 0 deletions
diff --git a/lib/net/manager.ex b/lib/net/manager.ex
new file mode 100644
index 0000000..e5eb12d
--- /dev/null
+++ b/lib/net/manager.ex
@@ -0,0 +1,60 @@
+defmodule SNet.Manager do
+ use GenServer
+
+ def start_link(my_port) do
+ GenServer.start_link(__MODULE__, my_port, name: __MODULE__)
+ end
+
+ def init(my_port) do
+ state = %{
+ peers: %{},
+ my_port: my_port
+ }
+ {:ok, state}
+ end
+
+ def handle_cast({:peer_up, pk, pid, addr, ip}, state) do
+ new_peers = Map.put(state.peers, pk, {pid, addr, ip})
+ new_state = %{ state | peers: new_peers }
+ {:noreply, new_state}
+ end
+
+ def handle_cast({:peer_down, pk, addr, ip}, state) do
+ new_peers = Map.put(state.peers, pk, {nil, addr, ip})
+ new_state = %{ state | peers: new_peers }
+ {:noreply, new_state}
+ end
+
+ def handle_cast({:add_peer, ip, port}, state) do
+ add_peer(ip, port, state.my_port)
+ {:noreply, state}
+ end
+
+ def handle_cast({:try_connect, pk_list}, state) do
+ for pk <- pk_list do
+ case state.peers[pk] do
+ {nil, ip, port} -> add_peer(ip, port)
+ _ -> nil
+ end
+ end
+ {:noreply, state}
+ end
+
+ def handle_call({:get_connections, pk_list}, state) do
+ pid_list = (for pk <- pk_list, Map.has_key?(state.peers, pk), do: state.peers[pk])
+ |> Enum.map(fn {pid, _, _} -> pid end)
+ |> Enum.filter(&(&1 != nil))
+ {:ok, pid_list, state}
+ end
+
+ def add_peer(ip, port) do
+ GenServer.cast(__MODULE__, {:add_peer, ip, port})
+ end
+
+ def add_peer(ip, port, my_port) do
+ {:ok, client} = :gen_tcp.connect(ip, port, [:binary, packet: 2, active: false])
+ {:ok, pid} = DynamicSupervisor.start_child(SNet.ConnSupervisor, {SNet.TCPConn, %{socket: client, my_port: my_port}})
+ :ok = :gen_tcp.controlling_process(client, pid)
+ pid
+ end
+end