forked from Dniel97/artemis
pokken: Switch to using external STUN server
This commit is contained in:
parent
ec9ad1ebb0
commit
514f786e2d
@ -2,8 +2,11 @@ server:
|
|||||||
hostname: "localhost"
|
hostname: "localhost"
|
||||||
enable: True
|
enable: True
|
||||||
loglevel: "info"
|
loglevel: "info"
|
||||||
port: 9000
|
auto_register: True
|
||||||
port_stun: 9001
|
enable_matching: False
|
||||||
port_turn: 9002
|
stun_server_host: "stunserver.stunprotocol.org"
|
||||||
port_admission: 9003
|
stun_server_port: 3478
|
||||||
auto_register: True
|
|
||||||
|
ports:
|
||||||
|
game: 9000
|
||||||
|
admission: 9001
|
||||||
|
@ -44,19 +44,19 @@ class PokkenBase:
|
|||||||
biwa_setting = {
|
biwa_setting = {
|
||||||
"MatchingServer": {
|
"MatchingServer": {
|
||||||
"host": f"https://{self.game_cfg.server.hostname}",
|
"host": f"https://{self.game_cfg.server.hostname}",
|
||||||
"port": self.game_cfg.server.port,
|
"port": self.game_cfg.ports.game,
|
||||||
"url": "/SDAK/100/matching",
|
"url": "/SDAK/100/matching",
|
||||||
},
|
},
|
||||||
"StunServer": {
|
"StunServer": {
|
||||||
"addr": self.game_cfg.server.hostname,
|
"addr": self.game_cfg.server.stun_server_host,
|
||||||
"port": self.game_cfg.server.port_stun,
|
"port": self.game_cfg.server.stun_server_port,
|
||||||
},
|
},
|
||||||
"TurnServer": {
|
"TurnServer": {
|
||||||
"addr": self.game_cfg.server.hostname,
|
"addr": self.game_cfg.server.stun_server_host,
|
||||||
"port": self.game_cfg.server.port_turn,
|
"port": self.game_cfg.server.stun_server_port,
|
||||||
},
|
},
|
||||||
"AdmissionUrl": f"ws://{self.game_cfg.server.hostname}:{self.game_cfg.server.port_admission}",
|
"AdmissionUrl": f"ws://{self.game_cfg.server.hostname}:{self.game_cfg.ports.admission}",
|
||||||
"locationId": 123,
|
"locationId": 123, # FIXME: Get arcade's ID from the database
|
||||||
"logfilename": "JackalMatchingLibrary.log",
|
"logfilename": "JackalMatchingLibrary.log",
|
||||||
"biwalogfilename": "./biwa.log",
|
"biwalogfilename": "./biwa.log",
|
||||||
}
|
}
|
||||||
@ -94,6 +94,7 @@ class PokkenBase:
|
|||||||
res.type = jackal_pb2.MessageType.LOAD_CLIENT_SETTINGS
|
res.type = jackal_pb2.MessageType.LOAD_CLIENT_SETTINGS
|
||||||
settings = jackal_pb2.LoadClientSettingsResponseData()
|
settings = jackal_pb2.LoadClientSettingsResponseData()
|
||||||
|
|
||||||
|
# TODO: Make configurable
|
||||||
settings.money_magnification = 1
|
settings.money_magnification = 1
|
||||||
settings.continue_bonus_exp = 100
|
settings.continue_bonus_exp = 100
|
||||||
settings.continue_fight_money = 100
|
settings.continue_fight_money = 100
|
||||||
@ -356,12 +357,11 @@ class PokkenBase:
|
|||||||
self, data: Dict = {}, client_ip: str = "127.0.0.1"
|
self, data: Dict = {}, client_ip: str = "127.0.0.1"
|
||||||
) -> Dict:
|
) -> Dict:
|
||||||
"""
|
"""
|
||||||
"sessionId":"12345678",
|
"sessionId":"12345678",
|
||||||
"A":{
|
"A":{
|
||||||
"pcb_id": data["data"]["must"]["pcb_id"],
|
"pcb_id": data["data"]["must"]["pcb_id"],
|
||||||
"gip": client_ip
|
"gip": client_ip
|
||||||
},
|
},
|
||||||
"list":[]
|
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
"data": {
|
"data": {
|
||||||
@ -379,10 +379,13 @@ class PokkenBase:
|
|||||||
) -> Dict:
|
) -> Dict:
|
||||||
return {}
|
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:
|
def handle_admission_joinsession(self, data: Dict, req_ip: str = "127.0.0.1") -> Dict:
|
||||||
self.logger.info(f"Admission: JoinSession from {req_ip}")
|
self.logger.info(f"Admission: JoinSession from {req_ip}")
|
||||||
return {
|
return {
|
||||||
'data': {
|
'data': {
|
||||||
"id": 123
|
"id": 12345678
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
@property
|
||||||
def auto_register(self) -> bool:
|
def auto_register(self) -> bool:
|
||||||
"""
|
"""
|
||||||
@ -59,7 +35,51 @@ class PokkenServerConfig:
|
|||||||
self.__config, "pokken", "server", "auto_register", default=True
|
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):
|
class PokkenConfig(dict):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.server = PokkenServerConfig(self)
|
self.server = PokkenServerConfig(self)
|
||||||
|
self.ports = PokkenPortsConfig(self)
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from twisted.web.http import Request
|
from twisted.web.http import Request
|
||||||
from twisted.web import resource
|
from twisted.web import resource
|
||||||
from twisted.internet import reactor, endpoints
|
from twisted.internet import reactor
|
||||||
from autobahn.twisted.websocket import WebSocketServerFactory
|
|
||||||
import json, ast
|
import json, ast
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import yaml
|
import yaml
|
||||||
@ -17,7 +16,7 @@ from .config import PokkenConfig
|
|||||||
from .base import PokkenBase
|
from .base import PokkenBase
|
||||||
from .const import PokkenConstants
|
from .const import PokkenConstants
|
||||||
from .proto import jackal_pb2
|
from .proto import jackal_pb2
|
||||||
from .services import PokkenStunProtocol, PokkenAdmissionFactory, PokkenAdmissionProtocol
|
from .services import PokkenAdmissionFactory
|
||||||
|
|
||||||
|
|
||||||
class PokkenServlet(resource.Resource):
|
class PokkenServlet(resource.Resource):
|
||||||
@ -72,7 +71,7 @@ class PokkenServlet(resource.Resource):
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
True,
|
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/",
|
f"{game_cfg.server.hostname}/SDAK/$v/",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -93,21 +92,10 @@ class PokkenServlet(resource.Resource):
|
|||||||
return (True, "PKF1")
|
return (True, "PKF1")
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
# TODO: Setup stun, turn (UDP) and admission (WSS) servers
|
if self.game_cfg.server.enable_matching:
|
||||||
reactor.listenUDP(
|
reactor.listenTCP(
|
||||||
self.game_cfg.server.port_stun, PokkenStunProtocol(self.core_cfg, self.game_cfg, "Stun")
|
self.game_cfg.ports.admission, PokkenAdmissionFactory(self.core_cfg, self.game_cfg)
|
||||||
)
|
)
|
||||||
|
|
||||||
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)
|
|
||||||
)
|
|
||||||
|
|
||||||
def render_POST(
|
def render_POST(
|
||||||
self, request: Request, version: int = 0, endpoints: str = ""
|
self, request: Request, version: int = 0, endpoints: str = ""
|
||||||
@ -144,6 +132,9 @@ class PokkenServlet(resource.Resource):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def handle_matching(self, request: Request) -> bytes:
|
def handle_matching(self, request: Request) -> bytes:
|
||||||
|
if not self.game_cfg.server.enable_matching:
|
||||||
|
return b""
|
||||||
|
|
||||||
content = request.content.getvalue()
|
content = request.content.getvalue()
|
||||||
client_ip = Utils.get_ip_addr(request)
|
client_ip = Utils.get_ip_addr(request)
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
from twisted.internet.interfaces import IAddress
|
from twisted.internet.interfaces import IAddress
|
||||||
from twisted.internet.protocol import DatagramProtocol
|
|
||||||
from twisted.internet.protocol import Protocol
|
from twisted.internet.protocol import Protocol
|
||||||
from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory
|
from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory
|
||||||
from datetime import datetime
|
from autobahn.websocket.types import ConnectionRequest
|
||||||
|
from typing import Dict
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@ -10,21 +10,6 @@ from core.config import CoreConfig
|
|||||||
from .config import PokkenConfig
|
from .config import PokkenConfig
|
||||||
from .base import PokkenBase
|
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):
|
class PokkenAdmissionProtocol(WebSocketServerProtocol):
|
||||||
def __init__(self, cfg: CoreConfig, game_cfg: PokkenConfig):
|
def __init__(self, cfg: CoreConfig, game_cfg: PokkenConfig):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@ -33,27 +18,36 @@ class PokkenAdmissionProtocol(WebSocketServerProtocol):
|
|||||||
self.logger = logging.getLogger("pokken")
|
self.logger = logging.getLogger("pokken")
|
||||||
|
|
||||||
self.base = PokkenBase(cfg, game_cfg)
|
self.base = PokkenBase(cfg, game_cfg)
|
||||||
|
|
||||||
|
def onConnect(self, request: ConnectionRequest) -> None:
|
||||||
|
self.logger.debug(f"Admission: Connection from {request.peer}")
|
||||||
|
|
||||||
|
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:
|
def onMessage(self, payload, isBinary: bool) -> None:
|
||||||
msg = json.loads(payload)
|
msg: Dict = json.loads(payload)
|
||||||
self.logger.debug(f"WebSocket from from {self.transport.getPeer().host}:{self.transport.getPeer().port} -> {self.transport.getHost().port} - {msg}")
|
self.logger.debug(f"Admission: Message from {self.transport.getPeer().host}:{self.transport.getPeer().port} - {msg}")
|
||||||
|
|
||||||
handler = getattr(self.base, f"handle_admission_{msg['api'].lower()}")
|
api = msg.get("api", "noop")
|
||||||
|
handler = getattr(self.base, f"handle_admission_{api.lower()}")
|
||||||
resp = handler(msg, self.transport.getPeer().host)
|
resp = handler(msg, self.transport.getPeer().host)
|
||||||
|
|
||||||
|
if resp is None:
|
||||||
|
resp = {}
|
||||||
|
|
||||||
if "type" not in resp:
|
if "type" not in resp:
|
||||||
resp['type'] = "res"
|
resp['type'] = "res"
|
||||||
if "data" not in resp:
|
if "data" not in resp:
|
||||||
resp['data'] = {}
|
resp['data'] = {}
|
||||||
if "api" not in resp:
|
if "api" not in resp:
|
||||||
resp['api'] = msg["api"]
|
resp['api'] = api
|
||||||
if "result" not in resp:
|
if "result" not in resp:
|
||||||
resp['result'] = 'true'
|
resp['result'] = 'true'
|
||||||
|
|
||||||
self.logger.debug(f"Websocket response: {resp}")
|
self.logger.debug(f"Websocket response: {resp}")
|
||||||
self.sendMessage(json.dumps(resp).encode(), isBinary)
|
self.sendMessage(json.dumps(resp).encode(), isBinary)
|
||||||
|
|
||||||
# 0001002c2112a442334a0506a62efa71477dcd698022002872655455524e2053796e6320436c69656e7420302e33202d20524643353338392f7475726e2d3132
|
|
||||||
class PokkenAdmissionFactory(WebSocketServerFactory):
|
class PokkenAdmissionFactory(WebSocketServerFactory):
|
||||||
protocol = PokkenAdmissionProtocol
|
protocol = PokkenAdmissionProtocol
|
||||||
|
|
||||||
@ -64,7 +58,7 @@ class PokkenAdmissionFactory(WebSocketServerFactory):
|
|||||||
) -> None:
|
) -> None:
|
||||||
self.core_config = cfg
|
self.core_config = cfg
|
||||||
self.game_config = game_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:
|
def buildProtocol(self, addr: IAddress) -> Protocol:
|
||||||
p = self.protocol(self.core_config, self.game_config)
|
p = self.protocol(self.core_config, self.game_config)
|
||||||
|
Loading…
Reference in New Issue
Block a user