diff --git a/lib/jellyfish_web/peer_socket.ex b/lib/jellyfish_web/peer_socket.ex index 3a48b91f..45da3768 100644 --- a/lib/jellyfish_web/peer_socket.ex +++ b/lib/jellyfish_web/peer_socket.ex @@ -51,18 +51,14 @@ defmodule JellyfishWeb.PeerSocket do {:reply, :ok, {:text, message}, state} else {:error, reason} -> - reason = - case reason do - :invalid -> :invalid_token - other -> other - end + reason = reason_to_string(reason) Logger.warn(""" Authentication failed, reason: #{reason}. Closing the connection. """) - {:stop, :closed, {1000, inspect(reason)}, state} + {:stop, :closed, {1000, reason}, state} end _other -> @@ -163,6 +159,14 @@ defmodule JellyfishWeb.PeerSocket do :ok end + defp reason_to_string(:invalid), do: "invalid token" + defp reason_to_string(:missing), do: "missing token" + defp reason_to_string(:expired), do: "expired token" + defp reason_to_string(:room_not_found), do: "room not found" + defp reason_to_string(:peer_not_found), do: "peer not found" + defp reason_to_string(:peer_already_connected), do: "peer already connected" + defp reason_to_string(other), do: "#{other}" + defp control_message(data) do %{ "type" => "controlMessage", diff --git a/lib/jellyfish_web/server_socket .ex b/lib/jellyfish_web/server_socket .ex index 514ff6d8..e7fb2eb0 100644 --- a/lib/jellyfish_web/server_socket .ex +++ b/lib/jellyfish_web/server_socket .ex @@ -88,7 +88,7 @@ defmodule JellyfishWeb.ServerSocket do control_message(%{type: "peerConnected", id: peer_id}) {:peer_disconnected, peer_id} -> - control_message(%{type: "peerDisonnected", id: peer_id}) + control_message(%{type: "peerDisconnected", id: peer_id}) {:room_crashed, room_id} -> control_message(%{type: "roomCrashed", id: room_id}) diff --git a/test/jellyfish_web/controllers/component_controller_test.exs b/test/jellyfish_web/controllers/component_controller_test.exs index 9c28186a..f47ac70e 100644 --- a/test/jellyfish_web/controllers/component_controller_test.exs +++ b/test/jellyfish_web/controllers/component_controller_test.exs @@ -10,12 +10,12 @@ defmodule JellyfishWeb.ComponentControllerTest do server_api_token = Application.fetch_env!(:jellyfish, :server_api_token) conn = put_req_header(conn, "authorization", "Bearer " <> server_api_token) - room_conn = post(conn, ~p"/room") - assert %{"id" => id} = json_response(room_conn, :created)["data"] + conn = post(conn, ~p"/room") + assert %{"id" => id} = json_response(conn, :created)["data"] on_exit(fn -> - room_conn = delete(conn, ~p"/room/#{id}") - assert response(room_conn, :no_content) + conn = delete(conn, ~p"/room/#{id}") + assert response(conn, :no_content) end) {:ok, %{conn: put_req_header(conn, "accept", "application/json"), room_id: id}} diff --git a/test/jellyfish_web/controllers/peer_controller_test.exs b/test/jellyfish_web/controllers/peer_controller_test.exs index 48dd832c..adb349aa 100644 --- a/test/jellyfish_web/controllers/peer_controller_test.exs +++ b/test/jellyfish_web/controllers/peer_controller_test.exs @@ -10,12 +10,12 @@ defmodule JellyfishWeb.PeerControllerTest do server_api_token = Application.fetch_env!(:jellyfish, :server_api_token) conn = put_req_header(conn, "authorization", "Bearer " <> server_api_token) - room_conn = post(conn, ~p"/room", maxPeers: 1) - assert %{"id" => id} = json_response(room_conn, :created)["data"] + conn = post(conn, ~p"/room", maxPeers: 1) + assert %{"id" => id} = json_response(conn, :created)["data"] on_exit(fn -> - room_conn = delete(conn, ~p"/room/#{id}") - assert response(room_conn, :no_content) + conn = delete(conn, ~p"/room/#{id}") + assert response(conn, :no_content) end) {:ok, %{conn: put_req_header(conn, "accept", "application/json"), room_id: id}} diff --git a/test/jellyfish_web/integration/peer_socket_test.exs b/test/jellyfish_web/integration/peer_socket_test.exs index e257dfdb..82380360 100644 --- a/test/jellyfish_web/integration/peer_socket_test.exs +++ b/test/jellyfish_web/integration/peer_socket_test.exs @@ -7,6 +7,12 @@ defmodule JellyfishWeb.Integration.PeerSocketTest do @port 5908 @path "ws://127.0.0.1:#{@port}/socket/peer/websocket" + @auth_response %{ + "type" => "controlMessage", + "data" => %{ + "type" => "authenticated" + } + } Application.put_env( :jellyfish, @@ -35,8 +41,8 @@ defmodule JellyfishWeb.Integration.PeerSocketTest do server_api_token = Application.fetch_env!(:jellyfish, :server_api_token) conn = put_req_header(conn, "authorization", "Bearer " <> server_api_token) - room_conn = post(conn, ~p"/room", maxPeers: 1) - assert %{"id" => room_id} = json_response(room_conn, :created)["data"] + conn = post(conn, ~p"/room", maxPeers: 1) + assert %{"id" => room_id} = json_response(conn, :created)["data"] {:ok, _room_pid} = RoomService.find_room(room_id) conn = post(conn, ~p"/room/#{room_id}/peer", type: "webrtc") @@ -62,7 +68,7 @@ defmodule JellyfishWeb.Integration.PeerSocketTest do :ok = WS.send_frame(ws, auth_request) - assert_receive {:disconnected, {:remote, 1000, ":invalid_token"}}, 1000 + assert_receive {:disconnected, {:remote, 1000, "invalid token"}}, 1000 end test "correct token", %{token: token} do @@ -72,13 +78,7 @@ defmodule JellyfishWeb.Integration.PeerSocketTest do :ok = WS.send_frame(ws, auth_request) - assert_receive %{ - "type" => "controlMessage", - "data" => %{ - "type" => "authenticated" - } - }, - 1000 + assert_receive @auth_response, 1000 end test "valid token but peer doesn't exist", %{room_id: room_id} do @@ -89,17 +89,7 @@ defmodule JellyfishWeb.Integration.PeerSocketTest do :ok = WS.send_frame(ws, auth_request) - assert_receive {:disconnected, {:remote, 1000, ":peer_not_found"}}, 1000 - end - - defp auth_request(token) do - %{ - type: "controlMessage", - data: %{ - type: "authRequest", - token: token - } - } + assert_receive {:disconnected, {:remote, 1000, "peer not found"}}, 1000 end test "message from unauthenticated peer" do @@ -111,4 +101,14 @@ defmodule JellyfishWeb.Integration.PeerSocketTest do assert_receive {:disconnected, {:remote, 1000, "unauthenticated"}}, 1000 end + + defp auth_request(token) do + %{ + type: "controlMessage", + data: %{ + type: "authRequest", + token: token + } + } + end end diff --git a/test/jellyfish_web/integration/server_socket_test.exs b/test/jellyfish_web/integration/server_socket_test.exs index 8c18db43..70289496 100644 --- a/test/jellyfish_web/integration/server_socket_test.exs +++ b/test/jellyfish_web/integration/server_socket_test.exs @@ -1,11 +1,17 @@ defmodule JellyfishWeb.Integration.ServerSocketTest do - use ExUnit.Case + use JellyfishWeb.ConnCase alias __MODULE__.Endpoint - alias JellyfishWeb.{ServerSocket, WS} + alias JellyfishWeb.{PeerSocket, ServerSocket, WS} @port 5907 @path "ws://127.0.0.1:#{@port}/socket/server/websocket" + @auth_response %{ + "type" => "controlMessage", + "data" => %{ + "type" => "authenticated" + } + } Application.put_env( :jellyfish, @@ -23,6 +29,10 @@ defmodule JellyfishWeb.Integration.ServerSocketTest do socket "/socket/server", ServerSocket, websocket: true, longpoll: false + + socket "/socket/peer", PeerSocket, + websocket: true, + longpoll: false end setup_all do @@ -32,8 +42,8 @@ defmodule JellyfishWeb.Integration.ServerSocketTest do test "invalid token" do {:ok, ws} = WS.start_link(@path) - token = "invalid" <> Application.fetch_env!(:jellyfish, :server_api_token) - auth_request = auth_request(token) + server_api_token = "invalid" <> Application.fetch_env!(:jellyfish, :server_api_token) + auth_request = auth_request(server_api_token) :ok = WS.send_frame(ws, auth_request) assert_receive {:disconnected, {:remote, 1000, "invalid token"}}, 1000 @@ -42,7 +52,7 @@ defmodule JellyfishWeb.Integration.ServerSocketTest do test "missing token" do {:ok, ws} = WS.start_link(@path) - {_token, auth_request} = + {_server_api_token, auth_request} = Application.fetch_env!(:jellyfish, :server_api_token) |> auth_request() |> pop_in([:data, :token]) @@ -53,18 +63,17 @@ defmodule JellyfishWeb.Integration.ServerSocketTest do test "correct token" do {:ok, ws} = WS.start_link(@path) - token = Application.fetch_env!(:jellyfish, :server_api_token) - auth_request = auth_request(token) + server_api_token = Application.fetch_env!(:jellyfish, :server_api_token) + auth_request = auth_request(server_api_token) :ok = WS.send_frame(ws, auth_request) - assert_receive msg, 1000 - assert msg == auth_response() + assert_receive @auth_response, 1000 end test "closes on receiving a message from a client" do {:ok, ws} = WS.start_link(@path) - token = Application.fetch_env!(:jellyfish, :server_api_token) - auth_request = auth_request(token) + server_api_token = Application.fetch_env!(:jellyfish, :server_api_token) + auth_request = auth_request(server_api_token) :ok = WS.send_frame(ws, auth_request) @@ -73,6 +82,64 @@ defmodule JellyfishWeb.Integration.ServerSocketTest do assert_receive {:disconnected, {:remote, 1003, "operation not allowed"}}, 1000 end + test "sends a message when room crashes", %{conn: conn} do + {:ok, ws} = WS.start_link(@path) + server_api_token = Application.fetch_env!(:jellyfish, :server_api_token) + auth_request = auth_request(server_api_token) + + :ok = WS.send_frame(ws, auth_request) + + conn = put_req_header(conn, "authorization", "Bearer " <> server_api_token) + + conn = post(conn, ~p"/room", maxPeers: 1) + assert %{"id" => room_id} = json_response(conn, :created)["data"] + {:ok, room_pid} = Jellyfish.RoomService.find_room(room_id) + + Process.exit(room_pid, :kill) + + assert_receive %{ + "data" => %{"id" => ^room_id, "type" => "roomCrashed"}, + "type" => "controlMessage" + } + end + + test "sends a message when peer connects", %{conn: conn} do + {:ok, ws} = WS.start_link(@path) + server_api_token = Application.fetch_env!(:jellyfish, :server_api_token) + auth_request = auth_request(server_api_token) + + :ok = WS.send_frame(ws, auth_request) + + conn = put_req_header(conn, "authorization", "Bearer " <> server_api_token) + + conn = post(conn, ~p"/room", maxPeers: 1) + assert %{"id" => room_id} = json_response(conn, :created)["data"] + + conn = post(conn, ~p"/room/#{room_id}/peer", type: "webrtc") + + assert %{"token" => peer_token, "peer" => %{"id" => peer_id}} = + json_response(conn, :created)["data"] + + {:ok, peer_ws} = WS.start_link("ws://127.0.0.1:#{@port}/socket/peer/websocket") + + auth_request = auth_request(peer_token) + + :ok = WS.send_frame(peer_ws, auth_request) + + assert_receive %{ + "data" => %{"id" => ^peer_id, "type" => "peerConnected"}, + "type" => "controlMessage" + } + + conn = delete(conn, ~p"/room/#{room_id}/") + response(conn, :no_content) + + assert_receive %{ + "data" => %{"id" => ^peer_id, "type" => "peerDisconnected"}, + "type" => "controlMessage" + } + end + defp auth_request(token) do %{ type: "controlMessage", @@ -82,13 +149,4 @@ defmodule JellyfishWeb.Integration.ServerSocketTest do } } end - - defp auth_response() do - %{ - "type" => "controlMessage", - "data" => %{ - "type" => "authenticated" - } - } - end end diff --git a/test/jellyfish_web/peer_socket_test.exs b/test/jellyfish_web/peer_socket_test.exs index 2268e5e1..92de9b8b 100644 --- a/test/jellyfish_web/peer_socket_test.exs +++ b/test/jellyfish_web/peer_socket_test.exs @@ -12,8 +12,8 @@ defmodule JellyfishWeb.PeerSocketTest do server_api_token = Application.fetch_env!(:jellyfish, :server_api_token) conn = put_req_header(conn, "authorization", "Bearer " <> server_api_token) - room_conn = post(conn, ~p"/room", maxPeers: 1) - assert %{"id" => room_id} = json_response(room_conn, :created)["data"] + conn = post(conn, ~p"/room", maxPeers: 1) + assert %{"id" => room_id} = json_response(conn, :created)["data"] {:ok, _room_pid} = RoomService.find_room(room_id) conn = post(conn, ~p"/room/#{room_id}/peer", type: "webrtc")