evennia.server.portal.amp

The AMP (Asynchronous Message Protocol)-communication commands and constants used by Evennia.

This module acts as a central place for AMP-servers and -clients to get commands to use.

evennia.server.portal.amp.dumps(data)[source]
evennia.server.portal.amp.loads(data)[source]
class evennia.server.portal.amp.Compressed(optional=False)[source]

Bases: twisted.protocols.amp.String

This is a custom AMP command Argument that both handles too-long sends as well as uses zlib for compression across the wire. The batch-grouping of too-long sends is borrowed from the “mediumbox” recipy at twisted-hacks’s ~glyph/+junk/amphacks/mediumbox.

fromBox(name, strings, objects, proto)[source]

Converts from box string representation to python. We read back too-long batched data and put it back together here.

toBox(name, strings, objects, proto)[source]

Convert from python object to string box representation. we break up too-long data snippets into multiple batches here.

toString(inObject)[source]

Convert to send as a bytestring on the wire, with compression.

Note: In Py3 this is really a byte stream.

fromString(inString)[source]

Convert (decompress) from the string-representation on the wire to Python.

class evennia.server.portal.amp.MsgLauncher2Portal(**kw)[source]

Bases: twisted.protocols.amp.Command

Message Launcher -> Portal

key = 'MsgLauncher2Portal'
arguments: List[Tuple[bytes, twisted.protocols.amp.Argument]] = [(b'operation', <twisted.protocols.amp.String object>), (b'arguments', <twisted.protocols.amp.String object>)]
errors: Dict[Type[Exception], bytes] = {<class 'Exception'>: b'EXCEPTION'}
response: List[Tuple[bytes, twisted.protocols.amp.Argument]] = []
allErrors = {<class 'Exception'>: b'EXCEPTION'}
commandName = b'MsgLauncher2Portal'
reverseErrors = {b'EXCEPTION': <class 'Exception'>}
class evennia.server.portal.amp.MsgPortal2Server(**kw)[source]

Bases: twisted.protocols.amp.Command

Message Portal -> Server

key = b'MsgPortal2Server'
arguments: List[Tuple[bytes, twisted.protocols.amp.Argument]] = [(b'packed_data', <evennia.server.portal.amp.Compressed object>)]
errors: Dict[Type[Exception], bytes] = {<class 'Exception'>: b'EXCEPTION'}
response: List[Tuple[bytes, twisted.protocols.amp.Argument]] = []
allErrors = {<class 'Exception'>: b'EXCEPTION'}
commandName = b'MsgPortal2Server'
reverseErrors = {b'EXCEPTION': <class 'Exception'>}
class evennia.server.portal.amp.MsgServer2Portal(**kw)[source]

Bases: twisted.protocols.amp.Command

Message Server -> Portal

key = 'MsgServer2Portal'
arguments: List[Tuple[bytes, twisted.protocols.amp.Argument]] = [(b'packed_data', <evennia.server.portal.amp.Compressed object>)]
errors: Dict[Type[Exception], bytes] = {<class 'Exception'>: b'EXCEPTION'}
response: List[Tuple[bytes, twisted.protocols.amp.Argument]] = []
allErrors = {<class 'Exception'>: b'EXCEPTION'}
commandName = b'MsgServer2Portal'
reverseErrors = {b'EXCEPTION': <class 'Exception'>}
class evennia.server.portal.amp.AdminPortal2Server(**kw)[source]

Bases: twisted.protocols.amp.Command

Administration Portal -> Server

Sent when the portal needs to perform admin operations on the server, such as when a new session connects or resyncs

key = 'AdminPortal2Server'
arguments: List[Tuple[bytes, twisted.protocols.amp.Argument]] = [(b'packed_data', <evennia.server.portal.amp.Compressed object>)]
errors: Dict[Type[Exception], bytes] = {<class 'Exception'>: b'EXCEPTION'}
response: List[Tuple[bytes, twisted.protocols.amp.Argument]] = []
allErrors = {<class 'Exception'>: b'EXCEPTION'}
commandName = b'AdminPortal2Server'
reverseErrors = {b'EXCEPTION': <class 'Exception'>}
class evennia.server.portal.amp.AdminServer2Portal(**kw)[source]

Bases: twisted.protocols.amp.Command

Administration Server -> Portal

Sent when the server needs to perform admin operations on the portal.

key = 'AdminServer2Portal'
arguments: List[Tuple[bytes, twisted.protocols.amp.Argument]] = [(b'packed_data', <evennia.server.portal.amp.Compressed object>)]
errors: Dict[Type[Exception], bytes] = {<class 'Exception'>: b'EXCEPTION'}
response: List[Tuple[bytes, twisted.protocols.amp.Argument]] = []
allErrors = {<class 'Exception'>: b'EXCEPTION'}
commandName = b'AdminServer2Portal'
reverseErrors = {b'EXCEPTION': <class 'Exception'>}
class evennia.server.portal.amp.MsgStatus(**kw)[source]

Bases: twisted.protocols.amp.Command

Check Status between AMP services

key = 'MsgStatus'
arguments: List[Tuple[bytes, twisted.protocols.amp.Argument]] = [(b'status', <twisted.protocols.amp.String object>)]
errors: Dict[Type[Exception], bytes] = {<class 'Exception'>: b'EXCEPTION'}
response: List[Tuple[bytes, twisted.protocols.amp.Argument]] = [(b'status', <twisted.protocols.amp.String object>)]
allErrors = {<class 'Exception'>: b'EXCEPTION'}
commandName = b'MsgStatus'
reverseErrors = {b'EXCEPTION': <class 'Exception'>}
class evennia.server.portal.amp.FunctionCall(**kw)[source]

Bases: twisted.protocols.amp.Command

Bidirectional Server <-> Portal

Sent when either process needs to call an arbitrary function in the other. This does not use the batch-send functionality.

key = 'FunctionCall'
arguments: List[Tuple[bytes, twisted.protocols.amp.Argument]] = [(b'module', <twisted.protocols.amp.String object>), (b'function', <twisted.protocols.amp.String object>), (b'args', <twisted.protocols.amp.String object>), (b'kwargs', <twisted.protocols.amp.String object>)]
errors: Dict[Type[Exception], bytes] = {<class 'Exception'>: b'EXCEPTION'}
response: List[Tuple[bytes, twisted.protocols.amp.Argument]] = [(b'result', <twisted.protocols.amp.String object>)]
allErrors = {<class 'Exception'>: b'EXCEPTION'}
commandName = b'FunctionCall'
reverseErrors = {b'EXCEPTION': <class 'Exception'>}
class evennia.server.portal.amp.AMPMultiConnectionProtocol(*args, **kwargs)[source]

Bases: twisted.protocols.amp.AMP

AMP protocol that safely handle multiple connections to the same server without dropping old ones - new clients will receive all server returns (broadcast). Will also correctly handle erroneous HTTP requests on the port and return a HTTP error response.

__init__(*args, **kwargs)[source]

Initialize protocol with some things that need to be in place already before connecting both on portal and server.

stringReceived(string)[source]

Overrides the base stringReceived of twisted in order to handle the strange error reported in https://github.com/evennia/evennia/issues/2053, which can lead to the amp connection locking up.

Parameters

string (str) – the data coming in.

Notes

To test, add the following code to the beginning of evennia.server.amp_client.AMPServerClientProtocol.data_to_portal, then run multiple commands until the error trigger:

import random
from twisted.protocols.amp import AmpBox
always_fail = False
if always_fail or random.random() < 0.05:
    breaker = AmpBox()
    breaker['_answer'.encode()]='13541'.encode()
    self.transport.write(breaker.serialize())
dataReceived(data)[source]

Handle non-AMP messages, such as HTTP communication.

makeConnection(transport)[source]

Swallow connection log message here. Copied from original in the amp protocol.

connectionMade()[source]

This is called when an AMP connection is (re-)established. AMP calls it on both sides.

connectionLost(reason)[source]

We swallow connection errors here. The reason is that during a normal reload/shutdown there will almost always be cases where either the portal or server shuts down before a message has returned its (empty) return, triggering a connectionLost error that is irrelevant. If a true connection error happens, the portal will continuously try to reconnect, showing the problem that way.

errback(err, info)[source]

Error callback. Handles errors to avoid dropping connections on server tracebacks.

Parameters
  • err (Failure) – Deferred error instance.

  • info (str) – Error string.

data_in(packed_data)[source]

Process incoming packed data.

Parameters

packed_data (bytes) – Pickled data.

Returns

unpaced_data (any) – Unpickled package

broadcast(command, sessid, **kwargs)[source]

Send data across the wire to all connections.

Parameters
  • command (AMP Command) – A protocol send command.

  • sessid (int) – A unique Session id.

Returns

deferred (deferred or None) – A deferred with an errback.

Notes

Data will be sent across the wire pickled as a tuple (sessid, kwargs).

send_FunctionCall(modulepath, functionname, *args, **kwargs)[source]

Access method called by either process. This will call an arbitrary function on the other process (On Portal if calling from Server and vice versa).

Inputs:

modulepath (str) - python path to module holding function to call functionname (str) - name of function in given module *args, **kwargs will be used as arguments/keyword args for the

remote function call

Returns

A deferred that fires with the return value of the remote function call

receive_functioncall()[source]

Helper decorator