Skip to content

Commit

Permalink
Fixes closing websocket.
Browse files Browse the repository at this point in the history
 * Added close/1 to the stream protocol so websocket can properly
   close the underlying stream.
 * Added an option to Socket.Web.close/3 to get the reason and
   custom data sent by the server.
  • Loading branch information
sylane committed Mar 11, 2015
1 parent 7a011f4 commit 257fa5c
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
18 changes: 18 additions & 0 deletions lib/socket/stream.ex
Expand Up @@ -43,6 +43,13 @@ defprotocol Socket.Stream.Protocol do
"""
@spec shutdown(t, :both | :read | :write) :: :ok | { :error, term }
def shutdown(self, how \\ :both)

@doc """
Close the socket.
"""
@spec close(t) :: :ok | {:error, term}
def close(self)

end

defmodule Socket.Stream do
Expand Down Expand Up @@ -71,6 +78,9 @@ defmodule Socket.Stream do
defdelegate shutdown(self, how), to: Socket.Stream.Protocol
defbang shutdown(self, how), to: Socket.Stream.Protocol

defdelegate close(self), to: Socket.Stream.Protocol
defbang close(self), to: Socket.Stream.Protocol

@doc """
Read from the IO device and send to the socket following the given options.
Expand Down Expand Up @@ -184,6 +194,10 @@ defimpl Socket.Stream.Protocol, for: Port do
:both -> :read_write
end)
end

def close(self) do
:gen_tcp.close(self)
end
end

defimpl Socket.Stream.Protocol, for: Tuple do
Expand Down Expand Up @@ -255,4 +269,8 @@ defimpl Socket.Stream.Protocol, for: Tuple do
:both -> :read_write
end)
end

def close(self) do
:ssl.close(self)
end
end
22 changes: 15 additions & 7 deletions lib/socket/web.ex
Expand Up @@ -839,8 +839,10 @@ defmodule Socket.Web do
Close the socket sending a close request, unless `:wait` is set to `false` it
blocks until the close response has been received, and then closes the
underlying socket.
If :reason? is set to true and the response contains a closing reason
and custom data the function returns it as a tuple.
"""
@spec close(t, atom, Keyword.t) :: :ok | { :error, error }
@spec close(t, atom, Keyword.t) :: :ok | {:ok, atom, binary} | { :error, error }
def close(%W{socket: socket, version: 13, mask: mask} = self, reason, options \\ []) do
if reason |> is_tuple do
{ reason, data } = reason
Expand All @@ -857,20 +859,25 @@ defmodule Socket.Web do
<< close_code(reason) :: 16, data :: binary >>) :: binary >>)

unless options[:wait] == false do
do_close(self, recv(self))
do_close(self, recv(self), Dict.get(options, :reason?, false))
end
end

defp do_close(self, { :ok, :close }) do
defp do_close(self, { :ok, :close }, _) do
abort(self)
end

defp do_close(self, { :ok, { :close, _, _ } }) do
defp do_close(self, { :ok, { :close, _, _ } }, false) do
abort(self)
end

defp do_close(self, _) do
do_close(self, recv(self))
defp do_close(self, { :ok, { :close, reason, data } }, true) do
abort(self)
{:ok, reason, data}
end

defp do_close(self, _, reason?) do
do_close(self, recv(self), reason?)
end

@doc """
Expand All @@ -879,6 +886,7 @@ defmodule Socket.Web do
"""
@spec abort(t) :: :ok | { :error, error }
def abort(%W{socket: socket}) do
close(socket)
Socket.Stream.close(socket)
end

end

0 comments on commit 257fa5c

Please sign in to comment.