Added api functions for implementing protocols sending out-of-band data between server and portal (e.g. like GMCP)

This commit is contained in:
Griatch 2011-11-08 22:54:02 +01:00
parent 3e8b43d222
commit bced571805
6 changed files with 164 additions and 16 deletions

View file

@ -34,10 +34,6 @@ SERVER_RESTART = os.path.join(settings.GAME_DIR, "server.restart")
# i18n
from django.utils.translation import ugettext as _
# Signals
def get_restart_mode(restart_file):
"""
@ -141,6 +137,24 @@ class MsgServer2Portal(amp.Command):
errors = [(Exception, 'EXCEPTION')]
response = []
class OOBPortal2Server(amp.Command):
"""
OOB data portal -> server
"""
arguments = [('sessid', amp.Integer()),
('data', amp.String())]
errors = [(Exception, "EXCEPTION")]
response = []
class OOBServer2Portal(amp.Command):
"""
OOB data server -> portal
"""
arguments = [('sessid', amp.Integer()),
('data', amp.String())]
errors = [(Exception, "EXCEPTION")]
response = []
class ServerAdmin(amp.Command):
"""
Portal -> Server
@ -168,6 +182,8 @@ class PortalAdmin(amp.Command):
errors = [(Exception, 'EXCEPTION')]
response = []
dumps = lambda data: utils.to_str(pickle.dumps(data, pickle.HIGHEST_PROTOCOL))
loads = lambda data: pickle.loads(utils.to_str(data))
#------------------------------------------------------------
# Core AMP protocol for communication Server <-> Portal
@ -220,7 +236,7 @@ class AMPProtocol(amp.AMP):
Relays message to server. This method is executed on the Server.
"""
#print "msg portal -> server (server side):", sessid, msg
self.factory.server.sessions.data_in(sessid, msg, pickle.loads(utils.to_str(data)))
self.factory.server.sessions.data_in(sessid, msg, loads(data))
return {}
MsgPortal2Server.responder(amp_msg_portal2server)
@ -232,7 +248,7 @@ class AMPProtocol(amp.AMP):
self.callRemote(MsgPortal2Server,
sessid=sessid,
msg=msg,
data=utils.to_str(pickle.dumps(data))).addErrback(self.errback, "MsgPortal2Server")
data=dumps(data)).addErrback(self.errback, "MsgPortal2Server")
# Server -> Portal message
@ -241,7 +257,7 @@ class AMPProtocol(amp.AMP):
Relays message to Portal. This method is executed on the Portal.
"""
#print "msg server->portal (portal side):", sessid, msg
self.factory.portal.sessions.data_out(sessid, msg, pickle.loads(utils.to_str(data)))
self.factory.portal.sessions.data_out(sessid, msg, loads(data))
return {}
MsgServer2Portal.responder(amp_msg_server2portal)
@ -253,8 +269,50 @@ class AMPProtocol(amp.AMP):
self.callRemote(MsgServer2Portal,
sessid=sessid,
msg=utils.to_str(msg),
data=utils.to_str(pickle.dumps(data))).addErrback(self.errback, "MsgServer2Portal")
data=dumps(data)).addErrback(self.errback, "OOBServer2Portal")
# OOB Portal -> Server
# Portal -> Server Msg
def amp_oob_portal2server(self, sessid, data):
"""
Relays out-of-band data to server. This method is executed on the Server.
"""
#print "oob portal -> server (server side):", sessid, loads(data)
self.factory.server.sessions.oob_data_in(sessid, loads(data))
return {}
OOBPortal2Server.responder(amp_oob_portal2server)
def call_remote_OOBPortal2Server(self, sessid, data=""):
"""
Access method called by the Portal and executed on the Portal.
"""
#print "oob portal->server (portal side):", sessid, data
self.callRemote(OOBPortal2Server,
sessid=sessid,
data=dumps(data)).addErrback(self.errback, "OOBPortal2Server")
# Server -> Portal message
def amp_oob_server2portal(self, sessid, data):
"""
Relays out-of-band data to Portal. This method is executed on the Portal.
"""
#print "oob server->portal (portal side):", sessid, data
self.factory.portal.sessions.oob_data_out(sessid, loads(data))
return {}
OOBServer2Portal.responder(amp_oob_server2portal)
def call_remote_OOBServer2Portal(self, sessid, data=""):
"""
Access method called by the Server and executed on the Server.
"""
#print "oob server->portal (server side):", sessid, data
self.callRemote(OOBServer2Portal,
sessid=sessid,
data=dumps(data)).addErrback(self.errback, "OOBServer2Portal")
# Server administration from the Portal side
@ -264,7 +322,7 @@ class AMPProtocol(amp.AMP):
operations on the server. This is executed on the Server.
"""
data = pickle.loads(utils.to_str(data))
data = loads(data)
#print "serveradmin (server side):", sessid, operation, data
@ -315,7 +373,7 @@ class AMPProtocol(amp.AMP):
Access method called by the Portal and Executed on the Portal.
"""
#print "serveradmin (portal side):", sessid, operation, data
data = utils.to_str(pickle.dumps(data))
data = dumps(data)
self.callRemote(ServerAdmin,
sessid=sessid,
@ -329,7 +387,7 @@ class AMPProtocol(amp.AMP):
This allows the server to perform admin
operations on the portal. This is executed on the Portal.
"""
data = pickle.loads(utils.to_str(data))
data = loads(data)
#print "portaladmin (portal side):", sessid, operation, data
if operation == 'SLOGIN': # 'server_session_login'
@ -376,7 +434,7 @@ class AMPProtocol(amp.AMP):
Access method called by the server side.
"""
#print "portaladmin (server side):", sessid, operation, data
data = utils.to_str(pickle.dumps(data))
data = dumps(data)
self.callRemote(PortalAdmin,
sessid=sessid,

View file

@ -12,12 +12,16 @@ from datetime import datetime
from django.conf import settings
from src.scripts.models import ScriptDB
from src.comms.models import Channel
from src.utils import logger
from src.utils import logger, utils
from src.commands import cmdhandler, cmdsethandler
from src.server.session import Session
IDLE_COMMAND = settings.IDLE_COMMAND
from src.server.session import Session
# load optional out-of-band function module
OOB_FUNC_MODULE = settings.OOB_FUNC_MODULE
if OOB_FUNC_MODULE:
OOB_FUNC_MODULE = utils.mod_import(settings.OOB_FUNC_MODULE)
# i18n
from django.utils.translation import ugettext as _
@ -208,6 +212,44 @@ class ServerSession(Session):
"""
self.sessionhandler.data_out(self, msg, data)
def oob_data_in(self, data):
"""
This receives out-of-band data from the Portal.
This method parses the data input (a dict) and uses
it to launch correct methods from those plugged into
the system.
data = {funcname: ( [args], {kwargs]),
funcname: ( [args], {kwargs}), ...}
example:
data = {"get_hp": ([], {}),
"update_counter", (["counter1"], {"now":True}) }
"""
print "server: "
outdata = {}
for funcname, argtuple in data.items():
# loop through the data, calling available functions.
func = OOB_FUNC_MODULE.__dict__.get(funcname, None)
if func:
outdata[funcname] = func(*argtuple[0], **argtuple[1])
else:
logger.log_errmsg("oob_data_in error: funcname '%s' not found in OOB_FUNC_MODULE." % funcname)
if outdata:
self.oob_data_out(outdata)
def oob_data_out(self, data):
"""
This sends data from Server to the Portal across the AMP connection.
"""
self.sessionhandler.oob_data_out(self, data)
def __eq__(self, other):
return self.address == other.address

View file

@ -123,3 +123,20 @@ class Session(object):
"""
pass
def oob_data_out(self, data):
"""
for Portal, this receives out-of-band data from Server across the AMP.
for Server, this sends out-of-band data to Portal.
data is a dictionary
"""
pass
def oob_data_in(self, data):
"""
for Portal, this sends out-of-band requests to Server over the AMP.
for Server, this receives data from Portal.
data is a dictionary
"""
pass

View file

@ -295,6 +295,20 @@ class ServerSessionHandler(SessionHandler):
# to put custom effects on the server due to data input, e.g.
# from a custom client.
def oob_data_in(self, sessid, data):
"""
OOB (Out-of-band) Data Portal -> Server
"""
session = self.sessions.get(sessid, None)
if session:
session.oob_data_in(data)
def oob_data_out(self, session, data):
"""
OOB (Out-of-band) Data Server -> Portal
"""
self.server.amp_protocol.call_remote_OOBServer2Portal(session.sessid,
data=data)
#------------------------------------------------------------
# Portal-SessionHandler class
@ -392,5 +406,20 @@ class PortalSessionHandler(SessionHandler):
if session:
session.data_out(string, data=data)
def oob_data_in(self, session, data):
"""
OOB (Out-of-band) data Portal -> Server
"""
self.portal.amp_protocol.call_remote_OOBPortal2Server(session.sessid,
data=data)
def oob_data_out(self, sessid, data):
"""
OOB (Out-of-band) data Server -> Portal
"""
session = self.sessions.get(sessid, None)
if session:
session.oob_data_out(data)
SESSIONS = ServerSessionHandler()
PORTAL_SESSIONS = PortalSessionHandler()

View file

@ -253,6 +253,8 @@ PERMISSION_PLAYER_DEFAULT = "Players"
# Tuple of modules implementing lock functions. All callable functions
# inside these modules will be available as lock functions.
LOCK_FUNC_MODULES = ("src.locks.lockfuncs",)
# Module holding server-side functions for out-of-band protocols to call.
OOB_FUNC_MODULE = ""
###################################################

View file

@ -542,7 +542,7 @@ def has_parent(basepath, obj):
def mod_import(mod_path, propname=None):
"""
Takes filename of a module, converts it to a python path
Takes filename of a module (a python path or a full pathname)
and imports it. If property is given, return the named
property from this module instead of the module itself.
"""