syntaxwebsite/app/services/gameserver_comm.py

117 lines
3.9 KiB
Python

import requests
import time
import base64
import json
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from app.models.gameservers import GameServer
from config import Config
config = Config()
def sign_content( content : bytes ) -> str:
"""
Signs the given content using the gameserver private key
:param content: The content to sign
:returns: str
"""
assert isinstance( content, bytes ), "content must be a bytes object"
with open( config.GAMESERVER_COMM_PRIVATE_KEY_LOCATION, "rb" ) as f:
private_key = serialization.load_pem_private_key(
f.read(),
password=None,
backend=default_backend()
)
signature = private_key.sign(
content,
padding.PKCS1v15(),
hashes.SHA256()
)
return base64.b64encode( signature ).decode( "utf-8" )
def perform_get(
TargetGameserver : GameServer,
Endpoint : str,
AdditionalHeaders : dict = {},
RequestTimeout : int = 10
) -> requests.Response:
"""
Performs a GET request to the given gameserver
:param TargetGameserver: The gameserver to send the request to
:param Endpoint: The endpoint to send the request to
:param AdditionalHeaders: Additional headers to send with the request
:param RequestTimeout: The amount of time before the request times out
:returns: requests.Response
"""
assert isinstance( TargetGameserver, GameServer ), "TargetGameserver must be an instance of GameServer"
assert isinstance( Endpoint, str ), "Endpoint must be a string"
assert isinstance( AdditionalHeaders, dict ), "AdditionalHeaders must be a dictionary"
RequestTimestamp = time.time()
signed_content = sign_content( f'{RequestTimestamp}\nGET'.encode( 'utf-8' ) )
ReqSignature = f"{str(RequestTimestamp)}|{ signed_content }"
headers = {
"User-Agent": "SYNTAX-Gameserver-Communication/1.0",
"X-Syntax-Request-Signature": ReqSignature
}
return requests.get(
url = f"http://{TargetGameserver.serverIP}:{TargetGameserver.serverPort}/{Endpoint}",
headers = headers,
timeout = RequestTimeout
)
def perform_post(
TargetGameserver : GameServer,
Endpoint : str,
JSONData : dict | list = {},
AdditionalHeaders : dict = {},
RequestTimeout : int = 10
) -> requests.Response:
"""
Performs a POST request to the given gameserver
:param TargetGameserver: The gameserver to send the request to
:param Endpoint: The endpoint to send the request to
:param JSONData: The JSON data to send with the request
:param AdditionalHeaders: Additional headers to send with the request
:param RequestTimeout: The amount of time before the request times out
:returns: requests.Response
"""
assert isinstance( TargetGameserver, GameServer ), "TargetGameserver must be an instance of GameServer"
assert isinstance( Endpoint, str ), "Endpoint must be a string"
assert isinstance( JSONData, ( dict, list ) ), "JSONData must be a dictionary or list"
assert isinstance( AdditionalHeaders, dict ), "AdditionalHeaders must be a dictionary"
RequestTimestamp = time.time()
signed_content = sign_content( f"{RequestTimestamp}\nPOST\n{json.dumps(JSONData)}".encode( "utf-8" ))
ReqSignature = f"{str(RequestTimestamp)}|{signed_content}"
headers = {
"User-Agent": "SYNTAX-Gameserver-Communication/1.0",
"X-Syntax-Request-Signature": ReqSignature,
"Content-Type": "application/json"
}
headers.update( AdditionalHeaders )
return requests.post(
url = f"http://{TargetGameserver.serverIP}:{TargetGameserver.serverPort}/{Endpoint}",
headers = headers,
data = json.dumps( JSONData ),
timeout = RequestTimeout
)