Handle AMP issue. Resolve #2053.

This commit is contained in:
Griatch 2022-02-13 11:57:28 +01:00
parent 99255bcf07
commit 0e401017ab

View file

@ -5,8 +5,8 @@ This module acts as a central place for AMP-servers and -clients to get commands
""" """
from functools import wraps
import time import time
from functools import wraps
from twisted.protocols import amp from twisted.protocols import amp
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from io import BytesIO from io import BytesIO
@ -358,6 +358,48 @@ class AMPMultiConnectionProtocol(amp.AMP):
deferred.addCallback(self._safeEmit) deferred.addCallback(self._safeEmit)
deferred.addErrback(self.unhandledError) deferred.addErrback(self.unhandledError)
def stringReceived(self, 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.
Args:
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())
"""
try:
pto = "proto_" + self.state
statehandler = getattr(self, pto)
except AttributeError:
log.msg("callback", self.state, "not found")
else:
try:
# make sure to catch a KeyError cleanly here
self.state = statehandler(string)
if self.state == "done":
self.transport.loseConnection()
except KeyError as err:
_get_logger().log_err(
f"AMP error (KeyError: {err}). Discarded data (see "
"https://github.com/evennia/evennia/issues/2053)"
)
def dataReceived(self, data): def dataReceived(self, data):
""" """
Handle non-AMP messages, such as HTTP communication. Handle non-AMP messages, such as HTTP communication.