diff --git a/dsst/common/util.py b/dsst/common/util.py index 903be04..8c52538 100644 --- a/dsst/common/util.py +++ b/dsst/common/util.py @@ -25,4 +25,8 @@ def recvall(sock, n): if not packet: return None data += packet - return data \ No newline at end of file + return data + + +def list_class_methods(class_obj): + return [name for name in dir(class_obj) if not name.startswith('__')] diff --git a/dsst/dsst_client/client.py b/dsst/dsst_client/client.py deleted file mode 100644 index 45db76c..0000000 --- a/dsst/dsst_client/client.py +++ /dev/null @@ -1,28 +0,0 @@ -import socket - -try: - import cPickcle as pickle -except ImportError: - print('cPickle package not installed, falling back to pickle') - import pickle - -from common import util, models - -PORT = 12345 -HOST = 'europa' -BUFFER_SIZE = 1024 - -s = socket.socket() -s.connect((HOST, PORT)) - -try: - data = 'get_dummy' - message = pickle.dumps(data) - util.send_msg(s, message) - response = util.recv_msg(s) - result = pickle.loads(response) - print(result, result.__dict__) - -finally: - s.close() - diff --git a/dsst/dsst_client/dsst_gtk3/handlers/__init__.py b/dsst/dsst_client/dsst_gtk3/handlers/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/dsst/dsst_client/__init__.py b/dsst/dsst_gtk3/__init__.py similarity index 100% rename from dsst/dsst_client/__init__.py rename to dsst/dsst_gtk3/__init__.py diff --git a/dsst/dsst_gtk3/client.py b/dsst/dsst_gtk3/client.py new file mode 100644 index 0000000..d024914 --- /dev/null +++ b/dsst/dsst_gtk3/client.py @@ -0,0 +1,40 @@ +import pprint +import socket +from common import util, models +try: + import cPickle as pickle +except ImportError: + import pickle + + +class Access: + def __init__(self, connection): + self.host = connection.get('host') + self.port = connection.get('port') + self.buffer = connection.get('buffer_size') + self.auth_key = connection.get('auth_key') + self.socket = socket.socket() + + def send_request(self, action: str, *args): + request = {'auth_key': self.auth_key, + 'action': action, + 'args': args} + request = pickle.dumps(request) + try: + self.socket.connect((self.host, self.port)) + util.send_msg(self.socket, request) + response = util.recv_msg(self.socket) + response = pickle.loads(response) + if not response.get('success'): + raise Exception(response.get('message')) + finally: + self.socket.close() + return response.get('data') + +if __name__ == '__main__': + access = Access({'host': 'europa', 'port': 12345, 'buffer_size': 1024, 'auth_key': 'a'}) + action = 'load_seasons' + response = access.send_request(action) + pp = pprint.PrettyPrinter(indent=1) + for s in response: + pp.pprint(s.__dict__) diff --git a/dsst/dsst_client/dsst_gtk3/dialogs.py b/dsst/dsst_gtk3/dialogs.py similarity index 100% rename from dsst/dsst_client/dsst_gtk3/dialogs.py rename to dsst/dsst_gtk3/dialogs.py diff --git a/dsst/dsst_client/dsst_gtk3/gtk_ui.py b/dsst/dsst_gtk3/gtk_ui.py similarity index 100% rename from dsst/dsst_client/dsst_gtk3/gtk_ui.py rename to dsst/dsst_gtk3/gtk_ui.py diff --git a/dsst/dsst_client/dsst_gtk3/__init__.py b/dsst/dsst_gtk3/handlers/__init__.py similarity index 100% rename from dsst/dsst_client/dsst_gtk3/__init__.py rename to dsst/dsst_gtk3/handlers/__init__.py diff --git a/dsst/dsst_client/dsst_gtk3/handlers/base_data_handlers.py b/dsst/dsst_gtk3/handlers/base_data_handlers.py similarity index 100% rename from dsst/dsst_client/dsst_gtk3/handlers/base_data_handlers.py rename to dsst/dsst_gtk3/handlers/base_data_handlers.py diff --git a/dsst/dsst_client/dsst_gtk3/handlers/death_handlers.py b/dsst/dsst_gtk3/handlers/death_handlers.py similarity index 100% rename from dsst/dsst_client/dsst_gtk3/handlers/death_handlers.py rename to dsst/dsst_gtk3/handlers/death_handlers.py diff --git a/dsst/dsst_client/dsst_gtk3/handlers/dialog_handlers.py b/dsst/dsst_gtk3/handlers/dialog_handlers.py similarity index 100% rename from dsst/dsst_client/dsst_gtk3/handlers/dialog_handlers.py rename to dsst/dsst_gtk3/handlers/dialog_handlers.py diff --git a/dsst/dsst_client/dsst_gtk3/handlers/handlers.py b/dsst/dsst_gtk3/handlers/handlers.py similarity index 100% rename from dsst/dsst_client/dsst_gtk3/handlers/handlers.py rename to dsst/dsst_gtk3/handlers/handlers.py diff --git a/dsst/dsst_client/dsst_gtk3/handlers/season_handlers.py b/dsst/dsst_gtk3/handlers/season_handlers.py similarity index 100% rename from dsst/dsst_client/dsst_gtk3/handlers/season_handlers.py rename to dsst/dsst_gtk3/handlers/season_handlers.py diff --git a/dsst/dsst_client/dsst_gtk3/handlers/victory_handlers.py b/dsst/dsst_gtk3/handlers/victory_handlers.py similarity index 100% rename from dsst/dsst_client/dsst_gtk3/handlers/victory_handlers.py rename to dsst/dsst_gtk3/handlers/victory_handlers.py diff --git a/dsst/dsst_client/dsst_gtk3/reload.py b/dsst/dsst_gtk3/reload.py similarity index 100% rename from dsst/dsst_client/dsst_gtk3/reload.py rename to dsst/dsst_gtk3/reload.py diff --git a/dsst/dsst_client/dsst_gtk3/resources/glade/dialogs.glade b/dsst/dsst_gtk3/resources/glade/dialogs.glade similarity index 100% rename from dsst/dsst_client/dsst_gtk3/resources/glade/dialogs.glade rename to dsst/dsst_gtk3/resources/glade/dialogs.glade diff --git a/dsst/dsst_client/dsst_gtk3/resources/glade/window.glade b/dsst/dsst_gtk3/resources/glade/window.glade similarity index 100% rename from dsst/dsst_client/dsst_gtk3/resources/glade/window.glade rename to dsst/dsst_gtk3/resources/glade/window.glade diff --git a/dsst/dsst_client/dsst_gtk3/util.py b/dsst/dsst_gtk3/util.py similarity index 100% rename from dsst/dsst_client/dsst_gtk3/util.py rename to dsst/dsst_gtk3/util.py diff --git a/dsst/dsst_server/data_access/mapping.py b/dsst/dsst_server/data_access/mapping.py new file mode 100644 index 0000000..0c724ad --- /dev/null +++ b/dsst/dsst_server/data_access/mapping.py @@ -0,0 +1,33 @@ +from dsst_server.data_access import sql +from common import models + + +def map_base_fields(cls, db_model): + model = cls() + attrs = [attr for attr in db_model._meta.fields] + for attr in attrs: + setattr(model, attr, getattr(db_model, attr)) + return model + + +def db_to_enemy(enemy: 'sql.Enemy'): + return map_base_fields(models.Enemy, enemy) + + +def db_to_player(player: 'sql.Player'): + model = map_base_fields(models.Player, player) + return model + + +def db_to_episode(episode: 'sql.Episode'): + model = map_base_fields(models.Episode, episode) + model.players = [db_to_player(player) for player in episode.players] + model.deaths = [] + model.victories = [] + + +def db_to_season(season: 'sql.Season'): + model = map_base_fields(models.Season, season) + model.enemies = [db_to_enemy(enemy) for enemy in season.enemies] + model.episodes = [db_to_episode(ep) for ep in season.episodes] + return model diff --git a/dsst/dsst_server/func_proxy.py b/dsst/dsst_server/func_proxy.py new file mode 100644 index 0000000..754ca0d --- /dev/null +++ b/dsst/dsst_server/func_proxy.py @@ -0,0 +1,6 @@ +from dsst_server.write_functions import WriteFunctions +from dsst_server.read_functions import ReadFunctions + + +class FunctionProxy(WriteFunctions, ReadFunctions): + pass diff --git a/dsst/dsst_server/read_functions.py b/dsst/dsst_server/read_functions.py new file mode 100644 index 0000000..e7c5187 --- /dev/null +++ b/dsst/dsst_server/read_functions.py @@ -0,0 +1,19 @@ +from dsst_server.data_access import sql, sql_func, mapping +from common import models +from playhouse import shortcuts + + +class ReadFunctions: + + @staticmethod + def load_seasons(*_): + return [mapping.db_to_season(season) for season in sql.Season.select()] + + @staticmethod + def load_seasons_all(*_): + return [shortcuts.model_to_dict(season, backrefs=True, max_depth=2) for season in sql.Season.select()] + + @staticmethod + def load_players(*_): + return [mapping.db_to_player(player) for player in sql.Player.select()] + diff --git a/dsst/dsst_server/server.py b/dsst/dsst_server/server.py index 1802df1..1eb5a3d 100644 --- a/dsst/dsst_server/server.py +++ b/dsst/dsst_server/server.py @@ -1,8 +1,14 @@ import pickle import socket -from data_access import sql +import sys + +import os + from common import util, models +from dsst_server import read_functions, write_functions +from dsst_server.func_proxy import FunctionProxy +from dsst_server.data_access import sql PORT = 12345 HOST = socket.gethostname() @@ -17,6 +23,13 @@ class DsstServer: self.socket_server.bind((HOST, PORT)) print(f'Bound socket to {PORT} on host {HOST}') + self.read_actions = util.list_class_methods(read_functions.ReadFunctions) + self.write_actions = util.list_class_methods(write_functions.WriteFunctions) + sql.db.init('dsst', user='dsst', password='dsst') + + self.key_access = {'a': self.read_actions, + 'b': self.read_actions + self.write_actions} + def run(self): self.socket_server.listen(5) print('Socket is listening') @@ -27,16 +40,39 @@ class DsstServer: print(f'Connection from {address}') data = util.recv_msg(client) request = pickle.loads(data) - print(f'Received data: {request}') - dummy = models.Player() - dummy.name = 'Player 1' - dummy.hex_id = '0xC2' - dummy.deaths = [1, 2, 3] - util.send_msg(client, pickle.dumps(dummy)) + print(f'Request: {request}') + # Validate auth key in request + key = request.get('auth_key') + if key not in self.key_access: + util.send_msg(client, pickle.dumps({'success': False, 'message': 'Auth Key invalid'})) + print(f'Rejected request from {address}. Auth key invalid ({key})') + continue + # Check read functions + action_name = request.get('action') + if action_name in self.key_access[key]: + action = getattr(FunctionProxy, action_name) + value = action(request.get('args')) + response = {'success': True, 'data': value} + util.send_msg(client, pickle.dumps(response)) + continue + else: + msg = f'Action does not exist on server ({request.get("action")})' + util.send_msg(client, pickle.dumps({'success': False, 'message': msg})) + except Exception as e: + print(e) finally: client.close() print('Connection to client closed') + if __name__ == '__main__': server = DsstServer() - server.run() + try: + server.run() + except KeyboardInterrupt: + print('Server stopped') + server.socket_server.close() + try: + sys.exit(0) + except SystemExit: + os._exit(0) diff --git a/dsst/dsst_server/write_functions.py b/dsst/dsst_server/write_functions.py new file mode 100644 index 0000000..ea27bdf --- /dev/null +++ b/dsst/dsst_server/write_functions.py @@ -0,0 +1,8 @@ +from common import models + + +class WriteFunctions: + + @staticmethod + def create_season(season: 'models.Season'): + return 'Season created.'