forked from Hay1tsme/artemis
added core logger, allnet resiliancy
This commit is contained in:
parent
2bd980165e
commit
c213926893
@ -95,14 +95,19 @@ class AllnetServlet:
|
|||||||
def handle_poweron(self, request: Request, _: Dict):
|
def handle_poweron(self, request: Request, _: Dict):
|
||||||
request_ip = request.getClientAddress().host
|
request_ip = request.getClientAddress().host
|
||||||
try:
|
try:
|
||||||
req = AllnetPowerOnRequest(self.allnet_req_to_dict(request.content.getvalue())[0])
|
req_dict = self.allnet_req_to_dict(request.content.getvalue())
|
||||||
|
if req_dict is None:
|
||||||
|
raise AllnetRequestException()
|
||||||
|
|
||||||
|
req = AllnetPowerOnRequest(req_dict[0])
|
||||||
# Validate the request. Currently we only validate the fields we plan on using
|
# 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.token or not req.serial or not req.ip:
|
||||||
raise AllnetRequestException(f"Bad auth request params from {request_ip} - {vars(req)}")
|
raise AllnetRequestException(f"Bad auth request params from {request_ip} - {vars(req)}")
|
||||||
|
|
||||||
except AllnetRequestException as e:
|
except AllnetRequestException as e:
|
||||||
self.logger.error(e)
|
if e.message != "":
|
||||||
|
self.logger.error(e)
|
||||||
return b""
|
return b""
|
||||||
|
|
||||||
if req.format_ver == 3:
|
if req.format_ver == 3:
|
||||||
@ -155,14 +160,19 @@ class AllnetServlet:
|
|||||||
def handle_dlorder(self, request: Request, _: Dict):
|
def handle_dlorder(self, request: Request, _: Dict):
|
||||||
request_ip = request.getClientAddress().host
|
request_ip = request.getClientAddress().host
|
||||||
try:
|
try:
|
||||||
req = AllnetDownloadOrderRequest(self.allnet_req_to_dict(request.content.getvalue())[0])
|
req_dict = self.allnet_req_to_dict(request.content.getvalue())
|
||||||
|
if req_dict is None:
|
||||||
|
raise AllnetRequestException()
|
||||||
|
|
||||||
|
req = AllnetDownloadOrderRequest(req_dict[0])
|
||||||
# Validate the request. Currently we only validate the fields we plan on using
|
# 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.serial:
|
if not req.game_id or not req.ver or not req.serial:
|
||||||
raise AllnetRequestException(f"Bad download request params from {request_ip} - {vars(req)}")
|
raise AllnetRequestException(f"Bad download request params from {request_ip} - {vars(req)}")
|
||||||
|
|
||||||
except AllnetRequestException as e:
|
except AllnetRequestException as e:
|
||||||
self.logger.error(e)
|
if e.message != "":
|
||||||
|
self.logger.error(e)
|
||||||
return b""
|
return b""
|
||||||
|
|
||||||
resp = AllnetDownloadOrderResponse()
|
resp = AllnetDownloadOrderResponse()
|
||||||
@ -265,7 +275,7 @@ class AllnetServlet:
|
|||||||
return self.kvp_to_dict(sections)
|
return self.kvp_to_dict(sections)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(e)
|
self.logger.error(f"billing_req_to_dict: {e} while parsing {data}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def allnet_req_to_dict(self, data: str) -> Optional[List[Dict[str, Any]]]:
|
def allnet_req_to_dict(self, data: str) -> Optional[List[Dict[str, Any]]]:
|
||||||
@ -280,7 +290,7 @@ class AllnetServlet:
|
|||||||
return self.kvp_to_dict(sections)
|
return self.kvp_to_dict(sections)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(e)
|
self.logger.error(f"allnet_req_to_dict: {e} while parsing {data}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def dict_to_http_form_string(self, data:List[Dict[str, Any]], crlf: bool = False, trailing_newline: bool = True) -> Optional[str]:
|
def dict_to_http_form_string(self, data:List[Dict[str, Any]], crlf: bool = False, trailing_newline: bool = True) -> Optional[str]:
|
||||||
@ -307,7 +317,7 @@ class AllnetServlet:
|
|||||||
return urlencode
|
return urlencode
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(e)
|
self.logger.error(f"dict_to_http_form_string: {e} while parsing {data}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
class AllnetPowerOnRequest():
|
class AllnetPowerOnRequest():
|
||||||
@ -407,6 +417,6 @@ class BillingResponse():
|
|||||||
# YYYY -> 4 digit year, MM -> 2 digit month, C -> Playcount during that period
|
# YYYY -> 4 digit year, MM -> 2 digit month, C -> Playcount during that period
|
||||||
|
|
||||||
class AllnetRequestException(Exception):
|
class AllnetRequestException(Exception):
|
||||||
def __init__(self, message="Allnet Request Error") -> None:
|
def __init__(self, message="") -> None:
|
||||||
self.message = message
|
self.message = message
|
||||||
super().__init__(self.message)
|
super().__init__(self.message)
|
||||||
|
46
index.py
46
index.py
@ -1,5 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import argparse
|
import argparse
|
||||||
|
import logging, coloredlogs
|
||||||
|
from logging.handlers import TimedRotatingFileHandler
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
import yaml
|
import yaml
|
||||||
from os import path, mkdir, access, W_OK
|
from os import path, mkdir, access, W_OK
|
||||||
@ -17,6 +19,7 @@ class HttpDispatcher(resource.Resource):
|
|||||||
self.isLeaf = True
|
self.isLeaf = True
|
||||||
self.map_get = Mapper()
|
self.map_get = Mapper()
|
||||||
self.map_post = Mapper()
|
self.map_post = Mapper()
|
||||||
|
self.logger = logging.getLogger("core")
|
||||||
|
|
||||||
self.allnet = AllnetServlet(cfg, config_dir)
|
self.allnet = AllnetServlet(cfg, config_dir)
|
||||||
self.title = TitleServlet(cfg, config_dir)
|
self.title = TitleServlet(cfg, config_dir)
|
||||||
@ -33,28 +36,36 @@ class HttpDispatcher(resource.Resource):
|
|||||||
self.map_get.connect("title_get", "/{game}/{version}/{endpoint:.*?}", controller="title", action="render_GET", conditions=dict(method=['GET']), requirements=dict(game=R"S..."))
|
self.map_get.connect("title_get", "/{game}/{version}/{endpoint:.*?}", controller="title", action="render_GET", conditions=dict(method=['GET']), requirements=dict(game=R"S..."))
|
||||||
self.map_post.connect("title_post", "/{game}/{version}/{endpoint:.*?}", controller="title", action="render_POST", conditions=dict(method=['POST']), requirements=dict(game=R"S..."))
|
self.map_post.connect("title_post", "/{game}/{version}/{endpoint:.*?}", controller="title", action="render_POST", conditions=dict(method=['POST']), requirements=dict(game=R"S..."))
|
||||||
|
|
||||||
def render_POST(self, request: Request) -> bytes:
|
def render_GET(self, request: Request) -> bytes:
|
||||||
test = self.map_get.match(request.uri.decode())
|
test = self.map_get.match(request.uri.decode())
|
||||||
if test is None:
|
if test is None:
|
||||||
return b""
|
self.logger.debug(f"Unknown GET endpoint {request.uri.decode()} from {request.getClientAddress().host} to port {request.getHost().port}")
|
||||||
|
request.setResponseCode(404)
|
||||||
|
return b"Endpoint not found."
|
||||||
|
|
||||||
return self.dispatch(test, request)
|
return self.dispatch(test, request)
|
||||||
|
|
||||||
def render_POST(self, request: Request) -> bytes:
|
def render_POST(self, request: Request) -> bytes:
|
||||||
test = self.map_post.match(request.uri.decode())
|
test = self.map_post.match(request.uri.decode())
|
||||||
if test is None:
|
if test is None:
|
||||||
return b""
|
self.logger.debug(f"Unknown POST endpoint {request.uri.decode()} from {request.getClientAddress().host} to port {request.getHost().port}")
|
||||||
|
request.setResponseCode(404)
|
||||||
|
return b"Endpoint not found."
|
||||||
|
|
||||||
return self.dispatch(test, request)
|
return self.dispatch(test, request)
|
||||||
|
|
||||||
def dispatch(self, matcher: Dict, request: Request) -> bytes:
|
def dispatch(self, matcher: Dict, request: Request) -> bytes:
|
||||||
controller = getattr(self, matcher["controller"], None)
|
controller = getattr(self, matcher["controller"], None)
|
||||||
if controller is None:
|
if controller is None:
|
||||||
return b""
|
self.logger.error(f"Controller {matcher['controller']} not found via endpoint {request.uri.decode()}")
|
||||||
|
request.setResponseCode(404)
|
||||||
|
return b"Endpoint not found."
|
||||||
|
|
||||||
handler = getattr(controller, matcher["action"], None)
|
handler = getattr(controller, matcher["action"], None)
|
||||||
if handler is None:
|
if handler is None:
|
||||||
return b""
|
self.logger.error(f"Action {matcher['action']} not found in controller {matcher['controller']} via endpoint {request.uri.decode()}")
|
||||||
|
request.setResponseCode(404)
|
||||||
|
return b"Endpoint not found."
|
||||||
|
|
||||||
url_vars = matcher
|
url_vars = matcher
|
||||||
url_vars.pop("controller")
|
url_vars.pop("controller")
|
||||||
@ -80,18 +91,37 @@ if __name__ == "__main__":
|
|||||||
cfg: CoreConfig = CoreConfig()
|
cfg: CoreConfig = CoreConfig()
|
||||||
cfg.update(yaml.safe_load(open(f"{args.config}/core.yaml")))
|
cfg.update(yaml.safe_load(open(f"{args.config}/core.yaml")))
|
||||||
|
|
||||||
|
logger = logging.getLogger("core")
|
||||||
|
if not hasattr(logger, "initialized"):
|
||||||
|
log_fmt_str = "[%(asctime)s] Core | %(levelname)s | %(message)s"
|
||||||
|
log_fmt = logging.Formatter(log_fmt_str)
|
||||||
|
|
||||||
|
fileHandler = TimedRotatingFileHandler("{0}/{1}.log".format(cfg.server.log_dir, "core"), when="d", backupCount=10)
|
||||||
|
fileHandler.setFormatter(log_fmt)
|
||||||
|
|
||||||
|
consoleHandler = logging.StreamHandler()
|
||||||
|
consoleHandler.setFormatter(log_fmt)
|
||||||
|
|
||||||
|
logger.addHandler(fileHandler)
|
||||||
|
logger.addHandler(consoleHandler)
|
||||||
|
|
||||||
|
# TODO: Add log level for core to config
|
||||||
|
logger.setLevel(cfg.allnet.loglevel)
|
||||||
|
coloredlogs.install(level=cfg.allnet.loglevel, logger=logger, fmt=log_fmt_str)
|
||||||
|
logger.initialized = True
|
||||||
|
|
||||||
if not path.exists(cfg.server.log_dir):
|
if not path.exists(cfg.server.log_dir):
|
||||||
mkdir(cfg.server.log_dir)
|
mkdir(cfg.server.log_dir)
|
||||||
|
|
||||||
if not access(cfg.server.log_dir, W_OK):
|
if not access(cfg.server.log_dir, W_OK):
|
||||||
print(f"Log directory {cfg.server.log_dir} NOT writable, please check permissions")
|
logger.error(f"Log directory {cfg.server.log_dir} NOT writable, please check permissions")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
if not cfg.aimedb.key:
|
if not cfg.aimedb.key:
|
||||||
print("!!AIMEDB KEY BLANK, SET KEY IN CORE.YAML!!")
|
logger.error("!!AIMEDB KEY BLANK, SET KEY IN CORE.YAML!!")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
print(f"ARTEMiS starting in {'develop' if cfg.server.is_develop else 'production'} mode")
|
logger.info(f"ARTEMiS starting in {'develop' if cfg.server.is_develop else 'production'} mode")
|
||||||
|
|
||||||
allnet_server_str = f"tcp:{cfg.allnet.port}:interface={cfg.server.listen_address}"
|
allnet_server_str = f"tcp:{cfg.allnet.port}:interface={cfg.server.listen_address}"
|
||||||
title_server_str = f"tcp:{cfg.title.port}:interface={cfg.server.listen_address}"
|
title_server_str = f"tcp:{cfg.title.port}:interface={cfg.server.listen_address}"
|
||||||
|
Loading…
Reference in New Issue
Block a user