Subject: The problem with multiple channels

The problem with multiple channels

From: Daniel Stenberg <>
Date: Thu, 3 Jun 2010 14:54:19 +0200 (CEST)


Peter Stuge and I've been discussing back and forth on the shortcomings of our
API during the recent months and what we can do to overcome them. I intend to
present some ideas here. Don't get me wrong. I seriously believe our API
design in general is good, and we have a fine SSH library foundation compared
to others that exist. But there is still room for improvements!


The problem in a nutshell is that when an application opens up multiple
channels over a single session, those are all using the same socket. If the
application is then using select() to wait for traffic (like any sensible app
does) and wants to act on the data when select() tells there is something to
for example read, what does an application do?

With our current API, you have to loop over all the channels and read from
them to see if they have data. This effectively makes blocking reads
impossible. If the app has many channels in a setup like this, it even becomes
slow. (The original API had the libssh2_poll_channel_read() and libssh2_poll()
to somewhat overcome this hurdle, but they too have pretty much the same
problems plus a few others.)

Traffic in the other direction is similarly limited: the app has to try
sending to all channels, even though some of them may very well not accept any
data at that point.


I suggest we introduce two new helper functions:


  - Read "a bunch" of data from the given socket and returns information to the
    app about what channels that are now readable (ie they will not block when
    read from). The function can be called over and over and it will repeatedly
    return info about what channels that are readable at that moment.


  - Returns information about what channels that are writable, in the sense
    that they have windows set from the remote side that allows data to get
    sent. Writing to one of those channels will not block. Of course, the
    underlying socket may only accept a certain amount of data, so at the
    first short return, nothing more should be attempted to get sent until
    select() (or equivalent) has been used on the master socket again.

I haven't yet figured out a sensible API for how these functions should return
that info, but if we agree on the general principles I guess we can work that


   I wanted to mention that these two helper functions would not be mandatory
   in any way. They would just be there for those who want them, and existing
   programs can remain using the old functions only if they prefer to.


Received on 2010-06-03