Asyncio problem, looking for advice.
Benjamin Risher
brisher777 at gmail.com
Thu Nov 27 09:27:05 EST 2014
Hello all,
I'm working on a project to learn asyncio and network programming. What I'm trying to do is forward a connection from myself to another machine. Kind of like an asynchronous python implementation of fpipe.
In a nutshell:
1 --> start a server listening on localhost
2 --> connect to server
3 --> server connects to a listening service (ssh for instance)
4 --> server handles both connections to pass traffic back and forth through each
What I have now *kind of* works. It sends data back and forth, but when I ssh to localhost -p 12345, i never get the password prompt. It looks like one packet hangs out and doesn't get sent from what I saw in tcpdump.
Any help would be greatly appreciated.
Here's a link to the same code as below, just with syntax highlighting etc...
http://pastebin.com/iLE4GZH3
import asyncio
import logging
class MyServer:
def __init__(self, loop):
self.server = None
self.loop = loop
self.clients = dict()
self.log = logging.getLogger(__name__)
def _accept_client(self, client_reader, client_writer):
""" Client initially drops in here """
task = asyncio.Task(self._handle_client(client_reader, client_writer))
self.clients[task] = (client_reader, client_writer)
def client_done(task):
self.clients[task][1].close() # closes the StreamWriter that was part of the task
del self.clients[task]
self.log.info("New connection.")
task.add_done_callback(client_done)
@asyncio.coroutine
def _handle_client(self, client_reader, client_writer):
""" Try to connect to port 22 and broker between 2 connections.
:param client_reader: StreamReader object
:param client_writer: StreamWriter object
"""
reader, writer = yield from asyncio.async(asyncio.open_connection('localhost', 22))
while True:
client_data = yield from asyncio.async(self.read_data(client_reader))
if client_data:
writer.write(client_data)
yield from writer.drain()
server_data = yield from asyncio.async(self.read_data(reader))
if server_data:
client_writer.write(server_data)
yield from client_writer.drain()
@asyncio.coroutine
def read_data(self, reader):
data = None
while True:
print('top of while')
data = yield from asyncio.Task(reader.read(2048))
return data
def start(self):
""" start the server listening on 12345 """
self.server = self.loop.run_until_complete(
asyncio.streams.start_server(
self._accept_client, # client_connected_callback
'localhost', # host
12345, # port
loop=self.loop # loop
)
)
def stop(self):
if self.server:
self.server.close()
self.loop.run_until_complete(self.server.wait_closed())
self.server = None
if __name__ == '__main__':
loop = asyncio.get_event_loop()
my_server = MyServer(loop)
my_server.start()
loop.run_forever()
my_server.stop()
More information about the Python-list
mailing list