[Twisted-Python] Telnet negotiation with Twisted
Patrick Mylund Nielsen
twisted at patrickmylund.com
Sat Dec 3 09:48:04 EST 2011
Pardon my double-posting. Here it is, a little less confusing:
#!/usr/bin/env python
from twisted.internet.protocol import Factory
from twisted.conch.telnet import TelnetProtocol, TelnetTransport
from twisted.conch.telnet import WILL
# More info: http://www.faqs.org/rfcs/rfc1184.html
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 dataReceived(self, data):
if self.transport.lines:
line = data.rstrip()
print("data received (normal): " + line)
if line == "gounbuffered":
self.transport.requestNegotiation(LINEMODE,
LINEMODE_TRAPSIG) # Client should only trap signals locally
self.transport.lines = False
else:
# manually buffer data here
print("data received (unbuffered): " + data)
if data == "n":
self.transport.requestNegotiation(LINEMODE,
LINEMODE_EDIT) # Go back to buffered
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) # 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()
On Sat, Dec 3, 2011 at 15:22, Patrick Mylund Nielsen
<twisted at patrickmylund.com> wrote:
> 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