2011-11-19 19:34:00 +01:00
|
|
|
"""
|
2011-11-20 00:50:11 +01:00
|
|
|
TTYPE (MTTS) - Mud Terminal Type Standard
|
|
|
|
|
|
2011-11-19 19:34:00 +01:00
|
|
|
This module implements the TTYPE telnet protocol as per
|
|
|
|
|
http://tintin.sourceforge.net/mtts/. It allows the server to ask the
|
|
|
|
|
client about its capabilities. If the client also supports TTYPE, it
|
|
|
|
|
will return with information such as its name, if it supports colour
|
|
|
|
|
etc. If the client does not support TTYPE, this will be ignored.
|
|
|
|
|
|
|
|
|
|
All data will be stored on the protocol's protocol_flags dictionary,
|
|
|
|
|
under the 'TTYPE' key.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
# telnet option codes
|
|
|
|
|
TTYPE = chr(24)
|
|
|
|
|
IS = chr(0)
|
|
|
|
|
SEND = chr(1)
|
|
|
|
|
|
|
|
|
|
# terminal capabilities and their codes
|
2012-03-30 23:57:04 +02:00
|
|
|
MTTS = [(128,'PROXY'),
|
|
|
|
|
(64, 'SCREEN READER'),
|
|
|
|
|
(32, 'OSC COLOR PALETTE'),
|
|
|
|
|
(16, 'MOUSE TRACKING'),
|
|
|
|
|
(8, '256 COLORS'),
|
2011-11-19 19:34:00 +01:00
|
|
|
(4, 'UTF-8'),
|
|
|
|
|
(2, 'VT100'),
|
|
|
|
|
(1, 'ANSI')]
|
|
|
|
|
|
|
|
|
|
class Ttype(object):
|
|
|
|
|
"""
|
2012-03-30 23:57:04 +02:00
|
|
|
Handles ttype negotiations. Called and initiated by the
|
2011-11-19 19:34:00 +01:00
|
|
|
telnet protocol.
|
|
|
|
|
"""
|
|
|
|
|
def __init__(self, protocol):
|
|
|
|
|
"""
|
|
|
|
|
initialize ttype by storing protocol on ourselves and calling
|
|
|
|
|
the client to see if it supporst ttype.
|
|
|
|
|
|
|
|
|
|
the ttype_step indicates how far in the data retrieval we've
|
|
|
|
|
gotten.
|
|
|
|
|
"""
|
2012-03-30 23:57:04 +02:00
|
|
|
self.ttype_step = 0
|
2011-11-19 19:34:00 +01:00
|
|
|
self.protocol = protocol
|
2012-03-21 19:56:04 +01:00
|
|
|
self.protocol.protocol_flags['TTYPE'] = {"init_done":False}
|
2011-11-19 19:34:00 +01:00
|
|
|
|
|
|
|
|
# setup protocol to handle ttype initialization and negotiation
|
2012-03-30 23:57:04 +02:00
|
|
|
self.protocol.negotiationMap[TTYPE] = self.do_ttype
|
2011-11-19 19:34:00 +01:00
|
|
|
# ask if client will ttype, connect callback if it does.
|
2011-11-20 00:50:11 +01:00
|
|
|
self.protocol.will(TTYPE).addCallbacks(self.do_ttype, self.no_ttype)
|
2012-03-30 23:57:04 +02:00
|
|
|
|
2011-11-19 19:34:00 +01:00
|
|
|
def no_ttype(self, option):
|
|
|
|
|
"""
|
2012-03-30 23:57:04 +02:00
|
|
|
Callback if ttype is not supported by client.
|
2011-11-19 19:34:00 +01:00
|
|
|
"""
|
2012-03-30 23:57:04 +02:00
|
|
|
self.protocol.protocol_flags['TTYPE'] = False
|
2011-11-19 19:34:00 +01:00
|
|
|
|
2011-11-20 00:50:11 +01:00
|
|
|
def do_ttype(self, option):
|
2011-11-19 19:34:00 +01:00
|
|
|
"""
|
2012-03-30 23:57:04 +02:00
|
|
|
Handles negotiation of the ttype protocol once the
|
|
|
|
|
client has confirmed that it supports the ttype
|
|
|
|
|
protocol.
|
2011-11-19 19:34:00 +01:00
|
|
|
|
|
|
|
|
The negotiation proceeds in several steps, each returning a
|
|
|
|
|
certain piece of information about the client. All data is
|
|
|
|
|
stored on protocol.protocol_flags under the TTYPE key.
|
|
|
|
|
"""
|
|
|
|
|
|
2012-03-21 19:56:04 +01:00
|
|
|
if self.protocol.protocol_flags['TTYPE']['init_done']:
|
2012-03-30 23:57:04 +02:00
|
|
|
return
|
2012-03-21 19:56:04 +01:00
|
|
|
|
2011-11-19 19:34:00 +01:00
|
|
|
self.ttype_step += 1
|
|
|
|
|
|
2012-03-30 23:57:04 +02:00
|
|
|
if self.ttype_step == 1:
|
|
|
|
|
# set up info storage and initialize subnegotiation
|
2011-11-19 19:34:00 +01:00
|
|
|
self.protocol.requestNegotiation(TTYPE, SEND)
|
|
|
|
|
else:
|
2012-03-30 23:57:04 +02:00
|
|
|
# receive data
|
2011-11-19 19:34:00 +01:00
|
|
|
option = "".join(option).lstrip(IS)
|
|
|
|
|
if self.ttype_step == 2:
|
|
|
|
|
self.protocol.protocol_flags['TTYPE']['CLIENTNAME'] = option
|
|
|
|
|
self.protocol.requestNegotiation(TTYPE, SEND)
|
|
|
|
|
elif self.ttype_step == 3:
|
|
|
|
|
self.protocol.protocol_flags['TTYPE']['TERM'] = option
|
|
|
|
|
self.protocol.requestNegotiation(TTYPE, SEND)
|
2012-03-30 23:57:04 +02:00
|
|
|
elif self.ttype_step == 4:
|
2011-11-19 19:34:00 +01:00
|
|
|
option = int(option.strip('MTTS '))
|
2012-03-30 23:57:04 +02:00
|
|
|
self.protocol.protocol_flags['TTYPE']['MTTS'] = option
|
|
|
|
|
for codenum, standard in MTTS:
|
2011-11-19 19:34:00 +01:00
|
|
|
if option == 0:
|
2012-03-30 23:57:04 +02:00
|
|
|
break
|
2011-11-19 19:34:00 +01:00
|
|
|
status = option % codenum < option
|
|
|
|
|
self.protocol.protocol_flags['TTYPE'][standard] = status
|
2012-03-30 23:57:04 +02:00
|
|
|
if status:
|
2011-11-19 19:34:00 +01:00
|
|
|
option = option % codenum
|
2012-03-21 19:56:04 +01:00
|
|
|
self.protocol.protocol_flags['TTYPE']['init_done'] = True
|
|
|
|
|
|
2011-11-19 19:34:00 +01:00
|
|
|
#print "ttype results:", self.protocol.protocol_flags['TTYPE']
|