# 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)

`evennia.server.portal.amp.``loads`(data)

class `evennia.server.portal.amp.``Compressed`(optional=False)

  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)

    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)

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

  `toString`(inObject)

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

    Note: In Py3 this is really a byte stream.

  `fromString`(inString)

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

class `evennia.server.portal.amp.``MsgLauncher2Portal`(**kw)

  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)

  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)

  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)

  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)

  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)

  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)

  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)

  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)

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

  `stringReceived`(string)

    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)

    Handle non-AMP messages, such as HTTP communication.

  `makeConnection`(transport)

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

  `connectionMade`()

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

  `connectionLost`(reason)

    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)

    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)

    Process incoming packed data.

    Parameters

      packed_data (bytes) – Pickled data.

    Returns

      unpaced_data (any) – Unpickled package

  `broadcast`(command, sessid, **kwargs)

    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)

    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`()

    Helper decorator