From 91ec33b9a72989b28177f7158eefc823863326ff Mon Sep 17 00:00:00 2001 From: Griatch Date: Sun, 15 Apr 2012 19:53:03 +0200 Subject: [PATCH] Fixed a spurious error happening with mud clients not properly implementing TTYPE negotiating (sending strings instead of numbers to identify their abilities). --- src/commands/default/unloggedin.py | 3 +-- src/server/telnet.py | 35 ++++++++++++++++++------------ src/server/ttype.py | 22 ++++++++++++++++++- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/commands/default/unloggedin.py b/src/commands/default/unloggedin.py index 67d6b86af2..8642d2ac40 100644 --- a/src/commands/default/unloggedin.py +++ b/src/commands/default/unloggedin.py @@ -24,8 +24,7 @@ try: except Exception: pass if not CONNECTION_SCREEN: - CONNECTION_SCREEN = "\nEvennia: Error in CONNECTION_SCREEN MODULE. Connect screen not found. Enter 'help' for aid." - + CONNECTION_SCREEN = "\nEvennia: Error in CONNECTION_SCREEN MODULE (randomly picked connection screen variable is not a string). \nEnter 'help' for aid." class CmdUnconnectedConnect(MuxCommand): """ diff --git a/src/server/telnet.py b/src/server/telnet.py index 313bdd9547..4b93a6ed4d 100644 --- a/src/server/telnet.py +++ b/src/server/telnet.py @@ -11,7 +11,7 @@ from twisted.conch.telnet import Telnet, StatefulTelnetProtocol, IAC, LINEMODE from src.server.session import Session from src.server import ttype, mssp from src.server.mccp import Mccp, mccp_compress, MCCP -from src.utils import utils, ansi +from src.utils import utils, ansi, logger class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): """ @@ -25,6 +25,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): established. """ # initialize the session + self.iaw_mode = False client_address = self.transport.client self.init_session("telnet", client_address, self.factory.sessionhandler) # negotiate mccp (data compression) @@ -76,26 +77,32 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): """ 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. + be handled in line mode. Some clients also sends an erroneous + line break after IAC, which we must watch out for. """ - print "dataRcv (%s):" % data, - try: - for b in data: - print ord(b), - print "" - except Exception, e: - print str(e) + ":", str(data) + #print "dataRcv (%s):" % data, + #try: + # for b in data: + # print ord(b), + # print "" + #except Exception, e: + # print str(e) + ":", str(data) - if data and data[0] == IAC: + if data and data[0] == IAC or self.iaw_mode: try: - print "IAC mode" + #print "IAC mode" super(TelnetProtocol, self).dataReceived(data) + if len(data) == 1: + self.iaw_mode = True + else: + self.iaw_mode = False return except Exception: - pass + logger.log_trace() # if we get to this point the command must end with a linebreak. - #data = data.rstrip("\r\n") + "\r\n" - print "line mode: (%s)" % data + # We make sure to add it, to fix some clients messing this up. + data = data.rstrip("\r\n") + "\r\n" + #print "line mode: (%s)" % data StatefulTelnetProtocol.dataReceived(self, data) def _write(self, data): diff --git a/src/server/ttype.py b/src/server/ttype.py index 1d24803b37..6c72b35143 100644 --- a/src/server/ttype.py +++ b/src/server/ttype.py @@ -25,6 +25,16 @@ MTTS = [(128,'PROXY'), (4, 'UTF-8'), (2, 'VT100'), (1, 'ANSI')] +# some clients sends erroneous strings instead +# of capability numbers. We try to convert back. +MTTS_invert = {"PROXY":128, + "SCREEN COLOR PALETTE":64, + "OSC COLOR PALETTE": 32, + "MOUSE TRACKING": 16, + "256 COLORS": 8, + "UTF-8": 4, + "VT100": 2, + "ANSI": 1} class Ttype(object): """ @@ -81,7 +91,17 @@ class Ttype(object): self.protocol.protocol_flags['TTYPE']['TERM'] = option self.protocol.requestNegotiation(TTYPE, SEND) elif self.ttype_step == 4: - option = int(option.strip('MTTS ')) + try: + option = int(option.strip('MTTS ')) + except ValueError: + # it seems some clients don't send MTTS according to protocol + # specification, but instead just sends the data as plain + # strings. We try to convert back. + option = MTTS_invert.get(option.strip('MTTS ').upper()) + if not option: + # no conversion possible. Give up. + self.protocol.protocol_flags['TTYPE']['init_done'] = True + return self.protocol.protocol_flags['TTYPE']['MTTS'] = option for codenum, standard in MTTS: if option == 0: