[Twisted-Python] Telnet negotiation with Twisted

Patrick Mylund Nielsen twisted at patrickmylund.com
Sat Dec 3 09:22:19 EST 2011


Hi Lee,

Here is a complete example that works with Twisted 11.0. LINEMODE
itself is enabled at connect, but it has different modes that
determine what is sent when by the client. (See section 2.2 of
http://www.faqs.org/rfcs/rfc1184.html)

#####

#!/usr/bin/env python
from twisted.internet.protocol import Factory
from twisted.conch.telnet import TelnetProtocol,
StatefulTelnetProtocol, TelnetTransport
from twisted.conch.telnet import DO, DONT, WILL, WONT

LINEMODE = chr(34)
LINEMODE_EDIT = chr(1) + chr(1)
LINEMODE_TRAPSIG = chr(1) + chr(2)
LINEMODE_MODEACK = chr(1) + chr(4)
LINEMODE_SOFTTAB = chr(1) + chr(8)
LINEMODE_LITECHO = chr(1) + chr(16)

class LineModeProtocol(TelnetProtocol):

    def connectionMade(self):
        print("Connection made!")

    def connectionLost(self, reason):
        print("Connection lost!")

    def dataReceived(self, data):
        if self.transport.lines:
            line = data.rstrip()
            print("data received (normal): " + line)
            if line == "gounbuffered":
                self.transport.requestNegotiation(LINEMODE,
LINEMODE_TRAPSIG) # Only trap signals locally
                self.transport.lines = False
        else:
            # manually buffer data here
            print("data received (linemode): " + data)
            if data == "n":
                self.transport.requestNegotiation(LINEMODE,
LINEMODE_EDIT) # Change to edit mode
                self.transport.lines = True

class LineModeTransport(TelnetTransport):

    def connectionMade(self):
        self.lines = True
        self.do(LINEMODE) # Ask client to begin sub-negotation of linemode
        TelnetTransport.connectionMade(self)

    def commandReceived(self, command, argument):
        if argument == LINEMODE:
            if command == WILL: # Client said OK to our DO; let's... do it
                self.requestNegotiation(LINEMODE, LINEMODE_EDIT) # The
normal (buffered) mode
        else:
            TelnetTransport.commandReceived(self, command, argument)

class LineModeFactory(Factory):

    def buildProtocol(self, addr):
        return LineModeTransport(LineModeProtocol)

if __name__ == '__main__':
    from twisted.internet import reactor

    port = 2222
    factory = LineModeFactory()

    reactor.listenTCP(port, factory)
    reactor.run()

#####

There is probably an easier way to check the state of LINEMODE, e.g.
with getOptionState, but it works.

Example:

Client:
# telnet localhost 2222
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
How are you?
gounbuffered
testnback again

Server:
# ./linemode.py
Connection made!
data received (normal): How are you?
data received (normal): gounbuffered
data received (linemode): t
data received (linemode): e
data received (linemode): s
data received (linemode): t
data received (linemode): n
data received (normal): back again

Best,
Patrick

On Sat, Dec 3, 2011 at 14:59,  <exarkun at twistedmatrix.com> wrote:
> On 03:53 am, lmorsino at gmail.com wrote:
>>Jean-Paul,
>>
>>Thanks for your response. I still can't get self.will(LINEMODE) to work
>>but
>>I did get self.telnet_WILL(LINEMODE) to run without throwing an Error.
>>Can
>>you elaborate on what needs to happen in the enableRemote? My
>>impression
>>was that once I send the negotiation WILL command from server to the
>>client, the client will respond with either a DO or a DONT. What
>>further
>>logic is necessary?
>
> I can't say what further logic is necessary, because I don't know what
> logic you have now.  The description of your code you gave above is a
> good introduction to an actual code listing (<http://sscce.org/>), but
> it's not sufficient on its own.
>
> Jean-Paul
>
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python



More information about the Twisted-Python mailing list