allow subscribing to sessions
This commit is contained in:
parent
3671033f6d
commit
2f97c28add
|
@ -60,6 +60,10 @@ XferBlob ::= SEQUENCE {
|
||||||
data OCTET STRING
|
data OCTET STRING
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SessionModify ::= CHOICE {
|
||||||
|
attach [0] OCTET STRING
|
||||||
|
}
|
||||||
|
|
||||||
SummaryDirection ::= ENUMERATED {
|
SummaryDirection ::= ENUMERATED {
|
||||||
pull (0),
|
pull (0),
|
||||||
rejectpush (1),
|
rejectpush (1),
|
||||||
|
@ -72,8 +76,9 @@ Summary ::= SEQUENCE {
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtoMessage ::= CHOICE {
|
ProtoMessage ::= CHOICE {
|
||||||
summary [0] Summary,
|
session [0] SessionModify,
|
||||||
xfer [1] XferBlob
|
summary [1] Summary,
|
||||||
|
xfer [2] XferBlob
|
||||||
}
|
}
|
||||||
|
|
||||||
END
|
END
|
||||||
|
|
31
lib/floof.ex
31
lib/floof.ex
|
@ -31,8 +31,8 @@ defmodule Floof do
|
||||||
receive do
|
receive do
|
||||||
{:tcp, _, message} ->
|
{:tcp, _, message} ->
|
||||||
{:ok, dcd} = :FloofProtocol.decode(:ProtoMessage, message)
|
{:ok, dcd} = :FloofProtocol.decode(:ProtoMessage, message)
|
||||||
backlog2 = handle_incoming(client, backlog, dcd)
|
backlog = handle_incoming(client, backlog, dcd)
|
||||||
serve(client, backlog2)
|
serve(client, backlog)
|
||||||
{:fwdxfer, dcdmessage} ->
|
{:fwdxfer, dcdmessage} ->
|
||||||
dcdid = get_xfer_id dcdmessage
|
dcdid = get_xfer_id dcdmessage
|
||||||
handle_outgoing(client, dcdid)
|
handle_outgoing(client, dcdid)
|
||||||
|
@ -42,6 +42,14 @@ defmodule Floof do
|
||||||
{:ok, encd} = :FloofProtocol.encode(:ProtoMessage, {:summary, dat})
|
{:ok, encd} = :FloofProtocol.encode(:ProtoMessage, {:summary, dat})
|
||||||
:ok = client.send(encd)
|
:ok = client.send(encd)
|
||||||
serve(client, backlog)
|
serve(client, backlog)
|
||||||
|
{:SessionPushed, key} ->
|
||||||
|
{backlog, added_ids} = extract_backlog(key, backlog, [])
|
||||||
|
for id <- added_ids do
|
||||||
|
dat = {:Summary, :requestpull, id}
|
||||||
|
{:ok, encd} = :FloofProtocol.encode(:ProtoMessage, {:summary, dat})
|
||||||
|
:ok = client.send(encd)
|
||||||
|
end
|
||||||
|
serve(client, backlog)
|
||||||
x -> Logger.warn("unable to handle request: #{inspect(x)}")
|
x -> Logger.warn("unable to handle request: #{inspect(x)}")
|
||||||
serve(client, backlog)
|
serve(client, backlog)
|
||||||
end
|
end
|
||||||
|
@ -50,10 +58,17 @@ defmodule Floof do
|
||||||
defp handle_incoming(client, backlog, dcd) do
|
defp handle_incoming(client, backlog, dcd) do
|
||||||
Logger.debug("got packet #{inspect(dcd)}")
|
Logger.debug("got packet #{inspect(dcd)}")
|
||||||
case dcd do
|
case dcd do
|
||||||
|
{:session, {:SessionModify, {:attach, key}}} ->
|
||||||
|
if Floof.SessionManager.attach(key, self()) do
|
||||||
|
send self(), {:SessionPushed, key}
|
||||||
|
backlog
|
||||||
|
else
|
||||||
|
backlog
|
||||||
|
end
|
||||||
{:summary, {:Summary, direction, id}} ->
|
{:summary, {:Summary, direction, id}} ->
|
||||||
case direction do
|
case direction do
|
||||||
:requestpull ->
|
:requestpull ->
|
||||||
send(Floof.Distributor, {:havewe, self(), id})
|
send Floof.Distributor, {:havewe, self(), id}
|
||||||
backlog
|
backlog
|
||||||
:pull ->
|
:pull ->
|
||||||
case List.keytake(backlog, id, 0) do
|
case List.keytake(backlog, id, 0) do
|
||||||
|
@ -67,7 +82,7 @@ defmodule Floof do
|
||||||
List.keydelete(backlog, id, 0)
|
List.keydelete(backlog, id, 0)
|
||||||
end
|
end
|
||||||
{:xfer, xf} ->
|
{:xfer, xf} ->
|
||||||
send(Floof.Distributor, xf)
|
send Floof.Distributor, xf
|
||||||
backlog
|
backlog
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -82,4 +97,12 @@ defmodule Floof do
|
||||||
{:ok, {:XferInner, id, _, _, _, _}} = :FloofProtocol.decode(:XferInner, xfinner)
|
{:ok, {:XferInner, id, _, _, _, _}} = :FloofProtocol.decode(:XferInner, xfinner)
|
||||||
id
|
id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp extract_backlog(key, backlog, added_ids) do
|
||||||
|
case Floof.SessionManager.pop(key) do
|
||||||
|
:empty -> {backlog, added_ids}
|
||||||
|
{:value, {id, entry}} ->
|
||||||
|
extract_backlog(key, [{id, entry} | backlog], [id | added_ids])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,11 +5,23 @@ defmodule Floof.SessionManager do
|
||||||
Agent.start_link(fn -> initial_value end, name: __MODULE__)
|
Agent.start_link(fn -> initial_value end, name: __MODULE__)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def attach(key, pid) do
|
||||||
|
Agent.get_and_update(__MODULE__, fn state ->
|
||||||
|
Map.get_and_update(state, key, fn q ->
|
||||||
|
{_, q2} = entry_dfl(q)
|
||||||
|
{:queue.is_empty(q2), {pid, q2}}
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
def push(key, value) do
|
def push(key, value) do
|
||||||
Agent.cast(__MODULE__, fn state ->
|
Agent.cast(__MODULE__, fn state ->
|
||||||
{_, state2} = Map.get_and_update(state, key, fn q ->
|
{sub, state2} = Map.get_and_update(state, key, fn q ->
|
||||||
q2 = if q == nil do :queue.new() else q end
|
{sub, q2} = entry_dfl(q)
|
||||||
{nil, :queue.cons(value, q2)} end)
|
{sub, {sub, :queue.cons(value, q2)}} end)
|
||||||
|
if sub != nil do
|
||||||
|
send(sub, {:SessionPushed, key})
|
||||||
|
end
|
||||||
state2
|
state2
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
@ -17,7 +29,11 @@ defmodule Floof.SessionManager do
|
||||||
def pop(key) do
|
def pop(key) do
|
||||||
Agent.get_and_update(__MODULE__, fn state ->
|
Agent.get_and_update(__MODULE__, fn state ->
|
||||||
{tmp, state} = Map.get_and_update(state, key, fn q ->
|
{tmp, state} = Map.get_and_update(state, key, fn q ->
|
||||||
if q == nil do :pop else :queue.out_r(q) end
|
if q == nil do :pop else
|
||||||
|
{sub, q2} = q
|
||||||
|
{got, q3} = :queue.out_r(q2)
|
||||||
|
{got, {sub, q3}}
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
retval = case tmp do
|
retval = case tmp do
|
||||||
nil -> :empty
|
nil -> :empty
|
||||||
|
@ -26,4 +42,8 @@ defmodule Floof.SessionManager do
|
||||||
{retval, state}
|
{retval, state}
|
||||||
end, :infinity)
|
end, :infinity)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp entry_dfl(got) do
|
||||||
|
if got == nil do {nil, :queue.new()} else got end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue