aboutsummaryrefslogblamecommitdiff
path: root/lib/net/manager.ex
blob: e5eb12d0ab1eb120fa713403b3b9d29781cece5e (plain) (tree)



























































                                                                                                                        
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