Skip to content

Commit

Permalink
Allow non-TCP sockets to be passed in via the 'sock' option
Browse files Browse the repository at this point in the history
This commit guards against a setsockopt() failure when passing a
non-TCP socket (such as a socketpair) to AsyncSSH via the 'sock'
option. Thanks go to Christian Wendt for reporting this problem
and proposing a fix.
  • Loading branch information
ronf committed Sep 18, 2024
1 parent b244bb3 commit dcd1c61
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
4 changes: 3 additions & 1 deletion asyncssh/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1269,7 +1269,9 @@ def connection_made(self, transport: asyncio.BaseTransport) -> None:
if sock:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE,
self._tcp_keepalive)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

if sock.family in (socket.AF_INET, socket.AF_INET6):
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

sockname = cast(SockAddr, transport.get_extra_info('sockname'))

Expand Down
18 changes: 18 additions & 0 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,24 @@ async def test_connect_sock(self):
async with asyncssh.connect(sock=sock):
pass

@unittest.skipUnless(nc_available, 'Netcat not available')
@asynctest
async def test_connect_non_tcp_sock(self):
"""Test connecting using an non-TCP socket"""

sock1, sock2 = socket.socketpair()

proc = await asyncio.create_subprocess_exec(
'nc', str(self._server_addr), str(self._server_port),
stdin=sock1, stdout=sock1, stderr=sock1)

async with asyncssh.connect(
self._server_addr, self._server_port, sock=sock2):
pass

await proc.wait()
sock1.close()

@asynctest
async def test_run_client(self):
"""Test running an SSH client on an already-connected socket"""
Expand Down

0 comments on commit dcd1c61

Please sign in to comment.