-
Notifications
You must be signed in to change notification settings - Fork 169
Description
I see that in Sep 2023 a feature was added to allow port forwards to have an accept_handler so per-origin forwards could be decided. Great feature. I'm confused as to how it's implemented in the "_process_tcpip_forward_global_request" flow.
_finish_port_forward has listener = self._owner.server_requested(listen_host, listen_port), and then if that listener is callable (or an awaitable that yields a callable), passes it as the accept_handler to forward_local_port:
listener = await self.forward_local_port(
listen_host, listen_port,
listen_host, listen_port, listener)
This doesn't seem documented anywhere I can see. Docstring and type hinting for server_requested both indicate the return should be True, False, SSHListener, or an awaitable yielding one of those, but there even appears to be a test case checking that this works in test_forward:
class _TCPAcceptHandlerServer(Server):
"""Server for testing forwarding accept handler"""
async def server_requested(self, listen_host, listen_port):
"""Handle a request to create a new socket listener"""
def accept_handler(_orig_host: str, _orig_port: int) -> bool:
return True
return accept_handler
I'm digging into some stuff for other code I'm writing and this tripped me up: not a giant issue, but I thought some documentation might help clear up this slightly-obtuse path to declare an accept_handler. As a secondary issue, if you return a callable then it will not be used as the sshlistener (this would be a weird case where somebody, I guess, subclassed SSHListener and added a call method, hoping to do both?).