forked from Hay1tsme/artemis
Merge branch 'develop' into diva_handler_classes
This commit is contained in:
commit
3076bdf575
@ -12,8 +12,8 @@ from Crypto.Signature import PKCS1_v1_5
|
||||
from time import strptime
|
||||
|
||||
from core.config import CoreConfig
|
||||
from core.data import Data
|
||||
from core.utils import Utils
|
||||
from core.data import Data
|
||||
from core.const import *
|
||||
|
||||
|
||||
@ -65,11 +65,11 @@ class AllnetServlet:
|
||||
self.uri_registry[code] = (uri, host)
|
||||
|
||||
self.logger.info(
|
||||
f"Allnet serving {len(self.uri_registry)} games on port {core_cfg.allnet.port}"
|
||||
f"Serving {len(self.uri_registry)} game codes port {core_cfg.allnet.port}"
|
||||
)
|
||||
|
||||
def handle_poweron(self, request: Request, _: Dict):
|
||||
request_ip = request.getClientAddress().host
|
||||
request_ip = Utils.get_ip_addr(request)
|
||||
try:
|
||||
req_dict = self.allnet_req_to_dict(request.content.getvalue())
|
||||
if req_dict is None:
|
||||
@ -78,13 +78,7 @@ class AllnetServlet:
|
||||
req = AllnetPowerOnRequest(req_dict[0])
|
||||
# Validate the request. Currently we only validate the fields we plan on using
|
||||
|
||||
if (
|
||||
not req.game_id
|
||||
or not req.ver
|
||||
or not req.token
|
||||
or not req.serial
|
||||
or not req.ip
|
||||
):
|
||||
if not req.game_id or not req.ver or not req.serial or not req.ip:
|
||||
raise AllnetRequestException(
|
||||
f"Bad auth request params from {request_ip} - {vars(req)}"
|
||||
)
|
||||
@ -94,7 +88,7 @@ class AllnetServlet:
|
||||
self.logger.error(e)
|
||||
return b""
|
||||
|
||||
if req.format_ver == 3:
|
||||
if req.format_ver == "3":
|
||||
resp = AllnetPowerOnResponse3(req.token)
|
||||
else:
|
||||
resp = AllnetPowerOnResponse2()
|
||||
@ -168,7 +162,7 @@ class AllnetServlet:
|
||||
return self.dict_to_http_form_string([vars(resp)]).encode("utf-8")
|
||||
|
||||
def handle_dlorder(self, request: Request, _: Dict):
|
||||
request_ip = request.getClientAddress().host
|
||||
request_ip = Utils.get_ip_addr(request)
|
||||
try:
|
||||
req_dict = self.allnet_req_to_dict(request.content.getvalue())
|
||||
if req_dict is None:
|
||||
@ -261,7 +255,7 @@ class AllnetServlet:
|
||||
return resp_str.encode("utf-8")
|
||||
|
||||
def handle_naomitest(self, request: Request, _: Dict) -> bytes:
|
||||
self.logger.info(f"Ping from {request.getClientAddress().host}")
|
||||
self.logger.info(f"Ping from {Utils.get_ip_addr(request)}")
|
||||
return b"naomi ok"
|
||||
|
||||
def kvp_to_dict(self, kvp: List[str]) -> List[Dict[str, Any]]:
|
||||
@ -346,20 +340,16 @@ class AllnetPowerOnRequest:
|
||||
def __init__(self, req: Dict) -> None:
|
||||
if req is None:
|
||||
raise AllnetRequestException("Request processing failed")
|
||||
self.game_id: str = req["game_id"] if "game_id" in req else ""
|
||||
self.ver: str = req["ver"] if "ver" in req else ""
|
||||
self.serial: str = req["serial"] if "serial" in req else ""
|
||||
self.ip: str = req["ip"] if "ip" in req else ""
|
||||
self.firm_ver: str = req["firm_ver"] if "firm_ver" in req else ""
|
||||
self.boot_ver: str = req["boot_ver"] if "boot_ver" in req else ""
|
||||
self.encode: str = req["encode"] if "encode" in req else ""
|
||||
|
||||
try:
|
||||
self.hops = int(req["hops"]) if "hops" in req else 0
|
||||
self.format_ver = int(req["format_ver"]) if "format_ver" in req else 2
|
||||
self.token = int(req["token"]) if "token" in req else 0
|
||||
except ValueError as e:
|
||||
raise AllnetRequestException(f"Failed to parse int: {e}")
|
||||
self.game_id: str = req.get("game_id", "")
|
||||
self.ver: str = req.get("ver", "")
|
||||
self.serial: str = req.get("serial", "")
|
||||
self.ip: str = req.get("ip", "")
|
||||
self.firm_ver: str = req.get("firm_ver", "")
|
||||
self.boot_ver: str = req.get("boot_ver", "")
|
||||
self.encode: str = req.get("encode", "")
|
||||
self.hops = int(req.get("hops", "0"))
|
||||
self.format_ver = req.get("format_ver", "2")
|
||||
self.token = int(req.get("token", "0"))
|
||||
|
||||
|
||||
class AllnetPowerOnResponse3:
|
||||
@ -413,10 +403,10 @@ class AllnetPowerOnResponse2:
|
||||
|
||||
class AllnetDownloadOrderRequest:
|
||||
def __init__(self, req: Dict) -> None:
|
||||
self.game_id = req["game_id"] if "game_id" in req else ""
|
||||
self.ver = req["ver"] if "ver" in req else ""
|
||||
self.serial = req["serial"] if "serial" in req else ""
|
||||
self.encode = req["encode"] if "encode" in req else ""
|
||||
self.game_id = req.get("game_id", "")
|
||||
self.ver = req.get("ver", "")
|
||||
self.serial = req.get("serial", "")
|
||||
self.encode = req.get("encode", "")
|
||||
|
||||
|
||||
class AllnetDownloadOrderResponse:
|
||||
|
@ -267,24 +267,6 @@ class MuchaConfig:
|
||||
self.__config, "core", "mucha", "hostname", default="localhost"
|
||||
)
|
||||
|
||||
@property
|
||||
def port(self) -> int:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "core", "mucha", "port", default=8444
|
||||
)
|
||||
|
||||
@property
|
||||
def ssl_cert(self) -> str:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "core", "mucha", "ssl_cert", default="cert/server.pem"
|
||||
)
|
||||
|
||||
@property
|
||||
def signing_key(self) -> str:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "core", "mucha", "signing_key", default="cert/billing.key"
|
||||
)
|
||||
|
||||
|
||||
class CoreConfig(dict):
|
||||
def __init__(self) -> None:
|
||||
|
@ -71,7 +71,8 @@ class Data:
|
||||
games = Utils.get_all_titles()
|
||||
for game_dir, game_mod in games.items():
|
||||
try:
|
||||
title_db = game_mod.database(self.config)
|
||||
if hasattr(game_mod, "database") and hasattr(game_mod, "current_schema_version"):
|
||||
game_mod.database(self.config)
|
||||
metadata.create_all(self.__engine.connect())
|
||||
|
||||
self.base.set_schema_ver(
|
||||
@ -109,7 +110,8 @@ class Data:
|
||||
mod = importlib.import_module(f"titles.{dir}")
|
||||
|
||||
try:
|
||||
title_db = mod.database(self.config)
|
||||
if hasattr(mod, "database"):
|
||||
mod.database(self.config)
|
||||
metadata.drop_all(self.__engine.connect())
|
||||
|
||||
except Exception as e:
|
||||
|
@ -10,9 +10,8 @@ from twisted.python.components import registerAdapter
|
||||
import jinja2
|
||||
import bcrypt
|
||||
|
||||
from core.config import CoreConfig
|
||||
from core import CoreConfig, Utils
|
||||
from core.data import Data
|
||||
from core.utils import Utils
|
||||
|
||||
|
||||
class IUserSession(Interface):
|
||||
@ -143,7 +142,7 @@ class FE_Gate(FE_Base):
|
||||
|
||||
def render_POST(self, request: Request):
|
||||
uri = request.uri.decode()
|
||||
ip = request.getClientAddress().host
|
||||
ip = Utils.get_ip_addr(request)
|
||||
|
||||
if uri == "/gate/gate.login":
|
||||
access_code: str = request.args[b"access_code"][0].decode()
|
||||
|
@ -6,7 +6,7 @@ from twisted.web.http import Request
|
||||
from datetime import datetime
|
||||
import pytz
|
||||
|
||||
from core.config import CoreConfig
|
||||
from core import CoreConfig
|
||||
from core.utils import Utils
|
||||
|
||||
|
||||
@ -47,11 +47,13 @@ class MuchaServlet:
|
||||
self.mucha_registry.append(game_cd)
|
||||
|
||||
self.logger.info(
|
||||
f"Serving {len(self.mucha_registry)} games on port {self.config.mucha.port}"
|
||||
f"Serving {len(self.mucha_registry)} games"
|
||||
)
|
||||
|
||||
def handle_boardauth(self, request: Request, _: Dict) -> bytes:
|
||||
req_dict = self.mucha_preprocess(request.content.getvalue())
|
||||
client_ip = Utils.get_ip_addr(request)
|
||||
|
||||
if req_dict is None:
|
||||
self.logger.error(
|
||||
f"Error processing mucha request {request.content.getvalue()}"
|
||||
@ -61,7 +63,7 @@ class MuchaServlet:
|
||||
req = MuchaAuthRequest(req_dict)
|
||||
self.logger.debug(f"Mucha request {vars(req)}")
|
||||
self.logger.info(
|
||||
f"Boardauth request from {request.getClientAddress().host} for {req.gameVer}"
|
||||
f"Boardauth request from {client_ip} for {req.gameVer}"
|
||||
)
|
||||
|
||||
if req.gameCd not in self.mucha_registry:
|
||||
@ -71,7 +73,7 @@ class MuchaServlet:
|
||||
# TODO: Decrypt S/N
|
||||
|
||||
resp = MuchaAuthResponse(
|
||||
f"{self.config.mucha.hostname}{':' + self.config.mucha.port if self.config.server.is_develop else ''}"
|
||||
f"{self.config.mucha.hostname}{':' + str(self.config.allnet.port) if self.config.server.is_develop else ''}"
|
||||
)
|
||||
|
||||
self.logger.debug(f"Mucha response {vars(resp)}")
|
||||
@ -80,6 +82,8 @@ class MuchaServlet:
|
||||
|
||||
def handle_updatecheck(self, request: Request, _: Dict) -> bytes:
|
||||
req_dict = self.mucha_preprocess(request.content.getvalue())
|
||||
client_ip = Utils.get_ip_addr(request)
|
||||
|
||||
if req_dict is None:
|
||||
self.logger.error(
|
||||
f"Error processing mucha request {request.content.getvalue()}"
|
||||
@ -89,7 +93,7 @@ class MuchaServlet:
|
||||
req = MuchaUpdateRequest(req_dict)
|
||||
self.logger.debug(f"Mucha request {vars(req)}")
|
||||
self.logger.info(
|
||||
f"Updatecheck request from {request.getClientAddress().host} for {req.gameVer}"
|
||||
f"Updatecheck request from {client_ip} for {req.gameVer}"
|
||||
)
|
||||
|
||||
if req.gameCd not in self.mucha_registry:
|
||||
@ -132,24 +136,19 @@ class MuchaServlet:
|
||||
|
||||
class MuchaAuthRequest:
|
||||
def __init__(self, request: Dict) -> None:
|
||||
self.gameVer = (
|
||||
"" if "gameVer" not in request else request["gameVer"]
|
||||
) # gameCd + boardType + countryCd + version
|
||||
self.sendDate = (
|
||||
"" if "sendDate" not in request else request["sendDate"]
|
||||
) # %Y%m%d
|
||||
self.serialNum = "" if "serialNum" not in request else request["serialNum"]
|
||||
self.gameCd = "" if "gameCd" not in request else request["gameCd"]
|
||||
self.boardType = "" if "boardType" not in request else request["boardType"]
|
||||
self.boardId = "" if "boardId" not in request else request["boardId"]
|
||||
self.mac = "" if "mac" not in request else request["mac"]
|
||||
self.placeId = "" if "placeId" not in request else request["placeId"]
|
||||
self.storeRouterIp = (
|
||||
"" if "storeRouterIp" not in request else request["storeRouterIp"]
|
||||
)
|
||||
self.countryCd = "" if "countryCd" not in request else request["countryCd"]
|
||||
self.useToken = "" if "useToken" not in request else request["useToken"]
|
||||
self.allToken = "" if "allToken" not in request else request["allToken"]
|
||||
# gameCd + boardType + countryCd + version
|
||||
self.gameVer = request.get("gameVer", "")
|
||||
self.sendDate = request.get("sendDate", "") # %Y%m%d
|
||||
self.serialNum = request.get("serialNum", "")
|
||||
self.gameCd = request.get("gameCd", "")
|
||||
self.boardType = request.get("boardType", "")
|
||||
self.boardId = request.get("boardId", "")
|
||||
self.mac = request.get("mac", "")
|
||||
self.placeId = request.get("placeId", "")
|
||||
self.storeRouterIp = request.get("storeRouterIp", "")
|
||||
self.countryCd = request.get("countryCd", "")
|
||||
self.useToken = request.get("useToken", "")
|
||||
self.allToken = request.get("allToken", "")
|
||||
|
||||
|
||||
class MuchaAuthResponse:
|
||||
@ -199,14 +198,12 @@ class MuchaAuthResponse:
|
||||
|
||||
class MuchaUpdateRequest:
|
||||
def __init__(self, request: Dict) -> None:
|
||||
self.gameVer = "" if "gameVer" not in request else request["gameVer"]
|
||||
self.gameCd = "" if "gameCd" not in request else request["gameCd"]
|
||||
self.serialNum = "" if "serialNum" not in request else request["serialNum"]
|
||||
self.countryCd = "" if "countryCd" not in request else request["countryCd"]
|
||||
self.placeId = "" if "placeId" not in request else request["placeId"]
|
||||
self.storeRouterIp = (
|
||||
"" if "storeRouterIp" not in request else request["storeRouterIp"]
|
||||
)
|
||||
self.gameVer = request.get("gameVer", "")
|
||||
self.gameCd = request.get("gameCd", "")
|
||||
self.serialNum = request.get("serialNum", "")
|
||||
self.countryCd = request.get("countryCd", "")
|
||||
self.placeId = request.get("placeId", "")
|
||||
self.storeRouterIp = request.get("storeRouterIp", "")
|
||||
|
||||
|
||||
class MuchaUpdateResponse:
|
||||
|
@ -68,7 +68,7 @@ class TitleServlet:
|
||||
self.logger.error(f"{folder} missing game_code or index in __init__.py")
|
||||
|
||||
self.logger.info(
|
||||
f"Serving {len(self.title_registry)} game codes on port {core_cfg.title.port}"
|
||||
f"Serving {len(self.title_registry)} game codes {'on port ' + str(core_cfg.title.port) if core_cfg.title.port > 0 else ''}"
|
||||
)
|
||||
|
||||
def render_GET(self, request: Request, endpoints: dict) -> bytes:
|
||||
|
@ -1,5 +1,6 @@
|
||||
from typing import Dict, Any
|
||||
from types import ModuleType
|
||||
from twisted.web.http import Request
|
||||
import logging
|
||||
import importlib
|
||||
from os import walk
|
||||
@ -21,3 +22,7 @@ class Utils:
|
||||
logging.getLogger("core").error(f"get_all_titles: {dir} - {e}")
|
||||
raise
|
||||
return ret
|
||||
|
||||
@classmethod
|
||||
def get_ip_addr(cls, req: Request) -> str:
|
||||
return req.getAllHeaders()[b"x-forwarded-for"].decode() if b"x-forwarded-for" in req.getAllHeaders() else req.getClientAddress().host
|
||||
|
@ -48,6 +48,3 @@ mucha:
|
||||
enable: False
|
||||
hostname: "localhost"
|
||||
loglevel: "info"
|
||||
port: 8444
|
||||
ssl_key: "cert/server.key"
|
||||
ssl_cert: "cert/server.pem"
|
||||
|
@ -4,6 +4,8 @@ server {
|
||||
server_name naominet.jp;
|
||||
|
||||
location / {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass_request_headers on;
|
||||
proxy_pass http://localhost:8000/;
|
||||
}
|
||||
}
|
||||
@ -14,6 +16,8 @@ server {
|
||||
server_name your.hostname.here;
|
||||
|
||||
location / {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass_request_headers on;
|
||||
proxy_pass http://localhost:8080/;
|
||||
}
|
||||
}
|
||||
@ -75,6 +79,8 @@ server {
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
location / {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass_request_headers on;
|
||||
proxy_pass http://localhost:8080/;
|
||||
}
|
||||
}
|
||||
@ -95,6 +101,8 @@ server {
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
location / {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass_request_headers on;
|
||||
proxy_pass http://localhost:8080/SDBT/104/;
|
||||
}
|
||||
}
|
||||
@ -131,6 +139,8 @@ server {
|
||||
add_header Strict-Transport-Security "max-age=63072000" always;
|
||||
|
||||
location / {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass_request_headers on;
|
||||
proxy_pass http://localhost:8090/;
|
||||
}
|
||||
}
|
@ -3,9 +3,6 @@ server:
|
||||
enable: True
|
||||
loglevel: "info"
|
||||
port: 9000
|
||||
port_matching: 9001
|
||||
port_stun: 9002
|
||||
port_turn: 9003
|
||||
port_admission: 9004
|
||||
ssl_cert: cert/pokken.crt
|
||||
ssl_key: cert/pokken.key
|
||||
port_stun: 9001
|
||||
port_turn: 9002
|
||||
port_admission: 9003
|
16
index.py
16
index.py
@ -73,7 +73,7 @@ class HttpDispatcher(resource.Resource):
|
||||
"mucha_updatacheck",
|
||||
"/mucha/updatacheck.do",
|
||||
controller="mucha",
|
||||
action="handle_updatacheck",
|
||||
action="handle_updatecheck",
|
||||
conditions=dict(method=["POST"]),
|
||||
)
|
||||
|
||||
@ -96,9 +96,11 @@ class HttpDispatcher(resource.Resource):
|
||||
|
||||
def render_GET(self, request: Request) -> bytes:
|
||||
test = self.map_get.match(request.uri.decode())
|
||||
client_ip = Utils.get_ip_addr(request)
|
||||
|
||||
if test is None:
|
||||
self.logger.debug(
|
||||
f"Unknown GET endpoint {request.uri.decode()} from {request.getClientAddress().host} to port {request.getHost().port}"
|
||||
f"Unknown GET endpoint {request.uri.decode()} from {client_ip} to port {request.getHost().port}"
|
||||
)
|
||||
request.setResponseCode(404)
|
||||
return b"Endpoint not found."
|
||||
@ -107,9 +109,11 @@ class HttpDispatcher(resource.Resource):
|
||||
|
||||
def render_POST(self, request: Request) -> bytes:
|
||||
test = self.map_post.match(request.uri.decode())
|
||||
client_ip = Utils.get_ip_addr(request)
|
||||
|
||||
if test is None:
|
||||
self.logger.debug(
|
||||
f"Unknown POST endpoint {request.uri.decode()} from {request.getClientAddress().host} to port {request.getHost().port}"
|
||||
f"Unknown POST endpoint {request.uri.decode()} from {client_ip} to port {request.getHost().port}"
|
||||
)
|
||||
request.setResponseCode(404)
|
||||
return b"Endpoint not found."
|
||||
@ -163,6 +167,9 @@ if __name__ == "__main__":
|
||||
if path.exists(f"{args.config}/core.yaml"):
|
||||
cfg.update(yaml.safe_load(open(f"{args.config}/core.yaml")))
|
||||
|
||||
if not path.exists(cfg.server.log_dir):
|
||||
mkdir(cfg.server.log_dir)
|
||||
|
||||
logger = logging.getLogger("core")
|
||||
log_fmt_str = "[%(asctime)s] Core | %(levelname)s | %(message)s"
|
||||
log_fmt = logging.Formatter(log_fmt_str)
|
||||
@ -182,9 +189,6 @@ if __name__ == "__main__":
|
||||
logger.setLevel(log_lv)
|
||||
coloredlogs.install(level=log_lv, logger=logger, fmt=log_fmt_str)
|
||||
|
||||
if not path.exists(cfg.server.log_dir):
|
||||
mkdir(cfg.server.log_dir)
|
||||
|
||||
if not access(cfg.server.log_dir, W_OK):
|
||||
logger.error(
|
||||
f"Log directory {cfg.server.log_dir} NOT writable, please check permissions"
|
||||
|
3
read.py
3
read.py
@ -9,8 +9,7 @@ import logging, coloredlogs
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
from typing import List, Optional
|
||||
|
||||
from core import CoreConfig
|
||||
from core.utils import Utils
|
||||
from core import CoreConfig, Utils
|
||||
|
||||
|
||||
class BaseReader:
|
||||
|
@ -11,7 +11,7 @@ from Crypto.Util.Padding import pad
|
||||
from os import path
|
||||
from typing import Tuple
|
||||
|
||||
from core import CoreConfig
|
||||
from core import CoreConfig, Utils
|
||||
from titles.chuni.config import ChuniConfig
|
||||
from titles.chuni.const import ChuniConstants
|
||||
from titles.chuni.base import ChuniBase
|
||||
@ -111,6 +111,7 @@ class ChuniServlet:
|
||||
encrtped = False
|
||||
internal_ver = 0
|
||||
endpoint = url_split[len(url_split) - 1]
|
||||
client_ip = Utils.get_ip_addr(request)
|
||||
|
||||
if version < 105: # 1.0
|
||||
internal_ver = ChuniConstants.VER_CHUNITHM
|
||||
@ -179,7 +180,7 @@ class ChuniServlet:
|
||||
req_data = json.loads(unzip)
|
||||
|
||||
self.logger.info(
|
||||
f"v{version} {endpoint} request from {request.getClientAddress().host}"
|
||||
f"v{version} {endpoint} request from {client_ip}"
|
||||
)
|
||||
self.logger.debug(req_data)
|
||||
|
||||
|
@ -60,6 +60,9 @@ class ChuniNew(ChuniBase):
|
||||
"isAou": "false",
|
||||
}
|
||||
|
||||
def handle_remove_token_api_request(self, data: Dict) -> Dict:
|
||||
return { "returnCode": "1" }
|
||||
|
||||
def handle_delete_token_api_request(self, data: Dict) -> Dict:
|
||||
return {"returnCode": "1"}
|
||||
|
||||
|
@ -27,6 +27,8 @@ class CardMaker136(CardMakerBase):
|
||||
ret["gameConnectList"][1]["titleUri"] = f"{uri}/SDEZ/125/"
|
||||
ret["gameConnectList"][2]["titleUri"] = f"{uri}/SDDT/135/"
|
||||
|
||||
return ret
|
||||
|
||||
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_get_game_setting_api_request(data)
|
||||
ret["gameSetting"]["dataVersion"] = "1.35.00"
|
||||
|
@ -98,11 +98,11 @@ class CxbServlet(resource.Resource):
|
||||
).listen(server.Site(CxbServlet(self.core_cfg, self.cfg_dir)))
|
||||
|
||||
self.logger.info(
|
||||
f"Crossbeats title server ready on port {self.game_cfg.server.port} & {self.game_cfg.server.port_secure}"
|
||||
f"Ready on ports {self.game_cfg.server.port} & {self.game_cfg.server.port_secure}"
|
||||
)
|
||||
else:
|
||||
self.logger.info(
|
||||
f"Crossbeats title server ready on port {self.game_cfg.server.port}"
|
||||
f"Ready on port {self.game_cfg.server.port}"
|
||||
)
|
||||
|
||||
def render_POST(self, request: Request):
|
||||
|
@ -298,6 +298,6 @@ class DivaReader(BaseReader):
|
||||
tree[key] = (
|
||||
value
|
||||
if len(vector) == 1
|
||||
else self.add_branch(tree[key] if key in tree else {}, vector[1:], value)
|
||||
else self.add_branch(tree.get(key, {}), vector[1:], value)
|
||||
)
|
||||
return tree
|
||||
|
@ -1,6 +1,6 @@
|
||||
from datetime import datetime, timedelta
|
||||
import json
|
||||
from typing import Any
|
||||
import json, logging
|
||||
from typing import Any, Dict
|
||||
|
||||
from core.config import CoreConfig
|
||||
from titles.pokken.config import PokkenConfig
|
||||
@ -12,6 +12,7 @@ class PokkenBase:
|
||||
self.core_cfg = core_cfg
|
||||
self.game_cfg = game_cfg
|
||||
self.version = 0
|
||||
self.logger = logging.getLogger("pokken")
|
||||
|
||||
def handle_noop(self, request: Any) -> bytes:
|
||||
res = jackal_pb2.Response()
|
||||
@ -20,25 +21,26 @@ class PokkenBase:
|
||||
|
||||
return res.SerializeToString()
|
||||
|
||||
def handle_ping(self, request: jackal_pb2.PingRequestData) -> bytes:
|
||||
def handle_ping(self, request: jackal_pb2.Request) -> bytes:
|
||||
res = jackal_pb2.Response()
|
||||
res.result = 1
|
||||
res.type = jackal_pb2.MessageType.PING
|
||||
|
||||
return res.SerializeToString()
|
||||
|
||||
def handle_register_pcb(self, request: jackal_pb2.RegisterPcbRequestData) -> bytes:
|
||||
def handle_register_pcb(self, request: jackal_pb2.Request) -> bytes:
|
||||
res = jackal_pb2.Response()
|
||||
res.result = 1
|
||||
res.type = jackal_pb2.MessageType.REGISTER_PCB
|
||||
self.logger.info(f"Register PCB {request.register_pcb.pcb_id}")
|
||||
|
||||
regist_pcb = jackal_pb2.RegisterPcbResponseData()
|
||||
regist_pcb.server_time = int(datetime.now().timestamp() / 1000)
|
||||
regist_pcb.server_time = int(datetime.now().timestamp())
|
||||
biwa_setting = {
|
||||
"MatchingServer": {
|
||||
"host": f"https://{self.game_cfg.server.hostname}",
|
||||
"port": self.game_cfg.server.port_matching,
|
||||
"url": "/matching",
|
||||
"port": self.game_cfg.server.port,
|
||||
"url": "/SDAK/100/matching",
|
||||
},
|
||||
"StunServer": {
|
||||
"addr": self.game_cfg.server.hostname,
|
||||
@ -60,7 +62,7 @@ class PokkenBase:
|
||||
|
||||
return res.SerializeToString()
|
||||
|
||||
def handle_save_ads(self, request: jackal_pb2.SaveAdsRequestData) -> bytes:
|
||||
def handle_save_ads(self, request: jackal_pb2.Request) -> bytes:
|
||||
res = jackal_pb2.Response()
|
||||
res.result = 1
|
||||
res.type = jackal_pb2.MessageType.SAVE_ADS
|
||||
@ -68,7 +70,7 @@ class PokkenBase:
|
||||
return res.SerializeToString()
|
||||
|
||||
def handle_save_client_log(
|
||||
self, request: jackal_pb2.SaveClientLogRequestData
|
||||
self, request: jackal_pb2.Request
|
||||
) -> bytes:
|
||||
res = jackal_pb2.Response()
|
||||
res.result = 1
|
||||
@ -77,7 +79,7 @@ class PokkenBase:
|
||||
return res.SerializeToString()
|
||||
|
||||
def handle_check_diagnosis(
|
||||
self, request: jackal_pb2.CheckDiagnosisRequestData
|
||||
self, request: jackal_pb2.Request
|
||||
) -> bytes:
|
||||
res = jackal_pb2.Response()
|
||||
res.result = 1
|
||||
@ -86,7 +88,7 @@ class PokkenBase:
|
||||
return res.SerializeToString()
|
||||
|
||||
def handle_load_client_settings(
|
||||
self, request: jackal_pb2.CheckDiagnosisRequestData
|
||||
self, request: jackal_pb2.Request
|
||||
) -> bytes:
|
||||
res = jackal_pb2.Response()
|
||||
res.result = 1
|
||||
@ -108,3 +110,36 @@ class PokkenBase:
|
||||
res.load_client_settings.CopyFrom(settings)
|
||||
|
||||
return res.SerializeToString()
|
||||
|
||||
def handle_load_ranking(self, request: jackal_pb2.Request) -> bytes:
|
||||
res = jackal_pb2.Response()
|
||||
res.result = 1
|
||||
res.type = jackal_pb2.MessageType.LOAD_RANKING
|
||||
ranking = jackal_pb2.LoadRankingResponseData()
|
||||
|
||||
ranking.ranking_id = 1
|
||||
ranking.ranking_start = 0
|
||||
ranking.ranking_end = 1
|
||||
ranking.event_end = True
|
||||
ranking.modify_date = int(datetime.now().timestamp() / 1000)
|
||||
res.load_ranking.CopyFrom(ranking)
|
||||
|
||||
def handle_matching_noop(self, data: Dict = {}, client_ip: str = "127.0.0.1") -> Dict:
|
||||
return {}
|
||||
|
||||
def handle_matching_start_matching(self, data: Dict = {}, client_ip: str = "127.0.0.1") -> Dict:
|
||||
return {}
|
||||
|
||||
def handle_matching_is_matching(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":[]
|
||||
"""
|
||||
return {}
|
||||
|
||||
def handle_matching_stop_matching(self, data: Dict = {}, client_ip: str = "127.0.0.1") -> Dict:
|
||||
return {}
|
@ -31,43 +31,24 @@ class PokkenServerConfig:
|
||||
self.__config, "pokken", "server", "port", default=9000
|
||||
)
|
||||
|
||||
@property
|
||||
def port_matching(self) -> int:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "pokken", "server", "port_matching", default=9001
|
||||
)
|
||||
|
||||
@property
|
||||
def port_stun(self) -> int:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "pokken", "server", "port_stun", default=9002
|
||||
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=9003
|
||||
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=9004
|
||||
self.__config, "pokken", "server", "port_admission", default=9003
|
||||
)
|
||||
|
||||
@property
|
||||
def ssl_cert(self) -> str:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "pokken", "server", "ssl_cert", default="cert/pokken.crt"
|
||||
)
|
||||
|
||||
@property
|
||||
def ssl_key(self) -> str:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "pokken", "server", "ssl_key", default="cert/pokken.key"
|
||||
)
|
||||
|
||||
|
||||
class PokkenConfig(dict):
|
||||
def __init__(self) -> None:
|
||||
self.server = PokkenServerConfig(self)
|
||||
|
@ -1,18 +1,20 @@
|
||||
from typing import Tuple
|
||||
from twisted.web.http import Request
|
||||
from twisted.web import resource, server
|
||||
from twisted.internet import reactor, endpoints
|
||||
from twisted.web import resource
|
||||
import json, ast
|
||||
from datetime import datetime
|
||||
import yaml
|
||||
import logging, coloredlogs
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
from titles.pokken.proto import jackal_pb2
|
||||
import inflection
|
||||
from os import path
|
||||
from google.protobuf.message import DecodeError
|
||||
|
||||
from core.config import CoreConfig
|
||||
from core import CoreConfig, Utils
|
||||
from titles.pokken.config import PokkenConfig
|
||||
from titles.pokken.base import PokkenBase
|
||||
from titles.pokken.const import PokkenConstants
|
||||
from titles.pokken.proto import jackal_pb2
|
||||
|
||||
|
||||
class PokkenServlet(resource.Resource):
|
||||
@ -65,17 +67,10 @@ class PokkenServlet(resource.Resource):
|
||||
if not game_cfg.server.enable:
|
||||
return (False, "", "")
|
||||
|
||||
if core_cfg.server.is_develop:
|
||||
return (
|
||||
True,
|
||||
f"https://{game_cfg.server.hostname}:{game_cfg.server.port}/{game_code}/$v/",
|
||||
f"{game_cfg.server.hostname}:{game_cfg.server.port}/",
|
||||
)
|
||||
|
||||
return (
|
||||
True,
|
||||
f"https://{game_cfg.server.hostname}/{game_code}/$v/",
|
||||
f"{game_cfg.server.hostname}/",
|
||||
f"{game_cfg.server.hostname}/SDAK/$v/",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@ -90,46 +85,19 @@ class PokkenServlet(resource.Resource):
|
||||
)
|
||||
|
||||
if not game_cfg.server.enable:
|
||||
return (False, "", "")
|
||||
return (False, "")
|
||||
|
||||
return (True, "PKFN")
|
||||
return (True, "PKF2")
|
||||
|
||||
def setup(self):
|
||||
"""
|
||||
There's currently no point in having this server on because Twisted
|
||||
won't play ball with both the fact that it's TLSv1.1, and because the
|
||||
types of certs that pokken will accept are too flimsy for Twisted
|
||||
so it will throw a fit. Currently leaving this here in case a bypass
|
||||
is discovered in the future, but it's unlikly. For now, just use NGINX.
|
||||
"""
|
||||
if self.game_cfg.server.enable and self.core_cfg.server.is_develop:
|
||||
key_exists = path.exists(self.game_cfg.server.ssl_key)
|
||||
cert_exists = path.exists(self.game_cfg.server.ssl_cert)
|
||||
|
||||
if key_exists and cert_exists:
|
||||
endpoints.serverFromString(
|
||||
reactor,
|
||||
f"ssl:{self.game_cfg.server.port}"
|
||||
f":interface={self.core_cfg.server.listen_address}:privateKey={self.game_cfg.server.ssl_key}:"
|
||||
f"certKey={self.game_cfg.server.ssl_cert}",
|
||||
).listen(server.Site(self))
|
||||
|
||||
self.logger.info(
|
||||
f"Pokken title server ready on port {self.game_cfg.server.port}"
|
||||
)
|
||||
|
||||
else:
|
||||
self.logger.error(
|
||||
f"Could not find cert at {self.game_cfg.server.ssl_key} or key at {self.game_cfg.server.ssl_cert}, Pokken not running."
|
||||
)
|
||||
def setup(self) -> None:
|
||||
# TODO: Setup stun, turn (UDP) and admission (WSS) servers
|
||||
pass
|
||||
|
||||
def render_POST(
|
||||
self, request: Request, version: int = 0, endpoints: str = ""
|
||||
) -> bytes:
|
||||
if endpoints == "":
|
||||
endpoints = request.uri.decode()
|
||||
if endpoints.startswith("/matching"):
|
||||
self.logger.info("Matching request")
|
||||
if endpoints == "matching":
|
||||
return self.handle_matching(request)
|
||||
|
||||
content = request.content.getvalue()
|
||||
if content == b"":
|
||||
@ -143,12 +111,50 @@ class PokkenServlet(resource.Resource):
|
||||
self.logger.warn(f"{e} {content}")
|
||||
return b""
|
||||
|
||||
endpoint = jackal_pb2.MessageType(pokken_request.type).name.lower()
|
||||
|
||||
self.logger.info(f"{endpoint} request")
|
||||
endpoint = jackal_pb2.MessageType.DESCRIPTOR.values_by_number[
|
||||
pokken_request.type
|
||||
].name.lower()
|
||||
|
||||
handler = getattr(self.base, f"handle_{endpoint}", None)
|
||||
if handler is None:
|
||||
self.logger.warn(f"No handler found for message type {endpoint}")
|
||||
return self.base.handle_noop(pokken_request)
|
||||
return handler(pokken_request)
|
||||
|
||||
self.logger.info(f"{endpoint} request from {Utils.get_ip_addr(request)}")
|
||||
self.logger.debug(pokken_request)
|
||||
|
||||
ret = handler(pokken_request)
|
||||
self.logger.debug(f"Response: {ret}")
|
||||
return ret
|
||||
|
||||
def handle_matching(self, request: Request) -> bytes:
|
||||
content = request.content.getvalue()
|
||||
client_ip = Utils.get_ip_addr(request)
|
||||
|
||||
if content is None or content == b"":
|
||||
self.logger.info("Empty matching request")
|
||||
return json.dumps(self.base.handle_matching_noop()).encode()
|
||||
|
||||
json_content = ast.literal_eval(content.decode().replace('null', 'None').replace('true', 'True').replace('false', 'False'))
|
||||
self.logger.info(f"Matching {json_content['call']} request")
|
||||
self.logger.debug(json_content)
|
||||
|
||||
handler = getattr(self.base, f"handle_matching_{inflection.underscore(json_content['call'])}", None)
|
||||
if handler is None:
|
||||
self.logger.warn(f"No handler found for message type {json_content['call']}")
|
||||
return json.dumps(self.base.handle_matching_noop()).encode()
|
||||
|
||||
ret = handler(json_content, client_ip)
|
||||
|
||||
if ret is None:
|
||||
ret = {}
|
||||
if "result" not in ret:
|
||||
ret["result"] = "true"
|
||||
if "data" not in ret:
|
||||
ret["data"] = {}
|
||||
if "timestamp" not in ret:
|
||||
ret["timestamp"] = int(datetime.now().timestamp() * 1000)
|
||||
|
||||
self.logger.debug(f"Response {ret}")
|
||||
|
||||
return json.dumps(ret).encode()
|
||||
|
@ -1,6 +1,7 @@
|
||||
import yaml
|
||||
import jinja2
|
||||
from twisted.web.http import Request
|
||||
from os import path
|
||||
|
||||
from core.frontend import FE_Base
|
||||
from core.config import CoreConfig
|
||||
@ -16,7 +17,10 @@ class WaccaFrontend(FE_Base):
|
||||
super().__init__(cfg, environment)
|
||||
self.data = WaccaData(cfg)
|
||||
self.game_cfg = WaccaConfig()
|
||||
self.game_cfg.update(yaml.safe_load(open(f"{cfg_dir}/wacca.yaml")))
|
||||
if path.exists(f"{cfg_dir}/{WaccaConstants.CONFIG_NAME}"):
|
||||
self.game_cfg.update(
|
||||
yaml.safe_load(open(f"{cfg_dir}/{WaccaConstants.CONFIG_NAME}"))
|
||||
)
|
||||
self.nav_name = "Wacca"
|
||||
|
||||
def render_GET(self, request: Request) -> bytes:
|
||||
|
@ -8,7 +8,7 @@ from twisted.web.http import Request
|
||||
from typing import Dict, Tuple
|
||||
from os import path
|
||||
|
||||
from core.config import CoreConfig
|
||||
from core import CoreConfig, Utils
|
||||
from titles.wacca.config import WaccaConfig
|
||||
from titles.wacca.config import WaccaConfig
|
||||
from titles.wacca.const import WaccaConstants
|
||||
@ -89,25 +89,30 @@ class WaccaServlet:
|
||||
request.responseHeaders.addRawHeader(b"X-Wacca-Hash", hash.hex().encode())
|
||||
return json.dumps(resp).encode()
|
||||
|
||||
client_ip = Utils.get_ip_addr(request)
|
||||
try:
|
||||
req_json = json.loads(request.content.getvalue())
|
||||
version_full = Version(req_json["appVersion"])
|
||||
except:
|
||||
self.logger.error(
|
||||
f"Failed to parse request toi {request.uri} -> {request.content.getvalue()}"
|
||||
f"Failed to parse request to {url_path} -> {request.content.getvalue()}"
|
||||
)
|
||||
resp = BaseResponse()
|
||||
resp.status = 1
|
||||
resp.message = "不正なリクエスト エラーです"
|
||||
return end(resp.make())
|
||||
|
||||
url_split = url_path.split("/")
|
||||
start_req_idx = url_split.index("api") + 1
|
||||
if "/api/" in url_path:
|
||||
func_to_find = (
|
||||
"handle_" + url_path.partition("api/")[2].replace("/", "_") + "_request"
|
||||
)
|
||||
|
||||
func_to_find = "handle_"
|
||||
for x in range(len(url_split) - start_req_idx):
|
||||
func_to_find += f"{url_split[x + start_req_idx]}_"
|
||||
func_to_find += "request"
|
||||
else:
|
||||
self.logger.error(f"Malformed url {url_path}")
|
||||
resp = BaseResponse()
|
||||
resp.status = 1
|
||||
resp.message = "Bad URL"
|
||||
return end(resp.make())
|
||||
|
||||
ver_search = int(version_full)
|
||||
|
||||
@ -136,7 +141,7 @@ class WaccaServlet:
|
||||
return end(resp.make())
|
||||
|
||||
self.logger.info(
|
||||
f"v{req_json['appVersion']} {url_path} request from {request.getClientAddress().host} with chipId {req_json['chipId']}"
|
||||
f"v{req_json['appVersion']} {url_path} request from {client_ip} with chipId {req_json['chipId']}"
|
||||
)
|
||||
self.logger.debug(req_json)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user