2

I'm trying to write a simple telnet client that just runs a single command on a remote box using telnet. This needs to run over asyncio as other tasks are monitored at the same time under that framework.

I got it almost working, with the code below, that I tweaked from telnet-client as part of the telnetlib3 library; except that it does not return. I've had a hard time trying to figure what this protocol.waiter_closed is all about.

In any case, how do I need to tweak this code so that it returns once the command has been dealt with on the remote end ?

Thanks

#!/usr/bin/env python3
import logging

import asyncio
import telnetlib3

# just to check that connection is thrown away
class MyClient(telnetlib3.TelnetClient):
    def connection_lost(self, *args):
        print("connection lost on client {} - args={}".format(self, args))

@asyncio.coroutine
def register_telnet_command(loop, Client, host, port, command):
    transport, protocol = yield from loop.create_connection(Client, host, port)

    print("{} async connection OK for command {}".format(host, command))

    def send_command():
        EOF = chr(4)
        EOL = '\n'
        # adding newline and end-of-file for this simple example
        command_line = command + EOL + EOF
        protocol.stream.write(protocol.shell.encode(command_line))

    # one shot invokation of the command
    loop.call_soon(send_command)
    # what does this do exactly ?
    yield from protocol.waiter_closed

port = 23
hostname = "fit01"

def main():
    def ClientFactory():
        return MyClient(encoding='utf-8', shell = telnetlib3.TerminalShell)
    # create as many clients as we have hosts

    loop = asyncio.get_event_loop()
    loop.run_until_complete(
        register_telnet_command(loop, log, ClientFactory,
                                host = hostname, port = port,
                                command = "id"))
    return 0

main()
user5417363
  • 91
  • 2
  • 5
  • I figured it out; it is a very bad idea to redefine `connection_lost`; it is this method that is responsible for populating the `waiter_closed` attribute. – user5417363 Nov 14 '15 at 13:52

1 Answers1

1

Sorry, my mistake, redefining close_connection without calling the code from telnetlib3.connection_lost is a bad idea, since this is the code that populates waiter_closed.

I should have done

class MyClient(telnetlib3.TelnetClient):
    def connection_lost(self, *args):
        print("connection lost on client {} - args={}".format(self, args))
        super().connection_lost(*args)
user5417363
  • 91
  • 2
  • 5