aboutsummaryrefslogtreecommitdiff
path: root/shard/lib/net/group.ex
diff options
context:
space:
mode:
Diffstat (limited to 'shard/lib/net/group.ex')
-rw-r--r--shard/lib/net/group.ex60
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