-
Notifications
You must be signed in to change notification settings - Fork 610
Description
I'm using channel, created with libssh2_channel_direct_tcpip2(). Sometimes when the program writes a lot of data, writing process stops and all calls of libssh2_channel_write() returns LIBSSH2_ERROR_EAGAIN.
After some debug I found the reason and fix the problem:
There is key exchange procedure, that starts by _libssh2_transport_send().
Also the _libssh2_transport_send tryes to continue sending existing packet if any by calling send_existing().
send_existing() checks that we are trying to send the same packet that allready exists (if any). If packets are not the same, send_existing() exits with LIBSSH2_ERROR_EAGAIN.
But what happens if we need key exchange and send existing at the same time?
- _libssh2_transport_send() calls _libssh2_kex_exchange()
- _libssh2_kex_exchange() makes it's own packet and tryies to send it with _libssh2_transport_send()
- _libssh2_transport_send() calls send_existing()
- send_existing() compares new packet address and existing packet address. Test fails and we get LIBSSH2_ERROR_EAGAIN
- All subsequent write calls exits with LIBSSH2_ERROR_EAGAIN by this scheme
My suggestion is simply call send_existing() before _libssh2_kex_exchange() in _libssh2_transport_send(). That solves the problem.
To Reproduce
The bug is rather random. It's hard to reproduce. You need to create channel with libssh2_channel_direct_tcpip2() and write data as many as possible.
Expected behavior
Succesful write attempts sooner or latter.
Version:
- OS: Ubuntu 22.04 jammy
- Kernel: x86_64 Linux 6.8.0-83-generic
- libssh2 version: 1.11.1
- crypto backend and version: OpenSSL from repository
Additional context
Also I'm using read/write callbacks to run SSH session through custom IO layer, but it doesnt matter I gues.