From ca1bd3893c3cb3d6334d4d0948c1ab200657f670 Mon Sep 17 00:00:00 2001 From: Brutus5000 Date: Sun, 12 Nov 2023 22:28:20 +0100 Subject: [PATCH] Remove Coturn brokering (#982) --- README.md | 2 +- integration_tests/test_server.py | 14 ------- server/__init__.py | 4 +- server/config.py | 3 -- server/ice_servers/__init__.py | 3 -- server/ice_servers/coturn.py | 51 ------------------------ server/lobbyconnection.py | 14 ++----- tests/conftest.py | 21 ---------- tests/data/test_conf.yaml | 3 -- tests/integration_tests/test_server.py | 3 +- tests/unit_tests/test_ice.py | 35 ---------------- tests/unit_tests/test_lobbyconnection.py | 6 +-- 12 files changed, 9 insertions(+), 150 deletions(-) delete mode 100644 server/ice_servers/__init__.py delete mode 100644 server/ice_servers/coturn.py delete mode 100644 tests/unit_tests/test_ice.py diff --git a/README.md b/README.md index 2b1b97581..3ab5f9a05 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ SESSION: QString ##### ICE Servers -- `{command: ice_servers}`: Send ICE TURN/STUN servers - Returns: `{command: ice_servers, : , date_created: , ttl: }` +- (deprecated) `{command: ice_servers}`: Send ICE TURN/STUN servers - Returns: `{command: ice_servers, : , date_created: , ttl: }` #### Parties - `{command: invite_to_party, recipient_id: <...>}`: Invite this player to a party diff --git a/integration_tests/test_server.py b/integration_tests/test_server.py index a7d51db5a..ec94941ea 100644 --- a/integration_tests/test_server.py +++ b/integration_tests/test_server.py @@ -6,20 +6,6 @@ async def test_ping(client_factory): await client.read_until_command("pong", timeout=5) -async def test_ice_servers(client_factory): - client, _ = await client_factory.login("test") - - await client.send_command("ice_servers") - msg = await client.read_until_command("ice_servers") - - assert msg["ttl"] > 60 - assert msg["ice_servers"] - for server in msg["ice_servers"]: - assert server["urls"] - assert server["username"] - assert server["credential"] - - async def test_matchmaker_info(client_factory): client, _ = await client_factory.login("test") diff --git a/server/__init__.py b/server/__init__.py index 66fed5e0b..777cc64c2 100644 --- a/server/__init__.py +++ b/server/__init__.py @@ -59,8 +59,8 @@ using the Interactive Connectivity Establishment (ICE) protocol, using the lobby server as a medium of exchanging candidate addresses between clients. If clients require a relay in order to connect to eachother, they will -authenticate with a separate coturn server using credentials supplied by the -lobby server. +authenticate with a separate sturn or turn server using credentials supplied +by a separate API service. ## Achievements When a game ends, each client will report a summary of the game in the form of diff --git a/server/config.py b/server/config.py index 3b71211dc..ffa9ff93d 100644 --- a/server/config.py +++ b/server/config.py @@ -130,9 +130,6 @@ def __init__(self): self.MINORITY_BONUS = 1 self.MINORITY_BONUS_RATING_RANGE = 1250 - self.COTURN_HOSTS = [] - self.COTURN_KEYS = [] - self.GEO_IP_DATABASE_PATH = "GeoLite2-Country.mmdb" self.GEO_IP_DATABASE_URL = "https://download.maxmind.com/app/geoip_download" self.GEO_IP_LICENSE_KEY = "" diff --git a/server/ice_servers/__init__.py b/server/ice_servers/__init__.py deleted file mode 100644 index ee0470cc1..000000000 --- a/server/ice_servers/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -ICE server configuration -""" diff --git a/server/ice_servers/coturn.py b/server/ice_servers/coturn.py deleted file mode 100644 index a792ae1e1..000000000 --- a/server/ice_servers/coturn.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -Coturn static auth api - -Creates ice_server record with temporary credentials computed from coturn static-auth-secret - -http://stackoverflow.com/a/35767224 -""" - -import base64 -import hmac -import time -from hashlib import sha1 - - -class CoturnHMAC: - def __init__(self, coturn_hosts=[], coturn_keys=[]): - self.coturn_hosts = coturn_hosts - self.coturn_keys = coturn_keys - - def server_tokens(self, username="faf-user", ttl=None) -> list[dict[str]]: - if ttl is None: - ttl = 86400 # pragma: no cover - - servers = [] - - # See https://github.com/coturn/coturn/wiki/turnserver#turn-rest-api - # create hmac of coturn_key + timestamp:username - timestamp = int(time.time()) + ttl - token_name = f"{timestamp}:{username}" - - for coturn_host, coturn_key in zip( - self.coturn_hosts, self.coturn_keys - ): - secret = hmac.new( - coturn_key.encode(), - str(token_name).encode(), sha1 - ) - auth_token = base64.b64encode(secret.digest()).decode() - - servers.append({ - "urls": [ - f"turn:{coturn_host}?transport=tcp", - f"turn:{coturn_host}?transport=udp", - f"stun:{coturn_host}", - ], - "username": token_name, - "credential": auth_token, - "credentialType": "token", - }) - - return servers diff --git a/server/lobbyconnection.py b/server/lobbyconnection.py index 99db665b9..245ed204e 100644 --- a/server/lobbyconnection.py +++ b/server/lobbyconnection.py @@ -50,7 +50,6 @@ VisibilityState ) from .geoip_service import GeoIpService -from .ice_servers.coturn import CoturnHMAC from .ladder_service import LadderService from .oauth_service import OAuthService from .party_service import PartyService @@ -80,7 +79,6 @@ def __init__( self.geoip_service = geoip self.game_service = game_service self.player_service = players - self.coturn_generator = CoturnHMAC(config.COTURN_HOSTS, config.COTURN_KEYS) self.ladder_service = ladder_service self.party_service = party_service self.rating_service = rating_service @@ -1139,20 +1137,16 @@ async def command_modvault(self, message): else: raise ValueError("invalid type argument") + # DEPRECATED: ICE servers are handled outside of the lobby server. + # This message remains here for backwards compatibility, but the list + # of servers will always be empty. async def command_ice_servers(self, message): if not self.player: return - ttl = 86400 - ice_servers = self.coturn_generator.server_tokens( - username=self.player.id, - ttl=ttl - ) - await self.send({ "command": "ice_servers", - "ice_servers": ice_servers, - "ttl": ttl + "ice_servers": [], }) @player_idle("invite a player") diff --git a/tests/conftest.py b/tests/conftest.py index 85c42356c..8d550740e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,7 +10,6 @@ import gc import logging from contextlib import asynccontextmanager, contextmanager -from typing import Iterable from unittest import mock import hypothesis @@ -427,23 +426,3 @@ def oauth_service(): @pytest.fixture def game_stats_service(event_service, achievement_service): return GameStatsService(event_service, achievement_service) - - -@pytest.fixture -def coturn_hosts() -> Iterable[str]: - return ["a", "b", "c", "d"] - - -@pytest.fixture -def coturn_keys(coturn_hosts) -> Iterable[str]: - return [f"secret_{host}" for host in coturn_hosts] - - -@pytest.fixture -def coturn_credentials() -> Iterable[str]: - return [ - "mO/6NHZaG4fwCf7mVuaWNRS7Atw=", - "uSjJUafCX3fEQTGK3NI+mUe6UDo=", - "I5BcpufNrBb4JDj80KY/7VATNis=", - "4wYEgoPz2MHf35Fva8NWulI3vVU=" - ] diff --git a/tests/data/test_conf.yaml b/tests/data/test_conf.yaml index e498e44f8..261f3527c 100644 --- a/tests/data/test_conf.yaml +++ b/tests/data/test_conf.yaml @@ -27,9 +27,6 @@ NEWBIE_BASE_MEAN: 500 NEWBIE_MIN_GAMES: 10 TOP_PLAYER_MIN_RATING: 1600 -COTURN_HOSTS: [] -COTURN_KEYS: [] - GEO_IP_DATABASE_PATH: "GeoLite2-Country.mmdb" GEO_IP_DATABASE_URL: "https://download.maxmind.com/app/geoip_download" GEO_IP_LICENSE_KEY: "" diff --git a/tests/integration_tests/test_server.py b/tests/integration_tests/test_server.py index 160df9bc3..6c8f7ba01 100644 --- a/tests/integration_tests/test_server.py +++ b/tests/integration_tests/test_server.py @@ -764,8 +764,7 @@ async def test_ice_servers_empty(lobby_server): # By default the server config should not have any ice servers assert msg == { "command": "ice_servers", - "ice_servers": [], - "ttl": 86400 + "ice_servers": [] } diff --git a/tests/unit_tests/test_ice.py b/tests/unit_tests/test_ice.py deleted file mode 100644 index 1b4de0f5d..000000000 --- a/tests/unit_tests/test_ice.py +++ /dev/null @@ -1,35 +0,0 @@ -from unittest import mock - -import pytest - -from server.ice_servers.coturn import CoturnHMAC - - -@pytest.fixture -def coturn_hmac(coturn_hosts, coturn_keys): - return CoturnHMAC(coturn_hosts=coturn_hosts, coturn_keys=coturn_keys) - - -@mock.patch("time.time", mock.Mock(return_value=1000)) -def test_coturn_tokens(coturn_hmac, coturn_hosts, coturn_credentials): - servers = coturn_hmac.server_tokens(username="faf-test", ttl=123456) - comparison_list = [] - for coturn_host, coturn_cred in zip(coturn_hosts, coturn_credentials): - comparison_list.append( - {"host": coturn_host, "cred": coturn_cred} - ) - - for i in range(0, len(servers)): - server = servers[i] - host = comparison_list[i]["host"] - credential = comparison_list[i]["cred"] - assert server["credentialType"] == "token" - assert server["urls"] == \ - [ - f"turn:{host}?transport=tcp", - f"turn:{host}?transport=udp", - f"stun:{host}" - ] - - assert server["credential"] == credential - assert server["username"] == "124456:faf-test" diff --git a/tests/unit_tests/test_lobbyconnection.py b/tests/unit_tests/test_lobbyconnection.py index 7b545f107..3714dd75b 100644 --- a/tests/unit_tests/test_lobbyconnection.py +++ b/tests/unit_tests/test_lobbyconnection.py @@ -689,16 +689,12 @@ async def test_command_ice_servers( lobbyconnection: LobbyConnection, ): lobbyconnection.send = mock.AsyncMock() - lobbyconnection.coturn_generator.server_tokens = mock.Mock( - return_value=["coturn_tokens"] - ) await lobbyconnection.on_message_received({"command": "ice_servers"}) lobbyconnection.send.assert_called_once_with({ "command": "ice_servers", - "ice_servers": ["coturn_tokens"], - "ttl": 86400, + "ice_servers": [], })