Fix merge conflicts

This commit is contained in:
Griatch 2017-03-19 18:10:06 +01:00
commit 08670008ad
9 changed files with 111 additions and 107 deletions

View file

@ -7,7 +7,7 @@ The separation works like this:
Portal - (AMP client) handles protocols. It contains a list of connected
sessions in a dictionary for identifying the respective player
connected. If it looses the AMP connection it will automatically
connected. If it loses the AMP connection it will automatically
try to reconnect.
Server - (AMP server) Handles all mud operations. The server holds its own list
@ -32,33 +32,33 @@ from twisted.internet import protocol
from twisted.internet.defer import Deferred
from evennia.utils import logger
from evennia.utils.utils import to_str, variable_from_module
import zlib # Used in Compressed class
DUMMYSESSION = namedtuple('DummySession', ['sessid'])(0)
# communication bits
# (chr(9) and chr(10) are \t and \n, so skipping them)
PCONN = chr(1) # portal session connect
PDISCONN = chr(2) # portal session disconnect
PSYNC = chr(3) # portal session sync
SLOGIN = chr(4) # server session login
SDISCONN = chr(5) # server session disconnect
SDISCONNALL = chr(6) # server session disconnect all
SSHUTD = chr(7) # server shutdown
SSYNC = chr(8) # server session sync
PCONN = chr(1) # portal session connect
PDISCONN = chr(2) # portal session disconnect
PSYNC = chr(3) # portal session sync
SLOGIN = chr(4) # server session login
SDISCONN = chr(5) # server session disconnect
SDISCONNALL = chr(6) # server session disconnect all
SSHUTD = chr(7) # server shutdown
SSYNC = chr(8) # server session sync
SCONN = chr(11) # server creating new connection (for irc bots and etc)
PCONNSYNC = chr(12) # portal post-syncing a session
PDISCONNALL = chr(13) # portal session disconnect all
PCONNSYNC = chr(12) # portal post-syncing a session
PDISCONNALL = chr(13) # portal session disconnect all
AMP_MAXLEN = amp.MAX_VALUE_LENGTH # max allowed data length in AMP protocol (cannot be changed)
BATCH_RATE = 250 # max commands/sec before switching to batch-sending
BATCH_TIMEOUT = 0.5 # how often to poll to empty batch queue, in seconds
BATCH_RATE = 250 # max commands/sec before switching to batch-sending
BATCH_TIMEOUT = 0.5 # how often to poll to empty batch queue, in seconds
# buffers
_SENDBATCH = defaultdict(list)
_MSGBUFFER = defaultdict(list)
import zlib
def get_restart_mode(restart_file):
"""
@ -323,9 +323,9 @@ dumps = lambda data: to_str(pickle.dumps(to_str(data), pickle.HIGHEST_PROTOCOL))
loads = lambda data: pickle.loads(to_str(data))
#------------------------------------------------------------
# -------------------------------------------------------------
# Core AMP protocol for communication Server <-> Portal
#------------------------------------------------------------
# -------------------------------------------------------------
class AMPProtocol(amp.AMP):
"""
@ -385,7 +385,6 @@ class AMPProtocol(amp.AMP):
"""
pass
# Error handling
def errback(self, e, info):
@ -447,7 +446,7 @@ class AMPProtocol(amp.AMP):
Access method called by the Portal and executed on the Portal.
Args:
sessid (int): Unique Session id.
session (session): Session
kwargs (any, optional): Optional data.
Returns:
@ -473,7 +472,6 @@ class AMPProtocol(amp.AMP):
self.factory.portal.sessions.data_out(session, **kwargs)
return {}
def send_MsgServer2Portal(self, session, **kwargs):
"""
Access method - executed on the Server for sending data
@ -506,7 +504,7 @@ class AMPProtocol(amp.AMP):
# create a new session and sync it
server_sessionhandler.portal_connect(kwargs.get("sessiondata"))
elif operation == PCONNSYNC: #portal_session_sync
elif operation == PCONNSYNC: # portal_session_sync
server_sessionhandler.portal_session_sync(kwargs.get("sessiondata"))
elif operation == PDISCONN: # portal_session_disconnect
@ -515,7 +513,7 @@ class AMPProtocol(amp.AMP):
if session:
server_sessionhandler.portal_disconnect(session)
elif operation == PDISCONNALL: # portal_disconnect_all
elif operation == PDISCONNALL: # portal_disconnect_all
# portal orders all sessions to close
server_sessionhandler.portal_disconnect_all()
@ -545,7 +543,7 @@ class AMPProtocol(amp.AMP):
"""
return self.send_data(AdminPortal2Server, session.sessid, operation=operation, **kwargs)
# Portal administraton from the Server side
# Portal administration from the Server side
@AdminServer2Portal.responder
def portal_receive_adminserver2portal(self, packed_data):
@ -562,7 +560,6 @@ class AMPProtocol(amp.AMP):
operation = kwargs.pop("operation")
portal_sessionhandler = self.factory.portal.sessions
if operation == SLOGIN: # server_session_login
# a session has authenticated; sync it.
session = portal_sessionhandler.get(sessid)
@ -591,7 +588,7 @@ class AMPProtocol(amp.AMP):
# set a flag in case we are about to shut down soon
self.factory.server_restart_mode = True
elif operation == SCONN: # server_force_connection (for irc/etc)
elif operation == SCONN: # server_force_connection (for irc/etc)
portal_sessionhandler.server_connect(**kwargs)
else:
@ -665,4 +662,5 @@ class AMPProtocol(amp.AMP):
module=modulepath,
function=functionname,
args=dumps(args),
kwargs=dumps(kwargs)).addCallback(lambda r: loads(r["result"])).addErrback(self.errback, "FunctionCall")
kwargs=dumps(kwargs)).addCallback(
lambda r: loads(r["result"])).addErrback(self.errback, "FunctionCall")

View file

@ -198,7 +198,7 @@ class IRCBot(irc.IRCClient, Session):
logger.log_info("IRC bot '%s' connected to %s at %s:%s." % (self.nickname, self.channel,
self.network, self.port))
def disconnect(self, reason=None):
def disconnect(self, reason=""):
"""
Called by sessionhandler to disconnect this protocol.
@ -206,7 +206,7 @@ class IRCBot(irc.IRCClient, Session):
reason (str): Motivation for the disconnect.
"""
self.sessionhandler.disconnect(self)
self.sessionhandler.disconnect(self, reason=reason)
self.stopping = True
self.transport.loseConnection()

View file

@ -37,9 +37,9 @@ if os.name == 'nt':
# For Windows we need to handle pid files manually.
PORTAL_PIDFILE = os.path.join(settings.GAME_DIR, "server", 'portal.pid')
#------------------------------------------------------------
# -------------------------------------------------------------
# Evennia Portal settings
#------------------------------------------------------------
# -------------------------------------------------------------
VERSION = get_evennia_version()
@ -76,6 +76,8 @@ AMP_ENABLED = AMP_HOST and AMP_PORT and AMP_INTERFACE
# Maintenance function - this is called repeatedly by the portal.
_IDLE_TIMEOUT = settings.IDLE_TIMEOUT
def _portal_maintenance():
"""
The maintenance function handles repeated checks and updates that
@ -94,12 +96,12 @@ def _portal_maintenance():
if _IDLE_TIMEOUT > 0:
# only start the maintenance task if we care about idling.
_maintenance_task = LoopingCall(_portal_maintenance)
_maintenance_task.start(60) # called every minute
_maintenance_task.start(60) # called every minute
#------------------------------------------------------------
# -------------------------------------------------------------
# Portal Service object
#------------------------------------------------------------
# -------------------------------------------------------------
class Portal(object):
"""
@ -180,11 +182,11 @@ class Portal(object):
self.shutdown_complete = True
reactor.callLater(0, reactor.stop)
#------------------------------------------------------------
# -------------------------------------------------------------
#
# Start the Portal proxy server and add all active services
#
#------------------------------------------------------------
# -------------------------------------------------------------
# twistd requires us to define the variable 'application' so it knows
# what to execute from.

View file

@ -283,7 +283,8 @@ class SshProtocol(Manhole, session.Session):
else:
# we need to make sure to kill the color at the end in order
# to match the webclient output.
linetosend = ansi.parse_ansi(_RE_N.sub("", text) + "|n", strip_ansi=nocolor, xterm256=xterm256, mxp=False)
linetosend = ansi.parse_ansi(_RE_N.sub("", text) + ("|n" if text[-1] != "|" else "||n"),
strip_ansi=nocolor, xterm256=xterm256, mxp=False)
self.sendLine(linetosend)
def send_prompt(self, *args, **kwargs):

View file

@ -54,6 +54,7 @@ class SSLProtocol(TelnetProtocol):
super(SSLProtocol, self).__init__(*args, **kwargs)
self.protocol_name = "ssl"
def verify_SSL_key_and_cert(keyfile, certfile):
"""
This function looks for RSA key and certificate in the current
@ -82,7 +83,7 @@ def verify_SSL_key_and_cert(keyfile, certfile):
# try to create the certificate
CERT_EXPIRE = 365 * 20 # twenty years validity
# default:
#openssl req -new -x509 -key ssl.key -out ssl.cert -days 7300
# openssl req -new -x509 -key ssl.key -out ssl.cert -days 7300
exestring = "openssl req -new -x509 -key %s -out %s -days %s" % (keyfile, certfile, CERT_EXPIRE)
try:
subprocess.call(exestring)

View file

@ -141,7 +141,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
enable (bool): If this option should be enabled.
"""
return (option == MCCP or option==ECHO)
return option == MCCP or option == ECHO
def disableLocal(self, option):
"""
@ -189,7 +189,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
# legacy clients. There should never be a reason to send a
# lone NULL character so this seems to be a safe thing to
# support for backwards compatibility. It also stops the
# NULL from continously popping up as an unknown command.
# NULL from continuously popping up as an unknown command.
data = [_IDLE_COMMAND]
else:
data = _RE_LINEBREAK.split(data)
@ -225,16 +225,16 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
# Session hooks
def disconnect(self, reason=None):
def disconnect(self, reason=""):
"""
generic hook for the engine to call in order to
disconnect this protocol.
Args:
reason (str): Reason for disconnecting.
reason (str, optional): Reason for disconnecting.
"""
self.data_out(text=((reason or "",), {}))
self.data_out(text=((reason,), {}))
self.connectionLost(reason)
def data_in(self, **kwargs):
@ -306,9 +306,11 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
if options.get("send_prompt"):
# send a prompt instead.
prompt = text
if not raw:
# processing
prompt = ansi.parse_ansi(_RE_N.sub("", text) + "|n", strip_ansi=nocolor, xterm256=xterm256)
prompt = ansi.parse_ansi(_RE_N.sub("", prompt) + ("|n" if prompt[-1] != "|" else "||n"),
strip_ansi=nocolor, xterm256=xterm256)
if mxp:
prompt = mxp_parse(prompt)
prompt = prompt.replace(IAC, IAC + IAC).replace('\n', '\r\n')
@ -335,7 +337,8 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
else:
# we need to make sure to kill the color at the end in order
# to match the webclient output.
linetosend = ansi.parse_ansi(_RE_N.sub("", text) + "|n", strip_ansi=nocolor, xterm256=xterm256, mxp=mxp)
linetosend = ansi.parse_ansi(_RE_N.sub("", text) + ("|n" if text[-1] != "|" else "||n"),
strip_ansi=nocolor, xterm256=xterm256, mxp=mxp)
if mxp:
linetosend = mxp_parse(linetosend)
self.sendLine(linetosend)

View file

@ -32,12 +32,12 @@ from evennia.utils.utils import to_str
# MSDP-relevant telnet cmd/opt-codes
MSDP = chr(69)
MSDP_VAR = chr(1) #^A
MSDP_VAL = chr(2) #^B
MSDP_TABLE_OPEN = chr(3) #^C
MSDP_TABLE_CLOSE = chr(4) #^D
MSDP_ARRAY_OPEN = chr(5) #^E
MSDP_ARRAY_CLOSE = chr(6) #^F
MSDP_VAR = chr(1) # ^A
MSDP_VAL = chr(2) # ^B
MSDP_TABLE_OPEN = chr(3) # ^C
MSDP_TABLE_CLOSE = chr(4) # ^D
MSDP_ARRAY_OPEN = chr(5) # ^E
MSDP_ARRAY_CLOSE = chr(6) # ^F
# GMCP
GMCP = chr(201)
@ -51,13 +51,15 @@ force_str = lambda inp: to_str(inp, force_string=True)
# pre-compiled regexes
# returns 2-tuple
msdp_regex_table = re.compile(r"%s\s*(\w*?)\s*%s\s*%s(.*?)%s" % (MSDP_VAR, MSDP_VAL,
MSDP_TABLE_OPEN,
MSDP_TABLE_CLOSE))
msdp_regex_table = re.compile(r"%s\s*(\w*?)\s*%s\s*%s(.*?)%s"
% (MSDP_VAR, MSDP_VAL,
MSDP_TABLE_OPEN,
MSDP_TABLE_CLOSE))
# returns 2-tuple
msdp_regex_array = re.compile(r"%s\s*(\w*?)\s*%s\s*%s(.*?)%s" % (MSDP_VAR, MSDP_VAL,
MSDP_ARRAY_OPEN,
MSDP_ARRAY_CLOSE))
msdp_regex_array = re.compile(r"%s\s*(\w*?)\s*%s\s*%s(.*?)%s"
% (MSDP_VAR, MSDP_VAL,
MSDP_ARRAY_OPEN,
MSDP_ARRAY_CLOSE))
msdp_regex_var = re.compile(r"%s" % MSDP_VAR)
msdp_regex_val = re.compile(r"%s" % MSDP_VAL)
@ -67,6 +69,7 @@ EVENNIA_TO_GMCP = {"client_options": "Core.Supports.Get",
"repeat": "Char.Repeat.Update",
"monitor": "Char.Monitor.Update"}
# MSDP/GMCP communication handler
class TelnetOOB(object):
@ -100,7 +103,7 @@ class TelnetOOB(object):
Client reports No msdp supported or wanted.
Args:
options (Option): Not used.
option (Option): Not used.
"""
# no msdp, check GMCP
@ -173,7 +176,7 @@ class TelnetOOB(object):
if not (args or kwargs):
return msdp_cmdname
#print "encode_msdp in:", cmdname, args, kwargs
# print("encode_msdp in:", cmdname, args, kwargs) # DEBUG
msdp_args = ''
if args:
@ -182,30 +185,30 @@ class TelnetOOB(object):
msdp_args += args[0]
else:
msdp_args += "{msdp_array_open}" \
"{msdp_args}" \
"{msdp_array_close}".format(
msdp_array_open=MSDP_ARRAY_OPEN,
msdp_array_close=MSDP_ARRAY_CLOSE,
msdp_args= "".join("%s%s" % (
MSDP_VAL, json.dumps(val))
for val in args))
"{msdp_args}" \
"{msdp_array_close}".format(
msdp_array_open=MSDP_ARRAY_OPEN,
msdp_array_close=MSDP_ARRAY_CLOSE,
msdp_args="".join("%s%s"
% (MSDP_VAL, json.dumps(val))
for val in args))
msdp_kwargs = ""
if kwargs:
msdp_kwargs = msdp_cmdname
msdp_kwargs += "{msdp_table_open}" \
"{msdp_kwargs}" \
"{msdp_table_close}".format(
msdp_table_open=MSDP_TABLE_OPEN,
msdp_table_close=MSDP_TABLE_CLOSE,
msdp_kwargs = "".join("%s%s%s%s" % (
MSDP_VAR, key, MSDP_VAL, json.dumps(val))
for key, val in kwargs.iteritems()))
"{msdp_kwargs}" \
"{msdp_table_close}".format(
msdp_table_open=MSDP_TABLE_OPEN,
msdp_table_close=MSDP_TABLE_CLOSE,
msdp_kwargs="".join("%s%s%s%s"
% (MSDP_VAR, key, MSDP_VAL,
json.dumps(val))
for key, val in kwargs.iteritems()))
msdp_string = msdp_args + msdp_kwargs
#print "msdp_string:", msdp_string
# print("msdp_string:", msdp_string) # DEBUG
return msdp_string
def encode_gmcp(self, cmdname, *args, **kwargs):
@ -238,10 +241,10 @@ class TelnetOOB(object):
gmcp_string = "%s %s" % (cmdname, json.dumps([args, kwargs]))
else:
gmcp_string = "%s %s" % (cmdname, json.dumps(args))
else: # only kwargs
else: # only kwargs
gmcp_string = "%s %s" % (cmdname, json.dumps(kwargs))
#print "gmcp string", gmcp_string
# print("gmcp string", gmcp_string) # DEBUG
return gmcp_string
def decode_msdp(self, data):
@ -271,7 +274,7 @@ class TelnetOOB(object):
if hasattr(data, "__iter__"):
data = "".join(data)
#print "decode_msdp in:", data
# print("decode_msdp in:", data) # DEBUG
tables = {}
arrays = {}
@ -279,7 +282,7 @@ class TelnetOOB(object):
# decode tables
for key, table in msdp_regex_table.findall(data):
tables[key] = {} if not key in tables else tables[key]
tables[key] = {} if key not in tables else tables[key]
for varval in msdp_regex_var.split(table)[1:]:
var, val = msdp_regex_val.split(varval, 1)
if var:
@ -288,7 +291,7 @@ class TelnetOOB(object):
# decode arrays from all that was not a table
data_no_tables = msdp_regex_table.sub("", data)
for key, array in msdp_regex_array.findall(data_no_tables):
arrays[key] = [] if not key in arrays else arrays[key]
arrays[key] = [] if key not in arrays else arrays[key]
parts = msdp_regex_val.split(array)
if len(parts) == 2:
arrays[key].append(parts[1])
@ -326,10 +329,9 @@ class TelnetOOB(object):
for key, var in variables.iteritems():
cmds[key] = [[var], {}]
#print "msdp data in:", cmds
# print("msdp data in:", cmds) # DEBUG
self.protocol.data_in(**cmds)
def decode_gmcp(self, data):
"""
Decodes incoming GMCP data on the form 'varname <structure>'.
@ -353,7 +355,7 @@ class TelnetOOB(object):
if hasattr(data, "__iter__"):
data = "".join(data)
#print "decode_gmcp in:", data
# print("decode_gmcp in:", data) # DEBUG
if data:
try:
cmdname, structure = data.split(None, 1)
@ -368,7 +370,7 @@ class TelnetOOB(object):
args, kwargs = [], {}
if hasattr(structure, "__iter__"):
if isinstance(structure, dict):
kwargs = {key: value for key, value in structure.iteritems() if key }
kwargs = {key: value for key, value in structure.iteritems() if key}
else:
args = list(structure)
else:

View file

@ -27,6 +27,7 @@ MTTS = [(128, 'PROXY'),
(2, 'VT100'),
(1, 'ANSI')]
class Ttype(object):
"""
Handles ttype negotiations. Called and initiated by the
@ -104,22 +105,21 @@ class Ttype(object):
# use name to identify support for xterm256. Many of these
# only support after a certain version, but all support
# it since at least 4 years. We assume recent client here for now.
xterm256 = False
cupper = clientname.upper()
if cupper.startswith("MUDLET"):
# supports xterm256 stably since 1.1 (2010?)
xterm256 = cupper.split("MUDLET",1)[1].strip() >= "1.1"
xterm256 = cupper.split("MUDLET", 1)[1].strip() >= "1.1"
else:
xterm256 = (cupper.startswith("XTERM") or
cupper.endswith("-256COLOR") or
cupper in ("ATLANTIS", # > 0.9.9.0 (aug 2009)
"CMUD", # > 3.04 (mar 2009)
"KILDCLIENT", # > 2.2.0 (sep 2005)
"MUDLET", # > beta 15 (sep 2009)
"MUSHCLIENT", # > 4.02 (apr 2007)
"PUTTY", # > 0.58 (apr 2005)
"BEIP", # > 2.00.206 (late 2009) (BeipMu)
"POTATO")) # > 2.00 (maybe earlier)
"CMUD", # > 3.04 (mar 2009)
"KILDCLIENT", # > 2.2.0 (sep 2005)
"MUDLET", # > beta 15 (sep 2009)
"MUSHCLIENT", # > 4.02 (apr 2007)
"PUTTY", # > 0.58 (apr 2005)
"BEIP", # > 2.00.206 (late 2009) (BeipMu)
"POTATO")) # > 2.00 (maybe earlier)
# all clients supporting TTYPE at all seem to support ANSI
self.protocol.protocol_flags['ANSI'] = True

View file

@ -32,8 +32,9 @@ from django.utils.translation import ugettext as _
# Handlers for Session.db/ndb operation
class NDbHolder(object):
"Holder for allowing property access of attributes"
"""Holder for allowing property access of attributes"""
def __init__(self, obj, name, manager_name='attributes'):
_SA(self, name, _GA(obj, manager_name))
_SA(self, 'name', name)
@ -145,9 +146,9 @@ class NAttributeHandler(object):
return [key for key in self._store if not key.startswith("_")]
#------------------------------------------------------------
# -------------------------------------------------------------
# Server Session
#------------------------------------------------------------
# -------------------------------------------------------------
class ServerSession(Session):
"""
@ -160,7 +161,7 @@ class ServerSession(Session):
"""
def __init__(self):
"Initiate to avoid AttributeErrors down the line"
"""Initiate to avoid AttributeErrors down the line"""
self.puppet = None
self.player = None
self.cmdset_storage_string = ""
@ -203,7 +204,7 @@ class ServerSession(Session):
obj.player = self.player
self.puid = obj.id
self.puppet = obj
#obj.scripts.validate()
# obj.scripts.validate()
obj.locks.cache_lock_bypass(obj)
def at_login(self, player):
@ -264,7 +265,6 @@ class ServerSession(Session):
MONITOR_HANDLER.remove(player, "_saved_webclient_options",
self.sessid)
def get_player(self):
"""
Get the player associated with this session
@ -364,7 +364,6 @@ class ServerSession(Session):
self.protocol_flags.update(kwargs)
self.sessionhandler.session_portal_sync(self)
def data_out(self, **kwargs):
"""
Sending data from Evennia->Client
@ -437,7 +436,7 @@ class ServerSession(Session):
self.sessionhandler.data_in(self, **kwargs)
def __eq__(self, other):
"Handle session comparisons"
"""Handle session comparisons"""
try:
return self.address == other.address
except AttributeError:
@ -462,11 +461,9 @@ class ServerSession(Session):
return "%s%s@%s" % (self.uname, symbol, address)
def __unicode__(self):
"Unicode representation"
"""Unicode representation"""
return u"%s" % str(self)
# Dummy API hooks for use during non-loggedin operation
def at_cmdset_get(self, **kwargs):
@ -488,7 +485,7 @@ class ServerSession(Session):
def attributes(self):
return self.nattributes
#@property
# @property
def ndb_get(self):
"""
A non-persistent store (ndb: NonDataBase). Everything stored
@ -503,7 +500,7 @@ class ServerSession(Session):
self._ndb_holder = NDbHolder(self, "nattrhandler", manager_name="nattributes")
return self._ndb_holder
#@ndb.setter
# @ndb.setter
def ndb_set(self, value):
"""
Stop accidentally replacing the db object
@ -516,9 +513,9 @@ class ServerSession(Session):
string += "Use ndb.attr=value instead."
raise Exception(string)
#@ndb.deleter
# @ndb.deleter
def ndb_del(self):
"Stop accidental deletion."
"""Stop accidental deletion."""
raise Exception("Cannot delete the ndb object!")
ndb = property(ndb_get, ndb_set, ndb_del)
db = property(ndb_get, ndb_set, ndb_del)
@ -526,5 +523,5 @@ class ServerSession(Session):
# Mock access method for the session (there is no lock info
# at this stage, so we just present a uniform API)
def access(self, *args, **kwargs):
"Dummy method to mimic the logged-in API."
"""Dummy method to mimic the logged-in API."""
return True