Make telnet make better use of Twisted's in-build parsing, as per #1122.
This commit is contained in:
parent
3a4a097163
commit
0805fa1cde
1 changed files with 7 additions and 66 deletions
|
|
@ -9,13 +9,14 @@ sessions etc.
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from twisted.internet.task import LoopingCall
|
from twisted.internet.task import LoopingCall
|
||||||
from twisted.conch.telnet import Telnet, StatefulTelnetProtocol, IAC, NOP, LINEMODE, GA, WILL, WONT, ECHO, NULL
|
from twisted.conch.telnet import Telnet, StatefulTelnetProtocol
|
||||||
|
from twisted.conch.telnet import IAC, NOP, LINEMODE, GA, WILL, WONT, ECHO
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from evennia.server.session import Session
|
from evennia.server.session import Session
|
||||||
from evennia.server.portal import ttype, mssp, telnet_oob, naws
|
from evennia.server.portal import ttype, mssp, telnet_oob, naws
|
||||||
from evennia.server.portal.mccp import Mccp, mccp_compress, MCCP
|
from evennia.server.portal.mccp import Mccp, mccp_compress, MCCP
|
||||||
from evennia.server.portal.mxp import Mxp, mxp_parse
|
from evennia.server.portal.mxp import Mxp, mxp_parse
|
||||||
from evennia.utils import ansi, logger
|
from evennia.utils import ansi
|
||||||
from evennia.utils.utils import to_str
|
from evennia.utils.utils import to_str
|
||||||
|
|
||||||
_RE_N = re.compile(r"\{n$")
|
_RE_N = re.compile(r"\{n$")
|
||||||
|
|
@ -171,67 +172,6 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
|
||||||
self.sessionhandler.disconnect(self)
|
self.sessionhandler.disconnect(self)
|
||||||
self.transport.loseConnection()
|
self.transport.loseConnection()
|
||||||
|
|
||||||
def dataReceived(self, data):
|
|
||||||
"""
|
|
||||||
Handle incoming data over the wire.
|
|
||||||
|
|
||||||
This method will split the incoming data depending on if it
|
|
||||||
starts with IAC (a telnet command) or not. All other data will
|
|
||||||
be handled in line mode. Some clients also sends an erroneous
|
|
||||||
line break after IAC, which we must watch out for.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
data (str): Incoming data.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
OOB protocols (MSDP etc) already intercept subnegotiations on
|
|
||||||
their own, never entering this method. They will relay their
|
|
||||||
parsed data directly to self.data_in.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if data and data[0] == IAC or self.iaw_mode:
|
|
||||||
try:
|
|
||||||
super(TelnetProtocol, self).dataReceived(data)
|
|
||||||
if len(data) == 1:
|
|
||||||
self.iaw_mode = True
|
|
||||||
else:
|
|
||||||
self.iaw_mode = False
|
|
||||||
return
|
|
||||||
except Exception as err1:
|
|
||||||
conv = ""
|
|
||||||
try:
|
|
||||||
for b in data:
|
|
||||||
conv += " " + repr(ord(b))
|
|
||||||
except Exception as err2:
|
|
||||||
conv = str(err2) + ":", str(data)
|
|
||||||
out = "Telnet Error (%s): %s (%s)" % (err1, data, conv)
|
|
||||||
logger.log_trace(out)
|
|
||||||
return
|
|
||||||
|
|
||||||
if data and data.strip() == NULL:
|
|
||||||
# This is an ancient type of keepalive still used by some
|
|
||||||
# legacy clients. There should never be a reason to send
|
|
||||||
# a lone NULL character so this seems ok to support for
|
|
||||||
# backwards compatibility.
|
|
||||||
data = _IDLE_COMMAND
|
|
||||||
|
|
||||||
if self.no_lb_mode and _RE_LEND.search(data):
|
|
||||||
# we are in no_lb_mode and receive a line break;
|
|
||||||
# this means we should empty the buffer and send
|
|
||||||
# the command.
|
|
||||||
data = "".join(self.line_buffer) + data
|
|
||||||
data = data.rstrip("\r\n") + "\n"
|
|
||||||
self.line_buffer = []
|
|
||||||
self.no_lb_mode = False
|
|
||||||
elif not _RE_LEND.search(data):
|
|
||||||
# no line break at the end of the command, buffer instead.
|
|
||||||
self.line_buffer.append(data)
|
|
||||||
self.no_lb_mode = True
|
|
||||||
return
|
|
||||||
|
|
||||||
# if we get to this point the command should end with a linebreak.
|
|
||||||
StatefulTelnetProtocol.dataReceived(self, data)
|
|
||||||
|
|
||||||
def _write(self, data):
|
def _write(self, data):
|
||||||
"hook overloading the one used in plain telnet"
|
"hook overloading the one used in plain telnet"
|
||||||
data = data.replace('\n', '\r\n').replace('\r\r\n', '\r\n')
|
data = data.replace('\n', '\r\n').replace('\r\r\n', '\r\n')
|
||||||
|
|
@ -251,10 +191,11 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
|
||||||
line = line.replace(IAC, IAC + IAC).replace('\n', '\r\n')
|
line = line.replace(IAC, IAC + IAC).replace('\n', '\r\n')
|
||||||
return self.transport.write(mccp_compress(self, line))
|
return self.transport.write(mccp_compress(self, line))
|
||||||
|
|
||||||
def lineReceived(self, string):
|
def applicationDataReceived(self, string):
|
||||||
"""
|
"""
|
||||||
Telnet method called when data is coming in over the telnet
|
Telnet method called when non-telnet-command data is coming in
|
||||||
connection. We pass it on to the game engine directly.
|
over the telnet connection. We pass it on to the game engine
|
||||||
|
directly.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
string (str): Incoming data.
|
string (str): Incoming data.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue