diff options
Diffstat (limited to 'lib/net/manager.ex')
-rw-r--r-- | lib/net/manager.ex | 60 |
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 |