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