From a0a205c945ef4dd6efd3f585624a314110c67e32 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 25 Feb 2012 21:14:48 +0100 Subject: [PATCH] Did some additions to the MSDP implementation. Added a first test for implementing MSDP commands, but it is not working yet. --- src/server/msdp.py | 74 ++++++++++++++++++++++++++++++++++-- src/server/sessionhandler.py | 2 +- src/utils/utils.py | 6 +++ 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/src/server/msdp.py b/src/server/msdp.py index 9241ccb128..3cf36ded2d 100644 --- a/src/server/msdp.py +++ b/src/server/msdp.py @@ -11,6 +11,7 @@ etc. """ import re +from src.utils.utils import make_iter # variables MSDP = chr(69) @@ -112,22 +113,89 @@ class Msdp(object): arrays[array[0]] = dict(regex_varval(array[1])) variables = dict(regex._varval(regex_array.sub("", regex_table.sub("", data)))) + + + # MSDP Commands # Some given MSDP (varname, value) pairs can also be treated as command + argument. # Generic msdp command map. The argument will be sent to the given command. # See http://tintin.sourceforge.net/msdp/ for definitions of each command. + # These are client->server commands. + def msdp_cmd_list(self, arg): + """ + The List command allows for retrieving various info about the server/client + """ + if arg == 'COMMANDS': + return self.func_to_msdp(arg, MSDP_COMMANDS.keys()) + elif arg == 'LISTS': + return self.func_to_msdp(arg, ("COMMANDS", "LISTS", + "CONFIGURABLE_VARIABLES", + "REPORTED_VARIABLES", "SENDABLE_VARIABLES")) + elif arg == 'CONFIGURABLE_VARIABLES': + return self.func_to_msdp(arg, ("CLIENT_NAME", "CLIENT_VERSION", "PLUGIN_ID")) + elif arg == 'REPORTABLE_VARIABLES': + return self.func_to_msdp(arg, MSDP_REPORTABLE.keys()) + elif arg == 'REPORTED_VARIABLES': + return self.func_to_msdp(arg, MSDP_REPORTED.keys()) + elif arg == 'SENDABLE_VARIABLES': + return self.func_to_msdp(arg, MSDP_SEND.keys()) + else: + return self.func_to_msdp("LIST", arg) + + def msdp_cmd_report(self, arg): + """ + The report command instructs the server to start reporting a + reportable variable to the client. + """ + try: + MSDP_REPORTABLE[arg](report=True) + except Exception: + logger.log_trace() + + def msdp_cmd_unreport(self, arg): + """ + Unreport a previously reported variable + """ + try: + MSDP_REPORTABLE[arg](eport=False) + except Exception: + logger.log_trace() + + def msdp_cmd_reset(self, arg): + """ + The reset command resets a variable to its initial state. + """ + try: + MSDP_REPORTABLE[arg](reset=True) + except Exception: + logger.log_trace() + + def msdp_cmd_send(self, arg): + """ + Request the server to send a particular variable + to the client. + + arg - this is a list of variables the client wants. + """ + ret = [] + for var in makeiter(arg): + try: + ret.append(MSDP_REPORTABLE[arg](send=True)) + except Exception: + logger.log_trace() + return ret + MSDP_COMMANDS = { - "LIST": "msdp_list", + "LIST": self.msdp_list, "REPORT":"mspd_report", "RESET":"mspd_reset", "SEND":"mspd_send", "UNREPORT":"mspd_unreport" } - # MSDP_MAP is a standard suggestions for making it easy to create generic guis. # this maps MSDP command names to Evennia commands found in OOB_FUNC_MODULE. It # is up to these commands to return data on proper form. - MSDP_MAP = { + MSDP_REPORTABLE = { # General "CHARACTER_NAME": "get_character_name", "SERVER_ID": "get_server_id", diff --git a/src/server/sessionhandler.py b/src/server/sessionhandler.py index 3821af524b..45d9ce4043 100644 --- a/src/server/sessionhandler.py +++ b/src/server/sessionhandler.py @@ -221,7 +221,7 @@ class ServerSessionHandler(SessionHandler): and see if any are dead. """ tcurr = time.time() - reason= _("Idle timeout exceeded, disconnecting.")) + reason= _("Idle timeout exceeded, disconnecting.")2 for session in (session for session in self.sessions.values() if session.logged_in and IDLE_TIMEOUT > 0 and (tcurr - session.cmd_last) > IDLE_TIMEOUT): diff --git a/src/utils/utils.py b/src/utils/utils.py index bd0b13ca8a..7e2e8b0083 100644 --- a/src/utils/utils.py +++ b/src/utils/utils.py @@ -24,6 +24,12 @@ def is_iter(iterable): """ return hasattr(iterable, '__iter__') +def make_iter(obj): + "Makes sure that the object is always iterable." + if not hasattr(iterable, '__iter__'): + return [obj] + return obj + def fill(text, width=78, indent=0): """ Safely wrap text to a certain number of characters.