Source code for asyncssh.listener
# Copyright (c) 2013-2015 by Ron Frederick <ronf@timeheart.net>.
# All rights reserved.
#
# This program and the accompanying materials are made available under
# the terms of the Eclipse Public License v1.0 which accompanies this
# distribution and is available at:
#
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Ron Frederick - initial implementation, API, and documentation
"""SSH listeners"""
import asyncio
from .channel import SSHTCPChannel
[docs]class SSHListener(asyncio.AbstractServer):
"""SSH listener for inbound TCP connections"""
[docs] def get_port(self):
"""Return the port number being listened on
This method returns the port number that the remote listener
was bound to. When the requested remote listening port is ``0``
to indicate a dynamic port, this method can be called to
determine what listening port was selected.
:returns: The port number being listened on
"""
raise NotImplementedError
[docs] def close(self):
"""Stop listening for new connections
This method can be called to stop listening for connections.
Existing connections will remain open.
"""
raise NotImplementedError
@asyncio.coroutine
[docs] def wait_closed(self):
"""Wait for the listener to close
This method is a coroutine which waits for the associated
TCP listeners to be closed.
"""
raise NotImplementedError
class SSHForwardListener(SSHListener):
"""A TCP listener used when forwarding traffic fromm local ports"""
def __init__(self, listen_port, servers):
self._listen_port = listen_port
self._servers = servers
def get_port(self):
return self._listen_port
def close(self):
for server in self._servers:
server.close()
self._servers = []
@asyncio.coroutine
def wait_closed(self):
for server in self._servers:
yield from server.wait_closed()
class SSHClientListener(SSHListener):
"""SSH client listener used to accept inbound forwarded connections"""
def __init__(self, conn, loop, session_factory, listen_host, listen_port,
encoding, window, max_pktsize):
self._conn = conn
self._loop = loop
self._session_factory = session_factory
self._listen_host = listen_host
self._listen_port = listen_port
self._encoding = encoding
self._window = window
self._max_pktsize = max_pktsize
self._waiters = []
def process_connection(self, orig_host, orig_port):
"""Process a forwarded TCP connection"""
chan = SSHTCPChannel(self._conn, self._loop, self._encoding,
self._window, self._max_pktsize)
chan.set_inbound_peer_names(self._listen_host, self._listen_port,
orig_host, orig_port)
return chan, self._session_factory(orig_host, orig_port)
def get_port(self):
return self._listen_port
def close(self):
asyncio.async(self._conn.close_client_listener(self, self._listen_host,
self._listen_port),
loop=self._loop)
self._conn = None
for waiter in self._waiters:
if not waiter.cancelled():
waiter.set_result(None)
@asyncio.coroutine
def wait_closed(self):
if self._conn:
waiter = asyncio.Future(loop=self._loop)
self._waiters.append(waiter)
yield from waiter