pokken: Switch to using external STUN server

This commit is contained in:
Hay1tsme 2023-06-25 01:09:23 -04:00
parent ec9ad1ebb0
commit 514f786e2d
5 changed files with 97 additions and 86 deletions

View File

@ -2,8 +2,11 @@ server:
hostname: "localhost"
enable: True
loglevel: "info"
port: 9000
port_stun: 9001
port_turn: 9002
port_admission: 9003
auto_register: True
enable_matching: False
stun_server_host: "stunserver.stunprotocol.org"
stun_server_port: 3478
ports:
game: 9000
admission: 9001

View File

@ -44,19 +44,19 @@ class PokkenBase:
biwa_setting = {
"MatchingServer": {
"host": f"https://{self.game_cfg.server.hostname}",
"port": self.game_cfg.server.port,
"port": self.game_cfg.ports.game,
"url": "/SDAK/100/matching",
},
"StunServer": {
"addr": self.game_cfg.server.hostname,
"port": self.game_cfg.server.port_stun,
"addr": self.game_cfg.server.stun_server_host,
"port": self.game_cfg.server.stun_server_port,
},
"TurnServer": {
"addr": self.game_cfg.server.hostname,
"port": self.game_cfg.server.port_turn,
"addr": self.game_cfg.server.stun_server_host,
"port": self.game_cfg.server.stun_server_port,
},
"AdmissionUrl": f"ws://{self.game_cfg.server.hostname}:{self.game_cfg.server.port_admission}",
"locationId": 123,
"AdmissionUrl": f"ws://{self.game_cfg.server.hostname}:{self.game_cfg.ports.admission}",
"locationId": 123, # FIXME: Get arcade's ID from the database
"logfilename": "JackalMatchingLibrary.log",
"biwalogfilename": "./biwa.log",
}
@ -94,6 +94,7 @@ class PokkenBase:
res.type = jackal_pb2.MessageType.LOAD_CLIENT_SETTINGS
settings = jackal_pb2.LoadClientSettingsResponseData()
# TODO: Make configurable
settings.money_magnification = 1
settings.continue_bonus_exp = 100
settings.continue_fight_money = 100
@ -356,12 +357,11 @@ class PokkenBase:
self, data: Dict = {}, client_ip: str = "127.0.0.1"
) -> Dict:
"""
"sessionId":"12345678",
"A":{
"pcb_id": data["data"]["must"]["pcb_id"],
"gip": client_ip
},
"list":[]
"sessionId":"12345678",
"A":{
"pcb_id": data["data"]["must"]["pcb_id"],
"gip": client_ip
},
"""
return {
"data": {
@ -379,10 +379,13 @@ class PokkenBase:
) -> Dict:
return {}
def handle_admission_noop(self, data: Dict, req_ip: str = "127.0.0.1") -> Dict:
return {}
def handle_admission_joinsession(self, data: Dict, req_ip: str = "127.0.0.1") -> Dict:
self.logger.info(f"Admission: JoinSession from {req_ip}")
return {
'data': {
"id": 123
"id": 12345678
}
}

View File

@ -25,30 +25,6 @@ class PokkenServerConfig:
)
)
@property
def port(self) -> int:
return CoreConfig.get_config_field(
self.__config, "pokken", "server", "port", default=9000
)
@property
def port_stun(self) -> int:
return CoreConfig.get_config_field(
self.__config, "pokken", "server", "port_stun", default=9001
)
@property
def port_turn(self) -> int:
return CoreConfig.get_config_field(
self.__config, "pokken", "server", "port_turn", default=9002
)
@property
def port_admission(self) -> int:
return CoreConfig.get_config_field(
self.__config, "pokken", "server", "port_admission", default=9003
)
@property
def auto_register(self) -> bool:
"""
@ -59,7 +35,51 @@ class PokkenServerConfig:
self.__config, "pokken", "server", "auto_register", default=True
)
@property
def enable_matching(self) -> bool:
"""
If global matching should happen
"""
return CoreConfig.get_config_field(
self.__config, "pokken", "server", "enable_matching", default=False
)
@property
def stun_server_host(self) -> str:
"""
Hostname of the EXTERNAL stun server the game should connect to. This is not handled by artemis.
"""
return CoreConfig.get_config_field(
self.__config, "pokken", "server", "stun_server_host", default="stunserver.stunprotocol.org"
)
@property
def stun_server_port(self) -> int:
"""
Port of the EXTERNAL stun server the game should connect to. This is not handled by artemis.
"""
return CoreConfig.get_config_field(
self.__config, "pokken", "server", "stun_server_port", default=3478
)
class PokkenPortsConfig:
def __init__(self, parent_config: "PokkenConfig"):
self.__config = parent_config
@property
def game(self) -> int:
return CoreConfig.get_config_field(
self.__config, "pokken", "ports", "game", default=9000
)
@property
def admission(self) -> int:
return CoreConfig.get_config_field(
self.__config, "pokken", "ports", "admission", default=9001
)
class PokkenConfig(dict):
def __init__(self) -> None:
self.server = PokkenServerConfig(self)
self.ports = PokkenPortsConfig(self)

View File

@ -1,8 +1,7 @@
from typing import Tuple
from twisted.web.http import Request
from twisted.web import resource
from twisted.internet import reactor, endpoints
from autobahn.twisted.websocket import WebSocketServerFactory
from twisted.internet import reactor
import json, ast
from datetime import datetime
import yaml
@ -17,7 +16,7 @@ from .config import PokkenConfig
from .base import PokkenBase
from .const import PokkenConstants
from .proto import jackal_pb2
from .services import PokkenStunProtocol, PokkenAdmissionFactory, PokkenAdmissionProtocol
from .services import PokkenAdmissionFactory
class PokkenServlet(resource.Resource):
@ -72,7 +71,7 @@ class PokkenServlet(resource.Resource):
return (
True,
f"https://{game_cfg.server.hostname}:{game_cfg.server.port}/{game_code}/$v/",
f"https://{game_cfg.server.hostname}:{game_cfg.ports.game}/{game_code}/$v/",
f"{game_cfg.server.hostname}/SDAK/$v/",
)
@ -93,21 +92,10 @@ class PokkenServlet(resource.Resource):
return (True, "PKF1")
def setup(self) -> None:
# TODO: Setup stun, turn (UDP) and admission (WSS) servers
reactor.listenUDP(
self.game_cfg.server.port_stun, PokkenStunProtocol(self.core_cfg, self.game_cfg, "Stun")
)
reactor.listenUDP(
self.game_cfg.server.port_turn, PokkenStunProtocol(self.core_cfg, self.game_cfg, "Turn")
)
factory = WebSocketServerFactory(f"ws://{self.game_cfg.server.hostname}:{self.game_cfg.server.port_admission}")
factory.protocol = PokkenAdmissionProtocol
reactor.listenTCP(
self.game_cfg.server.port_admission, PokkenAdmissionFactory(self.core_cfg, self.game_cfg)
)
if self.game_cfg.server.enable_matching:
reactor.listenTCP(
self.game_cfg.ports.admission, PokkenAdmissionFactory(self.core_cfg, self.game_cfg)
)
def render_POST(
self, request: Request, version: int = 0, endpoints: str = ""
@ -144,6 +132,9 @@ class PokkenServlet(resource.Resource):
return ret
def handle_matching(self, request: Request) -> bytes:
if not self.game_cfg.server.enable_matching:
return b""
content = request.content.getvalue()
client_ip = Utils.get_ip_addr(request)

View File

@ -1,8 +1,8 @@
from twisted.internet.interfaces import IAddress
from twisted.internet.protocol import DatagramProtocol
from twisted.internet.protocol import Protocol
from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory
from datetime import datetime
from autobahn.websocket.types import ConnectionRequest
from typing import Dict
import logging
import json
@ -10,21 +10,6 @@ from core.config import CoreConfig
from .config import PokkenConfig
from .base import PokkenBase
class PokkenStunProtocol(DatagramProtocol):
def __init__(self, cfg: CoreConfig, game_cfg: PokkenConfig, type: str) -> None:
super().__init__()
self.core_config = cfg
self.game_config = game_cfg
self.logger = logging.getLogger("pokken")
self.server_type = type
def datagramReceived(self, data, addr):
self.logger.debug(
f"{self.server_type} from from {addr[0]}:{addr[1]} -> {self.transport.getHost().port} - {data.hex()}"
)
self.transport.write(data, addr)
# 474554202f20485454502f312e310d0a436f6e6e656374696f6e3a20557067726164650d0a486f73743a207469746c65732e6861793174732e6d653a393030330d0a5365632d576562536f636b65742d4b65793a204f4a6b6d522f376b646d6953326573483548783776413d3d0d0a5365632d576562536f636b65742d56657273696f6e3a2031330d0a557067726164653a20776562736f636b65740d0a557365722d4167656e743a20576562536f636b65742b2b2f302e332e300d0a0d0a
class PokkenAdmissionProtocol(WebSocketServerProtocol):
def __init__(self, cfg: CoreConfig, game_cfg: PokkenConfig):
super().__init__()
@ -34,26 +19,35 @@ class PokkenAdmissionProtocol(WebSocketServerProtocol):
self.base = PokkenBase(cfg, game_cfg)
def onMessage(self, payload, isBinary: bool) -> None:
msg = json.loads(payload)
self.logger.debug(f"WebSocket from from {self.transport.getPeer().host}:{self.transport.getPeer().port} -> {self.transport.getHost().port} - {msg}")
def onConnect(self, request: ConnectionRequest) -> None:
self.logger.debug(f"Admission: Connection from {request.peer}")
handler = getattr(self.base, f"handle_admission_{msg['api'].lower()}")
def onClose(self, wasClean: bool, code: int, reason: str) -> None:
self.logger.debug(f"Admission: Connection with {self.transport.getPeer().host} closed {'cleanly ' if wasClean else ''}with code {code} - {reason}")
def onMessage(self, payload, isBinary: bool) -> None:
msg: Dict = json.loads(payload)
self.logger.debug(f"Admission: Message from {self.transport.getPeer().host}:{self.transport.getPeer().port} - {msg}")
api = msg.get("api", "noop")
handler = getattr(self.base, f"handle_admission_{api.lower()}")
resp = handler(msg, self.transport.getPeer().host)
if resp is None:
resp = {}
if "type" not in resp:
resp['type'] = "res"
if "data" not in resp:
resp['data'] = {}
if "api" not in resp:
resp['api'] = msg["api"]
resp['api'] = api
if "result" not in resp:
resp['result'] = 'true'
self.logger.debug(f"Websocket response: {resp}")
self.sendMessage(json.dumps(resp).encode(), isBinary)
# 0001002c2112a442334a0506a62efa71477dcd698022002872655455524e2053796e6320436c69656e7420302e33202d20524643353338392f7475726e2d3132
class PokkenAdmissionFactory(WebSocketServerFactory):
protocol = PokkenAdmissionProtocol
@ -64,7 +58,7 @@ class PokkenAdmissionFactory(WebSocketServerFactory):
) -> None:
self.core_config = cfg
self.game_config = game_cfg
super().__init__(f"ws://{self.game_config.server.hostname}:{self.game_config.server.port_admission}")
super().__init__(f"ws://{self.game_config.server.hostname}:{self.game_config.ports.admission}")
def buildProtocol(self, addr: IAddress) -> Protocol:
p = self.protocol(self.core_config, self.game_config)