Skip to content

Commit

Permalink
Allow errors in TCP.start_protocol/1 pipeline to be returned.
Browse files Browse the repository at this point in the history
When connecting many clients to an XMPP server quickly, closed streams
can occur. Let those errors through instead of blowing up due to
FunctionClauseError.

Fixes scrogson#27
  • Loading branch information
lmarlow committed Oct 13, 2017
1 parent 0ecef1e commit 01a3bc5
Showing 1 changed file with 14 additions and 2 deletions.
16 changes: 14 additions & 2 deletions lib/romeo/transports/tcp.ex
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,14 @@ defmodule Romeo.Transports.TCP do
end)
end

defp negotiate_features({:error, _} = error), do: error
defp negotiate_features(%Conn{} = conn) do
recv(conn, fn conn, xmlel(name: "stream:features") = packet ->
%{conn | features: Features.parse_stream_features(packet)}
end)
end

defp maybe_start_tls({:error, _} = error), do: error
defp maybe_start_tls(%Conn{features: %Features{tls?: true}} = conn) do
conn
|> send(Stanza.start_tls)
Expand All @@ -93,6 +95,7 @@ defmodule Romeo.Transports.TCP do
end
defp maybe_start_tls(%Conn{} = conn), do: conn

defp upgrade_to_tls({:error, _} = error), do: error
defp upgrade_to_tls(%Conn{parser: parser, socket: {:gen_tcp, socket}} = conn) do
Logger.info fn -> "Negotiating secure connection" end

Expand All @@ -103,6 +106,7 @@ defmodule Romeo.Transports.TCP do
%{conn | socket: {:ssl, socket}, parser: parser}
end

defp authenticate({:error, _} = error), do: error
defp authenticate(%Conn{} = conn) do
conn
|> Romeo.Auth.authenticate!
Expand All @@ -111,10 +115,12 @@ defmodule Romeo.Transports.TCP do
|> negotiate_features
end

defp handshake({:error, _} = error), do: error
defp handshake(%Conn{} = conn) do
Romeo.Auth.handshake!(conn)
end

defp bind({:error, _} = error), do: error
defp bind(%Conn{owner: owner, resource: resource} = conn) do
stanza = Romeo.Stanza.bind(resource)
id = Romeo.XML.attr(stanza, "id")
Expand All @@ -138,6 +144,7 @@ defmodule Romeo.Transports.TCP do
end)
end

defp session({:error, _} = error), do: error
defp session(%Conn{} = conn) do
stanza = Romeo.Stanza.session
id = Romeo.XML.attr(stanza, "id")
Expand All @@ -153,11 +160,13 @@ defmodule Romeo.Transports.TCP do
end)
end

defp ready({:error, _} = error), do: error
defp ready(%Conn{owner: owner} = conn) do
Kernel.send(owner, :connection_ready)
{:ok, conn}
end

defp reset_parser({:error, _} = error), do: error
defp reset_parser(%Conn{parser: parser} = conn) do
parser = :fxml_stream.reset(parser)
%{conn | parser: parser}
Expand Down Expand Up @@ -193,11 +202,14 @@ defmodule Romeo.Transports.TCP do
def send(%Conn{jid: jid, socket: {mod, socket}} = conn, stanza) do
stanza = Romeo.XML.encode!(stanza)
Logger.debug fn -> "[#{jid}][OUTGOING] #{inspect stanza}" end
:ok = mod.send(socket, stanza)
{:ok, conn}
case mod.send(socket, stanza) do
:ok -> {:ok, conn}
{:error, _} = error -> error
end
end

def recv({:ok, conn}, fun), do: recv(conn, fun)
def recv({:error, _} = error, _fun), do: error
def recv(%Conn{socket: {:gen_tcp, socket}, timeout: timeout} = conn, fun) do
receive do
{:xmlstreamelement, stanza} ->
Expand Down

0 comments on commit 01a3bc5

Please sign in to comment.