Keep pre-rebrand discovery installs compatible
This commit is contained in:
parent
de454ff48a
commit
ee3982e428
8 changed files with 154 additions and 16 deletions
|
|
@ -90,6 +90,12 @@ release. The versioned HTTP contract remains independent from straywild's save s
|
|||
network protocol. Each tagged deployment accepts room advertisements only from its matching game
|
||||
release so incompatible rooms are never presented as publicly available.
|
||||
|
||||
Existing NETfishing installations can be upgraded in place. The legacy
|
||||
`netfishing_discovery` module, command name, and `NETFISHING_DISCOVERY_*`
|
||||
environment variables remain accepted, while new installations should use the
|
||||
Straywild names shown above. When both forms of an environment setting exist,
|
||||
the Straywild value takes precedence.
|
||||
|
||||
## Licensing
|
||||
|
||||
Project-owned source code is licensed under the GNU General Public License,
|
||||
|
|
|
|||
5
netfishing_discovery/__init__.py
Normal file
5
netfishing_discovery/__init__.py
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
"""Compatibility package for pre-Straywild discovery installations."""
|
||||
|
||||
from straywild_discovery import __version__
|
||||
|
||||
__all__ = ["__version__"]
|
||||
7
netfishing_discovery/__main__.py
Normal file
7
netfishing_discovery/__main__.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
"""Run the Straywild discovery service through its legacy module name."""
|
||||
|
||||
from straywild_discovery.server import main
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -15,6 +15,7 @@ classifiers = [
|
|||
|
||||
[project.scripts]
|
||||
straywild-discovery-server = "straywild_discovery.server:main"
|
||||
netfishing-discovery-server = "straywild_discovery.server:main"
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
include = ["straywild_discovery*"]
|
||||
include = ["straywild_discovery*", "netfishing_discovery*"]
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@ TRAVERSAL_PACKET_PREFIX = b"straywild_TRAVERSAL_V1 "
|
|||
MAX_TRAVERSAL_PACKET_BYTES = 2048
|
||||
|
||||
|
||||
def _environment(primary: str, legacy: str, default: str) -> str:
|
||||
"""Read the Straywild setting first, then its NETfishing predecessor."""
|
||||
if primary in os.environ:
|
||||
return os.environ[primary]
|
||||
return os.getenv(legacy, default)
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class ServerConfig:
|
||||
bind_host: str = "127.0.0.1"
|
||||
|
|
@ -53,39 +60,72 @@ class ServerConfig:
|
|||
@classmethod
|
||||
def from_environment(cls) -> "ServerConfig":
|
||||
proxy_cidrs: list[ipaddress.IPv4Network | ipaddress.IPv6Network] = []
|
||||
raw_cidrs = os.getenv("straywild_DISCOVERY_TRUSTED_PROXY_CIDRS", "")
|
||||
raw_cidrs = _environment(
|
||||
"straywild_DISCOVERY_TRUSTED_PROXY_CIDRS",
|
||||
"NETFISHING_DISCOVERY_TRUSTED_PROXY_CIDRS",
|
||||
"",
|
||||
)
|
||||
for value in raw_cidrs.split(","):
|
||||
value = value.strip()
|
||||
if value:
|
||||
proxy_cidrs.append(ipaddress.ip_network(value, strict=False))
|
||||
return cls(
|
||||
bind_host=os.getenv("straywild_DISCOVERY_HOST", "127.0.0.1"),
|
||||
bind_port=int(os.getenv("straywild_DISCOVERY_PORT", "7770")),
|
||||
room_ttl_seconds=float(os.getenv("straywild_DISCOVERY_ROOM_TTL", "45")),
|
||||
bind_host=_environment(
|
||||
"straywild_DISCOVERY_HOST", "NETFISHING_DISCOVERY_HOST", "127.0.0.1"
|
||||
),
|
||||
bind_port=int(_environment(
|
||||
"straywild_DISCOVERY_PORT", "NETFISHING_DISCOVERY_PORT", "7770"
|
||||
)),
|
||||
room_ttl_seconds=float(_environment(
|
||||
"straywild_DISCOVERY_ROOM_TTL",
|
||||
"NETFISHING_DISCOVERY_ROOM_TTL",
|
||||
"45",
|
||||
)),
|
||||
max_rooms=int(
|
||||
os.getenv("straywild_DISCOVERY_MAX_ROOMS", str(DEFAULT_MAX_ROOMS))
|
||||
_environment(
|
||||
"straywild_DISCOVERY_MAX_ROOMS",
|
||||
"NETFISHING_DISCOVERY_MAX_ROOMS",
|
||||
str(DEFAULT_MAX_ROOMS),
|
||||
)
|
||||
),
|
||||
max_rooms_per_address=int(
|
||||
os.getenv(
|
||||
_environment(
|
||||
"straywild_DISCOVERY_MAX_ROOMS_PER_ADDRESS",
|
||||
"NETFISHING_DISCOVERY_MAX_ROOMS_PER_ADDRESS",
|
||||
str(DEFAULT_MAX_ROOMS_PER_ADDRESS),
|
||||
)
|
||||
),
|
||||
max_body_bytes=int(
|
||||
os.getenv("straywild_DISCOVERY_MAX_BODY_BYTES", str(DEFAULT_MAX_BODY_BYTES))
|
||||
_environment(
|
||||
"straywild_DISCOVERY_MAX_BODY_BYTES",
|
||||
"NETFISHING_DISCOVERY_MAX_BODY_BYTES",
|
||||
str(DEFAULT_MAX_BODY_BYTES),
|
||||
)
|
||||
),
|
||||
trusted_proxy_cidrs=tuple(proxy_cidrs),
|
||||
traversal_bind_host=os.getenv(
|
||||
"straywild_DISCOVERY_TRAVERSAL_HOST", "0.0.0.0"
|
||||
traversal_bind_host=_environment(
|
||||
"straywild_DISCOVERY_TRAVERSAL_HOST",
|
||||
"NETFISHING_DISCOVERY_TRAVERSAL_HOST",
|
||||
"0.0.0.0",
|
||||
),
|
||||
traversal_port=int(
|
||||
os.getenv("straywild_DISCOVERY_TRAVERSAL_PORT", "7771")
|
||||
_environment(
|
||||
"straywild_DISCOVERY_TRAVERSAL_PORT",
|
||||
"NETFISHING_DISCOVERY_TRAVERSAL_PORT",
|
||||
"7771",
|
||||
)
|
||||
),
|
||||
traversal_public_host=os.getenv(
|
||||
"straywild_DISCOVERY_TRAVERSAL_PUBLIC_HOST", "127.0.0.1"
|
||||
traversal_public_host=_environment(
|
||||
"straywild_DISCOVERY_TRAVERSAL_PUBLIC_HOST",
|
||||
"NETFISHING_DISCOVERY_TRAVERSAL_PUBLIC_HOST",
|
||||
"127.0.0.1",
|
||||
),
|
||||
build_revision=(
|
||||
os.getenv("straywild_DISCOVERY_BUILD_REVISION", "unknown").strip()
|
||||
_environment(
|
||||
"straywild_DISCOVERY_BUILD_REVISION",
|
||||
"NETFISHING_DISCOVERY_BUILD_REVISION",
|
||||
"unknown",
|
||||
).strip()
|
||||
or "unknown"
|
||||
)[:64],
|
||||
)
|
||||
|
|
@ -520,7 +560,14 @@ def _argument_parser() -> argparse.ArgumentParser:
|
|||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--host", help="bind address (overrides environment)")
|
||||
parser.add_argument("--port", type=int, help="bind port (overrides environment)")
|
||||
parser.add_argument("--log-level", default=os.getenv("straywild_DISCOVERY_LOG_LEVEL", "INFO"))
|
||||
parser.add_argument(
|
||||
"--log-level",
|
||||
default=_environment(
|
||||
"straywild_DISCOVERY_LOG_LEVEL",
|
||||
"NETFISHING_DISCOVERY_LOG_LEVEL",
|
||||
"INFO",
|
||||
),
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from .registry import RoomAdvertisement, RoomNotFoundError, RoomRegistry, Valida
|
|||
|
||||
|
||||
PRESENCE_DOMAIN = "straywild_PRESENCE_V1:"
|
||||
LEGACY_PRESENCE_DOMAIN = "NETFISHING_PRESENCE_V1:"
|
||||
INVITE_DOMAIN = "straywild_INVITE_V1:"
|
||||
SOCIAL_TOKEN_LENGTH = 64
|
||||
MAX_SOCIAL_CHANNELS_PER_REQUEST = 200
|
||||
|
|
@ -108,7 +109,14 @@ class SocialRegistry:
|
|||
online = payload.get("online")
|
||||
if not isinstance(online, bool):
|
||||
raise ValidationError("online must be a boolean")
|
||||
channels = [_capability_id(PRESENCE_DOMAIN, token) for token in write_tokens]
|
||||
channels = [
|
||||
channel
|
||||
for token in write_tokens
|
||||
for channel in (
|
||||
_capability_id(PRESENCE_DOMAIN, token),
|
||||
_capability_id(LEGACY_PRESENCE_DOMAIN, token),
|
||||
)
|
||||
]
|
||||
now = self._clock()
|
||||
with self._lock:
|
||||
self._purge_locked(now)
|
||||
|
|
|
|||
43
tests/test_server_config.py
Normal file
43
tests/test_server_config.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from straywild_discovery.server import ServerConfig
|
||||
|
||||
|
||||
class ServerConfigCompatibilityTests(unittest.TestCase):
|
||||
def test_legacy_environment_remains_accepted(self) -> None:
|
||||
with patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
"NETFISHING_DISCOVERY_HOST": "127.0.0.9",
|
||||
"NETFISHING_DISCOVERY_PORT": "7791",
|
||||
"NETFISHING_DISCOVERY_BUILD_REVISION": "legacy-config",
|
||||
},
|
||||
clear=True,
|
||||
):
|
||||
config = ServerConfig.from_environment()
|
||||
self.assertEqual(config.bind_host, "127.0.0.9")
|
||||
self.assertEqual(config.bind_port, 7791)
|
||||
self.assertEqual(config.build_revision, "legacy-config")
|
||||
|
||||
def test_straywild_environment_wins_over_legacy_names(self) -> None:
|
||||
with patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
"straywild_DISCOVERY_HOST": "127.0.0.8",
|
||||
"NETFISHING_DISCOVERY_HOST": "127.0.0.9",
|
||||
"straywild_DISCOVERY_PORT": "7792",
|
||||
"NETFISHING_DISCOVERY_PORT": "7791",
|
||||
},
|
||||
clear=True,
|
||||
):
|
||||
config = ServerConfig.from_environment()
|
||||
self.assertEqual(config.bind_host, "127.0.0.8")
|
||||
self.assertEqual(config.bind_port, 7792)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -77,6 +77,27 @@ class SocialRegistryTests(unittest.TestCase):
|
|||
[],
|
||||
)
|
||||
|
||||
def test_presence_keeps_pre_rebrand_friend_channels_reachable(self) -> None:
|
||||
write_token = "c" * 64
|
||||
legacy_channel = capability_id("NETFISHING_PRESENCE_V1:", write_token)
|
||||
channels = self.social.publish_presence(
|
||||
"203.0.113.10",
|
||||
{
|
||||
"write_tokens": [write_token],
|
||||
"online": True,
|
||||
"display_name": "Voyager",
|
||||
"room_id": self.room.room_id,
|
||||
"game_version": GAME_VERSION,
|
||||
"protocol_version": PROTOCOL_VERSION,
|
||||
},
|
||||
)
|
||||
self.assertIn(legacy_channel, channels)
|
||||
presence = self.social.query_presence(
|
||||
[legacy_channel], GAME_VERSION, PROTOCOL_VERSION, self.rooms
|
||||
)
|
||||
self.assertEqual(len(presence), 1)
|
||||
self.assertEqual(presence[0]["channel"], legacy_channel)
|
||||
|
||||
def test_invitation_requires_a_current_live_poll(self) -> None:
|
||||
inbox_token = "b" * 64
|
||||
with self.assertRaisesRegex(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue