aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO86
-rw-r--r--shard/lib/app/chat.ex6
-rw-r--r--shard/lib/app/identity.ex56
-rw-r--r--shard/lib/cli/cli.ex35
-rw-r--r--shard/lib/manager.ex16
-rw-r--r--shardweb/lib/shard_web/channels/room_channel.ex12
6 files changed, 103 insertions, 108 deletions
diff --git a/TODO b/TODO
index 177f292..dd13e1d 100644
--- a/TODO
+++ b/TODO
@@ -10,19 +10,26 @@ achieves our goals.
TASK LIST
=========
-- Highest priority: comm, privchat, ep
+- High priority: invite
- Medium priority: dht, dep
-Architecture for communication primitives (comm, MED)
------------------------------------------
+Invitation system (invite, EASY)
+--------------------------------
-Find the right abstraction(s) for communiation channels.
+A user may generate invitation tokens: an invite token is a signature of the
+invited user's pk by the inviter user's sk. The user that redeems the token
+writes some data that is saved temporarily in the user's identity shard, which
+might be stored by a 3rd party node for instance if we are on mobile devices
+that cannot connect directly.
+
+
+Networking improvements (net, HARD)
+-----------------------
Here are some things to keep in mind that we want at some point:
-- Encrypted point to point communication (to communicate private info after ACL check)
-- Flooding, gossip, RPS
+- RPS
- Congestion control, proper multiplexing of feeds
- Proper management of open connections to peers
@@ -43,22 +50,6 @@ Second option: custom DHT protocol (we probably won't be doing this
anytime soon, if ever at all)
-Epidemic broadcast (ep, EASY)
-------------------
-
-When a shard recieves new information from a peer, transfer that
-information to some other neigbors.
-
-How to select such neighbors ?
-
-a. All those that we know of
-b. Those that we are currently connected to
-c. A random number of known peers
-
-Best option: those that we are connected to + some random to
-reach a quota (for example 10 or so)
-
-
Partial merges, background pulls, caching (cache, req: bg, HARD)
-----------------------------------------
@@ -78,22 +69,6 @@ infrequently used pages, for examples those of old data that is only
kept for archival purpose.
-Private chat (privchat, MED)
-------------
-
-Proof-of-concept for private things: shard for private chat between two people.
-
-
-Invitation system (invite, EASY)
---------------------------------
-
-A user may generate invitation tokens: an invite token is a (sk, pk) plus a
-signature of pk by the user's sk. The user that redeems the token writes some
-data signed by sk that is saved temporarily in the user's identity shard, which
-might be stored by a 3rd party node for instance if we are on mobile devices
-that cannot connect directly.
-
-
User groups and access control (groups, req: sign, HARD)
------------------------------
@@ -124,8 +99,8 @@ access control decisions (obviously these can only run when an
identity with admin privilege is running).
-Shard dependency management (dep, MED)
----------------------------
+Shard lifetime and dependency management (dep, MED)
+----------------------------------------
Some Shards may pull other shards in, under certain conditions. For example
a stored folder shard will just be a list of other shards that we all pull in.
@@ -181,3 +156,34 @@ a correct signature from a certain identity.
We can have a special "identity" shard type that enables storing
profile information such as nickname or other information that we
might want to make public.
+
+
+Architecture for communication primitives (comm, MED)
+-----------------------------------------
+
+- Encrypted point to point communication (to communicate private info after ACL check) -> SHS
+- Flooding, gossip -> netgroups
+
+
+Private chat (privchat, MED)
+------------
+
+Proof-of-concept for private things: shard for private chat between two people.
+
+
+Epidemic broadcast (ep, EASY)
+------------------
+
+When a shard recieves new information from a peer, transfer that
+information to some other neigbors.
+
+How to select such neighbors ?
+
+a. All those that we know of
+b. Those that we are currently connected to
+c. A random number of known peers
+
+Best option: those that we are connected to + some random to
+reach a quota (for example 10 or so)
+
+Implementation: netgroups (lib/net/groups.ex)
diff --git a/shard/lib/app/chat.ex b/shard/lib/app/chat.ex
index 35ecdbf..ea210d8 100644
--- a/shard/lib/app/chat.ex
+++ b/shard/lib/app/chat.ex
@@ -108,12 +108,6 @@ defmodule SApp.Chat do
end
end
- def find_proc(chan) do
- manifest = %Manifest{channel: chan}
- id = SData.term_hash manifest
- Shard.Manager.find_proc id
- end
-
@doc """
Implementation of the :manifest call that returns the chat room's manifest
"""
diff --git a/shard/lib/app/identity.ex b/shard/lib/app/identity.ex
index 06bc225..02e8eb9 100644
--- a/shard/lib/app/identity.ex
+++ b/shard/lib/app/identity.ex
@@ -46,30 +46,6 @@ defmodule SApp.Identity do
end
end
- def default_nick(pk) do
- nick_suffix = Shard.Keys.pk_display pk
- "Anon" <> nick_suffix
- end
-
- def find_proc(pk) do
- manifest = %Manifest{pk: pk}
- id = SData.term_hash manifest
- case Shard.Manager.find_proc id do
- nil ->
- case Shard.Manifest.start manifest do
- {:ok, pid} -> pid
- {:error, :redundant} -> find_proc(pk)
- end
- pid -> pid
- end
- end
-
- def get_nick(pk) do
- pid = find_proc pk
- info = GenServer.call(pid, :get_info)
- info.nick
- end
-
def handle_call(:manifest, _from, state) do
{:reply, state.manifest, state}
end
@@ -136,8 +112,38 @@ defmodule SApp.Identity do
{:noreply, state}
end
- def bcast_state(state, _exclude \\ []) do
+ defp bcast_state(state, _exclude \\ []) do
# TODO: effectively apply exclude list
SNet.Group.broadcast(state.netgroup, {state.id, nil, {:update, SData.SignRev.signed(state.state), false}})
end
+
+ # ================
+ # PUBLIC INTERFACE
+ # ================
+
+ @doc"""
+ Return the default nickname associated to a pk,
+ in the form "Anonxxxxxxxx" with some bytes of the pk in hex.
+ """
+ def default_nick(pk) do
+ nick_suffix = Shard.Keys.pk_display pk
+ "Anon" <> nick_suffix
+ end
+
+ @doc"""
+ Find the shard process for an identity. Launches such a process
+ if necessary.
+ """
+ def find_proc(pk) do
+ Shard.Manager.find_or_start %Manifest{pk: pk}
+ end
+
+ @doc"""
+ Get a user's nickname from his pk
+ """
+ def get_nick(pk) do
+ pid = find_proc pk
+ info = GenServer.call(pid, :get_info)
+ info.nick
+ end
end
diff --git a/shard/lib/cli/cli.ex b/shard/lib/cli/cli.ex
index 85fa3fc..3b52fa5 100644
--- a/shard/lib/cli/cli.ex
+++ b/shard/lib/cli/cli.ex
@@ -113,18 +113,9 @@ defmodule SCLI do
end
defp handle_command(state, ["join", qchan]) do
- pid = SApp.Chat.find_proc qchan
- case pid do
- nil ->
- {:ok, pid} = Shard.Manifest.start %SApp.Chat.Manifest{channel: qchan}
- GenServer.cast(pid, {:subscribe, self()})
- IO.puts "Joining ##{qchan} (new shard)"
- %{state | room_pid: pid}
- pid ->
- GenServer.cast(pid, {:subscribe, self()})
- IO.puts "Switching to ##{qchan}"
- %{state | room_pid: pid}
- end
+ pid = Shard.Manager.find_or_start %SApp.Chat.Manifest{channel: qchan}
+ IO.puts "Switching to ##{qchan}"
+ %{state | room_pid: pid}
end
defp handle_command(state, ["pm" | people_list]) do
@@ -151,22 +142,12 @@ defmodule SCLI do
end
end
if Enum.all?(pk_list, &(&1 != :error)) do
- pk_list = [state.pk | pk_list]
- manifest = SApp.Chat.PrivChat.Manifest.new(pk_list)
- id = SData.term_hash manifest
- case Shard.Manager.find_proc id do
- nil ->
- {:ok, pid} = Shard.Manifest.start manifest
- GenServer.cast(pid, {:subscribe, self()})
- IO.puts "Joining private conversation (new shard)."
- %{state | room_pid: pid}
- pid ->
- GenServer.cast(pid, {:subscribe, self()})
- IO.puts "Switching to private conversation."
- %{state | room_pid: pid}
- end
+ manifest = SApp.Chat.PrivChat.Manifest.new([state.pk | pk_list])
+ pid = Shard.Manager.find_or_start manifest
+ IO.puts "Switching to private conversation."
+ %{state | room_pid: pid}
else
- state
+ state
end
end
diff --git a/shard/lib/manager.ex b/shard/lib/manager.ex
index 9def229..d6b493b 100644
--- a/shard/lib/manager.ex
+++ b/shard/lib/manager.ex
@@ -213,6 +213,22 @@ defmodule Shard.Manager do
end
@doc"""
+ Returns the pid for a shard defined by its manifest.
+ Start it if it doesn't exist.
+ """
+ def find_or_start(manifest) do
+ id = SData.term_hash manifest
+ case find_proc id do
+ nil ->
+ case Shard.Manifest.start manifest do
+ {:ok, pid} -> pid
+ {:error, :redundant} -> find_proc id
+ end
+ pid -> pid
+ end
+ end
+
+ @doc"""
Return the list of all shards.
"""
def list_shards() do
diff --git a/shardweb/lib/shard_web/channels/room_channel.ex b/shardweb/lib/shard_web/channels/room_channel.ex
index f582e06..7c3a16c 100644
--- a/shardweb/lib/shard_web/channels/room_channel.ex
+++ b/shardweb/lib/shard_web/channels/room_channel.ex
@@ -6,15 +6,7 @@ defmodule ShardWeb.RoomChannel do
def join("room:" <> room_name, payload, socket) do
if authorized?(payload) do
- list = for {_chid, %SApp.Chat.Manifest{channel: chan}, chpid} <- Shard.Manager.list_shards,
- do: {chan, chpid}
- pid = case List.keyfind(list, room_name, 0) do
- nil ->
- {:ok, pid} = Shard.Manifest.start %SApp.Chat.Manifest{channel: room_name}
- pid
- {_, pid} ->
- pid
- end
+ pid = Shard.Manager.find_or_start %SApp.Chat.Manifest{channel: room_name}
socket = assign(socket, :pid, pid)
GenServer.cast(pid, {:subscribe, self()})
@@ -68,8 +60,8 @@ defmodule ShardWeb.RoomChannel do
payload = Map.put(payload, "name", nick)
payload = Map.put(payload, "pk16", Shard.Keys.pk_display pk)
- broadcast socket, "shout", payload
GenServer.cast(socket.assigns.pid, {:chat_send, pk, payload["message"]})
+ broadcast socket, "shout", payload
{:noreply, socket}
end