Floof.serve should be always tail-recursive
This commit is contained in:
parent
e4d71e0b88
commit
8cf076bf5f
109
lib/floof.ex
109
lib/floof.ex
|
@ -17,9 +17,12 @@ defmodule Floof do
|
|||
] ++ opts
|
||||
)
|
||||
|
||||
Logger.info("Accepting connections on #{port}")
|
||||
loop_acceptor(socket)
|
||||
:ok = :gen_tcp.close(socket)
|
||||
try do
|
||||
Logger.info("Accepting connections on #{port}")
|
||||
loop_acceptor(socket)
|
||||
after
|
||||
:ok = :gen_tcp.close(socket)
|
||||
end
|
||||
end
|
||||
|
||||
defp loop_acceptor(socket) do
|
||||
|
@ -45,60 +48,70 @@ defmodule Floof do
|
|||
active: true
|
||||
)
|
||||
|
||||
Floof.Distributor.register(self())
|
||||
Logger.info("Established connection to #{inspect(host)}:#{port}")
|
||||
try do
|
||||
Floof.Distributor.register(self())
|
||||
Logger.info("Established connection to #{inspect(host)}:#{port}")
|
||||
|
||||
if sesskey != nil do
|
||||
{:ok, encd} = :FloofProtocol.encode(:ProtoMessage, {:session, {:attach, sesskey}})
|
||||
:ok = :gen_tcp.send(socket, encd)
|
||||
if sesskey != nil do
|
||||
{:ok, encd} = :FloofProtocol.encode(:ProtoMessage, {:session, {:attach, sesskey}})
|
||||
:ok = :gen_tcp.send(socket, encd)
|
||||
end
|
||||
|
||||
serve(socket, %{}, nil)
|
||||
after
|
||||
:ok = :gen_tcp.close(socket)
|
||||
end
|
||||
|
||||
serve(socket, %{}, nil)
|
||||
:ok = :gen_tcp.close(socket)
|
||||
end
|
||||
|
||||
defp serve(client, backlog, sesskey) do
|
||||
receive do
|
||||
{:tcp, _, message} ->
|
||||
message =
|
||||
if :erlang.is_binary(message) do
|
||||
message
|
||||
else
|
||||
:erlang.list_to_binary(message)
|
||||
{backlog, sesskey} =
|
||||
receive do
|
||||
{:tcp, _, message} ->
|
||||
message =
|
||||
if :erlang.is_binary(message) do
|
||||
message
|
||||
else
|
||||
:erlang.list_to_binary(message)
|
||||
end
|
||||
|
||||
{:ok, dcd} = :FloofProtocol.decode(:ProtoMessage, message)
|
||||
backlog = handle_incoming(client, backlog, sesskey, dcd)
|
||||
{backlog, sesskey}
|
||||
|
||||
{:fwdxfer, {dcdhash, dcd}} ->
|
||||
backlog =
|
||||
if sesskey != nil do
|
||||
# make sure that stuff gets handled uniformly
|
||||
Floof.SessionManager.set(sesskey, dcdhash, dcd)
|
||||
else
|
||||
:ok = send_summary(client, :requestpull, [dcdhash])
|
||||
Map.put(backlog, dcdhash, dcd)
|
||||
end
|
||||
|
||||
{backlog, sesskey}
|
||||
|
||||
{:SessionPushed, sesskey} ->
|
||||
:ok = send_summary(client, :requestpull, Floof.SessionManager.peek(sesskey))
|
||||
{backlog, sesskey}
|
||||
|
||||
{:SessionDetached, _} ->
|
||||
{backlog, nil}
|
||||
|
||||
{:tcp_closed, _} ->
|
||||
# put all the backlogged stuff back if possible
|
||||
if sesskey != nil do
|
||||
Floof.SessionManager.set_multi(sesskey, backlog)
|
||||
Floof.SessionManager.detach(sesskey, self())
|
||||
end
|
||||
|
||||
{:ok, dcd} = :FloofProtocol.decode(:ProtoMessage, message)
|
||||
backlog = handle_incoming(client, backlog, sesskey, dcd)
|
||||
serve(client, backlog, sesskey)
|
||||
:erlang.exit(:normal)
|
||||
|
||||
{:fwdxfer, {dcdhash, dcd}} ->
|
||||
if sesskey != nil do
|
||||
# make sure that stuff gets handled uniformly
|
||||
Floof.SessionManager.set(sesskey, dcdhash, dcd)
|
||||
serve(client, backlog, sesskey)
|
||||
else
|
||||
:ok = send_summary(client, :requestpull, [dcdhash])
|
||||
serve(client, Map.put(backlog, dcdhash, dcd), sesskey)
|
||||
end
|
||||
x ->
|
||||
Logger.warn("unable to handle request: #{inspect(x)}")
|
||||
{backlog, sesskey}
|
||||
end
|
||||
|
||||
{:SessionPushed, sesskey} ->
|
||||
:ok = send_summary(client, :requestpull, Floof.SessionManager.peek(sesskey))
|
||||
serve(client, backlog, sesskey)
|
||||
|
||||
{:SessionDetached, _} ->
|
||||
serve(client, backlog, nil)
|
||||
|
||||
{:tcp_closed, _} ->
|
||||
# put all the backlogged stuff back if possible
|
||||
if sesskey != nil do
|
||||
Floof.SessionManager.set_multi(sesskey, backlog)
|
||||
Floof.SessionManager.detach(sesskey, self())
|
||||
end
|
||||
|
||||
x ->
|
||||
Logger.warn("unable to handle request: #{inspect(x)}")
|
||||
serve(client, backlog, sesskey)
|
||||
end
|
||||
serve(client, backlog, sesskey)
|
||||
end
|
||||
|
||||
defp handle_incoming(client, backlog, sesskey, dcd) do
|
||||
|
|
Loading…
Reference in a new issue