diff options
Diffstat (limited to 'shard/lib/net/group.ex')
-rw-r--r-- | shard/lib/net/group.ex | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/shard/lib/net/group.ex b/shard/lib/net/group.ex index 692438a..f09d174 100644 --- a/shard/lib/net/group.ex +++ b/shard/lib/net/group.ex @@ -81,19 +81,67 @@ defmodule SNet.PrivGroup do defstruct [:pk_list] defimpl SNet.Group do - def init_lookup(%SNet.PubShardGroup{id: id}, notify_to) do - # TODO + def init_lookup(%SNet.PrivGroup{pk_list: pk_list}, notify_to) do + spawn fn -> + # 1. We might already have some connections to these guys + for {_, pid, %SNet.Auth{my_pk: my_pk, his_pk: his_pk}} <- SNet.Manager.list_connections do + if (my_pk in pk_list) and (his_pk in pk_list) do + GenServer.cast(notify_to, {:peer_connected, pid}) + end + end + # 2. We might also want to open some new connections to these guys + [my_pk|_] = Enum.filter(pk_list, &Shard.Keys.have_sk?/1) + for pk <- pk_list do + pid = SApp.Identity.find_proc(pk) + info = GenServer.call(pid, :get_info) + if Map.has_key?(info, :peer_info) do + for pi <- info.peer_info do + SNet.Manager.add_peer(pi, %SNet.Auth{my_pk: my_pk, his_pk: pk}) + # no callback here, we don't know if connect was successful + end + end + end + end end - def get_connections(%SNet.PubShardGroup{id: id}) do - # TODO + def get_connections(%SNet.PrivGroup{pk_list: pk_list}) do + for {_, pid, %SNet.Auth{my_pk: my_pk, his_pk: his_pk}} <- SNet.Manager.list_connections, + (my_pk in pk_list) and (his_pk in pk_list), + do: pid end def broadcast(group, msg, nmax) do + %SNet.PrivGroup{pk_list: pk_list} = group + nsent = get_connections(group) + |> Enum.shuffle + |> Enum.take(nmax) + |> Enum.map(&(GenServer.cast(&1, {:send_msg, msg}))) + |> Enum.count + if nmax - nsent > 0 do + my_pks = Enum.filter(pk_list, &Shard.Keys.have_sk?/1) + [my_pk|_] = my_pks + candidates = for pk <- pk_list, + pid = SApp.Identity.find_proc(pk), + info = GenServer.call(pid, :get_info), + Map.has_key?(info, :peer_info), + xx <- info.peer_info, + do: {xx, pk} + candidates + |> Enum.filter(fn {peer_info, his_pk} -> + SNet.Manager.get_auth_connections_to(peer_info, my_pks, his_pk) == [] end) + |> Enum.shuffle() + |> Enum.take(nmax - nsent) + |> Enum.map(fn {peer_info, his_pk} -> + SNet.Manager.send_auth(peer_info, %SNet.Auth{my_pk: my_pk, his_pk: his_pk}, msg) end) + end end - def in_group?(%SNet.PubShardGroup{id: _id}, peer_pid, auth) do - # TODO + def in_group?(%SNet.PrivGroup{pk_list: pk_list}, _peer_pid, auth) do + case auth do + nil -> false + %SNet.Auth{my_pk: my_pk, his_pk: his_pk} -> + (my_pk in pk_list) and (his_pk in pk_list) + end end end end |