Skip to content

Commit

Permalink
Handle SSL socket closings during the close_loop
Browse files Browse the repository at this point in the history
* Fixes Azolo#56
  • Loading branch information
Azolo committed Aug 31, 2018
1 parent 703ee8a commit b14fa10
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Fix `pong` frame not being a correct return type in spec
- Fix bare `ping` and `pong` frames in spec
- When neither grame doesn't have a payload
- Fix handling SSL socket closings during the `close_loop`

## 0.4.1
### Enhancements
Expand Down
2 changes: 1 addition & 1 deletion lib/websockex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ defmodule WebSockex do
:gen.reply(from, {:error, %WebSockex.NotConnectedError{connection_state: :closing}})
close_loop(reason, parent, debug, state)

{:tcp_closed, ^socket} ->
{close_mod, ^socket} when close_mod in [:tcp_closed, :ssl_closed] ->
new_conn = %{conn | socket: nil}
debug = Utils.sys_debug(debug, :closed, state)
purge_timer(timer_ref, :websockex_close_timeout)
Expand Down
28 changes: 28 additions & 0 deletions test/websockex_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule WebSockexTest do
end

@basic_server_frame <<1::1, 0::3, 1::4, 0::1, 5::7, "Hello"::utf8>>
@close_frame_with_error <<1::1, 0::3, 8::4, 0::1, 2::7, 1001::16>>

defmodule TestClient do
use WebSockex
Expand Down Expand Up @@ -1144,6 +1145,33 @@ defmodule WebSockexTest do
TestClient.catch_attr(context.pid, :disconnect, self())
end

test "can handle a ssl socket closing during the close loop", context do
# Close the original socket
WebSockex.cast(context.pid, :close)
assert_receive {:DOWN, _ref, :process, _, :normal}
assert_receive :normal_remote_closed
assert_receive :caught_disconnect

# Test HTTPS
{:ok, {server_ref, url}} = WebSockex.TestServer.start_https(self())
on_exit(fn -> WebSockex.TestServer.shutdown(server_ref) end)

{:ok, pid} = TestClient.start_link(url, %{})
Process.unlink(pid)
Process.monitor(pid)
TestClient.catch_attr(pid, :disconnect, self())

conn = TestClient.get_conn(pid)

# Ranch/Cowboy closes the tcp connection instead sending an :ssl close
# So we're going to fake closing just the `:ssl` connection
send(pid, {conn.transport, conn.socket, @close_frame_with_error})
send(pid, {:ssl_closed, conn.socket})

assert_receive {:DOWN, _ref, :process, ^pid, {:remote, 1001, ""}}
assert_receive {:caught_disconnect, 1001, ""}
end

test "is not invoked when there is an exception during runtime", context do
TestClient.set_attr(context.pid, :reconnect, true)
TestClient.catch_attr(context.pid, :terminate, self())
Expand Down

0 comments on commit b14fa10

Please sign in to comment.