On 10/18/2013 11:49 PM, Daniel Stenberg wrote:
> On Thu, 17 Oct 2013, Salvador Fandino wrote:
> 
>> In summary, the conclusion I get from these results is that
>> LIBSSH2_CHANNEL_WINDOW_DEFAULT value should be increased to 1 or 2 MB.
> 
> I can only agree. You up to making a patch with that change and parts of
> your great explanation here in the commit message to help future
> hackers? I think it makes sense to pick OpenSSH's default here.


Here is another run of patches.

I have gone a bit further and, besides increasing the default window
size to 2MB, I have also added two new slots into the session structure
channel_window_size and channel_packet_size that are used as the default
values for new channels.

The issue I try to avoid is that the window and packet sizes are not
always settable with the current API. I.e. they can not be set for
"tcp-ip" channels or for those created implicitly as for instance,
reverse tunnels.

The most controversial change is the way those new parameters are set as
I have added a new unified interface for setting/retrieving all the
session parameters "libssh2_session_config_(set|get)" and deprecated
"libssh2_session_flag" and
"libssh2_session_(set|get)_(timeout|blocking)". A more detailed
explanation is on the commit message.

The alternative would be to use a pair of functions to set/get every
parameter. I don't have a strong preference for one way or the other. My
only point is that the API should be consistent in the way those
accessors work.

In any case, IMO, patches 1 an 2 can be applied right now as they
implement changes we have already discussed.


>From 0404db14b41d2c6c96cb26129b038785019da917 Mon Sep 17 00:00:00 2001
From: Salvador <sfandino-/[email protected]>
Date: Wed, 16 Oct 2013 13:31:31 +0200
Subject: [PATCH 1/5] Honour window_size_initial from _libssh2_channel_read

_libssh2_channel_read was using an arbitrary hard-coded limit to
trigger the window adjusting code. The adjustment used was also
hard-coded and arbitrary, 15MB actually, which would limit the
usability of libssh2 on systems with little RAM.

This patch, uses the window_size parameter passed to
libssh2_channel_open_ex (stored as remote.window_size_initial)
plus the buflen as the base for the trigger and the adjustment
calculation.

The memory usage when using the default window size is reduced
from 22MB to 256KB per channel (actually, if compression is
used, these numbers should be incremented by ~50% to account
for the errors between the decompressed packet sizes and the
predicted sizes).

My tests indicate that this change does not impact the
performance of transfers across localhost or a LAN, being it
on par with that of OpenSSH. On the other hand, it will probably
slow down transfers on networks with high bandwidth*delay when
the default window size (LIBSSH2_CHANNEL_WINDOW_DEFAULT=256KB)
is used.

Signed-off-by: Salvador Fandino <[email protected]>
---
 src/channel.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/channel.c b/src/channel.c
index 9df2f8d..d6bfb98 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1761,14 +1761,17 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
                    stream_id);
 
     /* expand the receiving window first if it has become too narrow */
-    if((channel->read_state == libssh2_NB_state_jump1) ||
-       (channel->remote.window_size < (LIBSSH2_CHANNEL_WINDOW_DEFAULT*30))) {
+    if( (channel->read_state == libssh2_NB_state_jump1) ||
+        (channel->remote.window_size < channel->remote.window_size_initial / 4 * 3 + buflen) ) {
+
+        uint32_t adjustment = channel->remote.window_size_initial + buflen - channel->remote.window_size;
+        if (adjustment < LIBSSH2_CHANNEL_MINADJUST)
+            adjustment = LIBSSH2_CHANNEL_MINADJUST;
 
         /* the actual window adjusting may not finish so we need to deal with
            this special state here */
         channel->read_state = libssh2_NB_state_jump1;
-        rc = _libssh2_channel_receive_window_adjust(channel,
-                                                    (LIBSSH2_CHANNEL_WINDOW_DEFAULT*60),
+        rc = _libssh2_channel_receive_window_adjust(channel, adjustment,
                                                     0, NULL);
         if (rc)
             return rc;
-- 
1.8.3.2

>From 59df29ae35c8c59c0d18ccc9852bcd9f55aa6944 Mon Sep 17 00:00:00 2001
From: Salvador Fandino <[email protected]>
Date: Mon, 21 Oct 2013 11:58:55 +0200
Subject: [PATCH 2/5] Set default window size to 2MB

The default channel window size used until now was 256KB. This value is
too small and results on a bottleneck on real-life networks where
round-trip delays can easily reach 300ms.

The issue was not visible because the configured channel window size
was being ignored and a hard-coded value of ~22MB being used instead,
but that was fixed on a previous commit.

This patch just changes the default window size
(LIBSSH2_CHANNEL_WINDOW_DEFAULT) to 2MB. It is the same value used by
OpenSSH and in our opinion represents a good compromise between memory
used and transfer speed.

Performance tests were run to determine the optimum value. The details
and related discussion are available from the following thread on the
libssh2 mailing-list:

http://www.libssh2.org/mail/libssh2-devel-archive-2013-10/0018.shtml
http://article.gmane.org/gmane.network.ssh.libssh2.devel/6543

An excerpt follows:

"I have been running some transfer test and measuring their speed.

My setup was composed of a quad-core Linux machine running Ubuntu 13.10
x86_64 with a LXC container inside. The data transfers were performed
from the container to the host (never crossing through a physical
network device).

Network delays were simulated using the tc tool. And ping was used to
verify that they worked as intended during the tests.

The operation performed was the equivalent to the following ssh command:

  $ ssh container "dd bs=16K count=8K if=/dev/zero" >/dev/null

Though, establishment and closing of the SSH connection was excluded
from the timings.

I run the tests several times transferring files of sizes up to 128MB
and the results were consistent between runs.

The results corresponding to the 128MB transfer are available here:

https://docs.google.com/spreadsheet/ccc?key=0Ao1yRmX6PQQzdG5wSFlrZl9HRWNET3ZyN0hnaGo5ZFE&usp=sharing

It clearly shows that 256KB is too small as the default window size.
Moving to a 512MB generates a great improvement and after the 1MB mark
the returns rapidly diminish. Other factors (TCP window size, probably)
become more limiting than the channel window size

For comparison I also performed the same transfers using OpenSSH. Its
speed is usually on par with that of libssh2 using a window size of 1MB
(even if it uses a 2MB window, maybe it is less aggressive sending the
window adjust msgs)."

Signed-off-by: Salvador Fandino <[email protected]>
---
 include/libssh2.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/libssh2.h b/include/libssh2.h
index 1b0d690..56cb9a1 100644
--- a/include/libssh2.h
+++ b/include/libssh2.h
@@ -593,7 +593,7 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds,
                              long timeout);
 
 /* Channel API */
-#define LIBSSH2_CHANNEL_WINDOW_DEFAULT  (256*1024)
+#define LIBSSH2_CHANNEL_WINDOW_DEFAULT  (2*1024*1024)
 #define LIBSSH2_CHANNEL_PACKET_DEFAULT  32768
 #define LIBSSH2_CHANNEL_MINADJUST       1024
 
-- 
1.8.3.2

>From 4a692b4d1158b0ac3bcdb821d8a711301fb85cb4 Mon Sep 17 00:00:00 2001
From: Salvador Fandino <[email protected]>
Date: Mon, 21 Oct 2013 12:59:02 +0200
Subject: [PATCH 3/5] Set channel window and packet size from configurable
 values on the session object

Currently, the channel and packet window sizes can only be configured when
"libssh2_channel_open_ex" is used to create the channel. Unfortunatelly
this is not always an option. For instance, for some channel types
(i.e. tcp-ip) a different function must be used; in other cases, the
channel is not created explicitly by the user.

This patch adds two new slots into the session structure to
store the default window and packet sizes. Every channel created in
this session will use these values by default (unless a set of different
ones are explicitly set).

A new pair of constants (LIBSSH2_CHANNEL_WINDOW_CONFIGURED and
LIBSSH2_CHANNEL_PACKET_CONFIGURED) are also defined. These can be used
on function calls were the packet and/or window size are passed
to indicate that the configured values are to be used.

Note that this patch does not introduce any way to set or change
the values on the session object yet.

Signed-off-by: Salvador Fandino <[email protected]>
---
 include/libssh2.h  |  6 ++++--
 src/channel.c      | 10 ++++++++--
 src/libssh2_priv.h |  4 ++++
 src/packet.c       | 14 ++++++++------
 src/session.c      |  2 ++
 5 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/include/libssh2.h b/include/libssh2.h
index 56cb9a1..ea6d449 100644
--- a/include/libssh2.h
+++ b/include/libssh2.h
@@ -594,7 +594,9 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds,
 
 /* Channel API */
 #define LIBSSH2_CHANNEL_WINDOW_DEFAULT  (2*1024*1024)
+#define LIBSSH2_CHANNEL_WINDOW_CONFIGURED (~(unsigned int)0)
 #define LIBSSH2_CHANNEL_PACKET_DEFAULT  32768
+#define LIBSSH2_CHANNEL_PACKET_CONFIGURED (~(unsigned int)0)
 #define LIBSSH2_CHANNEL_MINADJUST       1024
 
 /* Extended Data Handling */
@@ -615,8 +617,8 @@ libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *channel_type,
 
 #define libssh2_channel_open_session(session) \
   libssh2_channel_open_ex((session), "session", sizeof("session") - 1, \
-                          LIBSSH2_CHANNEL_WINDOW_DEFAULT, \
-                          LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0)
+                          LIBSSH2_CHANNEL_WINDOW_CONFIGURED, \
+                          LIBSSH2_CHANNEL_PACKET_CONFIGURED, NULL, 0)
 
 LIBSSH2_API LIBSSH2_CHANNEL *
 libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, const char *host,
diff --git a/src/channel.c b/src/channel.c
index d6bfb98..b208530 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -154,6 +154,12 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
         memset(&session->open_packet_requirev_state, 0,
                sizeof(session->open_packet_requirev_state));
 
+        if (window_size == LIBSSH2_CHANNEL_WINDOW_CONFIGURED)
+            window_size = session->channel_window_size;
+
+        if (packet_size == LIBSSH2_CHANNEL_PACKET_CONFIGURED)
+            packet_size = session->channel_packet_size;
+
         _libssh2_debug(session, LIBSSH2_TRACE_CONN,
                        "Opening Channel - win %d pack %d", window_size,
                        packet_size);
@@ -375,8 +381,8 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host,
     channel =
         _libssh2_channel_open(session, "direct-tcpip",
                               sizeof("direct-tcpip") - 1,
-                              LIBSSH2_CHANNEL_WINDOW_DEFAULT,
-                              LIBSSH2_CHANNEL_PACKET_DEFAULT,
+                              session->channel_window_size,
+                              session->channel_packet_size,
                               session->direct_message,
                               session->direct_message_len);
 
diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h
index 461d14c..b901316 100644
--- a/src/libssh2_priv.h
+++ b/src/libssh2_priv.h
@@ -638,6 +638,10 @@ struct _LIBSSH2_SESSION
     void* tracehandler_context; /* context for the trace handler */
 #endif
 
+    /* configured values */
+    unsigned int channel_window_size;
+    unsigned int channel_packet_size;
+
     /* State variables used in libssh2_banner_send() */
     libssh2_nonblocking_states banner_TxRx_state;
     char banner_TxRx_banner[256];
diff --git a/src/packet.c b/src/packet.c
index 47bbf2b..94df7bf 100644
--- a/src/packet.c
+++ b/src/packet.c
@@ -172,11 +172,11 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
 
                     channel->remote.id = listen_state->sender_channel;
                     channel->remote.window_size_initial =
-                        LIBSSH2_CHANNEL_WINDOW_DEFAULT;
+                        session->channel_window_size;
                     channel->remote.window_size =
-                        LIBSSH2_CHANNEL_WINDOW_DEFAULT;
+                        session->channel_window_size;
                     channel->remote.packet_size =
-                        LIBSSH2_CHANNEL_PACKET_DEFAULT;
+                        session->channel_packet_size;
 
                     channel->local.id = _libssh2_channel_nextid(session);
                     channel->local.window_size_initial =
@@ -323,9 +323,11 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
 
             channel->remote.id = x11open_state->sender_channel;
             channel->remote.window_size_initial =
-                LIBSSH2_CHANNEL_WINDOW_DEFAULT;
-            channel->remote.window_size = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
-            channel->remote.packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT;
+                session->channel_window_size;
+            channel->remote.window_size =
+                session->channel_window_size;
+            channel->remote.packet_size =
+                session->channel_packet_size;
 
             channel->local.id = _libssh2_channel_nextid(session);
             channel->local.window_size_initial =
diff --git a/src/session.c b/src/session.c
index 9838d2b..e00b132 100644
--- a/src/session.c
+++ b/src/session.c
@@ -493,6 +493,8 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
         session->send = _libssh2_send;
         session->recv = _libssh2_recv;
         session->abstract = abstract;
+        session->channel_window_size = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
+        session->channel_packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT;
         session->api_timeout = 0; /* timeout-free API by default */
         session->api_block_mode = 1; /* blocking API by default */
         _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
-- 
1.8.3.2

>From 040409112882844176f744892d0c55d2bf5d4129 Mon Sep 17 00:00:00 2001
From: Salvador Fandino <[email protected]>
Date: Mon, 21 Oct 2013 17:09:06 +0200
Subject: [PATCH 4/5] add functions libssh2_session_config_(set|get)

There are several session parameters that can be reconfigured by the
user (compress, sigpipe, blocking, timeout and channel window and
packet size).

Currently, libssh2 lacks an uniform way to manipulate those
parameters. For "compress" and "sigpipe" "libssh2_session_flag" is
available which allows to change but not to retrieve these flags
values. For "blocking" and "timeout" there are
"libssh2_session_(set|get}_(blocking|timeout)" functions available,
though "libssh2_session_set_blocking" returns the old blocking setting
while "libssh2_session_set_timeout" is a void function.

The new "libssh2_session_config_set" and "libssh2_session_config_get"
functions provide a uniform interface for setting and getting
respectively the configurable session parameters.

A new set of constants to be used as the selector keys are also
defined (they are LIBSSH2_SESSION_CONFIG_SIGPIPE,
LIBSSH2_SESSION_CONFIG_COMPRESS,
LIBSSH2_SESSION_CONFIG_CHANNEL_WINDOW_SIZE,
LIBSSH2_SESSION_CONFIG_CHANNEL_PACKET_SIZE,
LIBSSH2_SESSION_CONFIG_TIMEOUT and LIBSSH2_SESSION_CONFIG_BLOCKING).

Signed-off-by: Salvador Fandino <[email protected]>
---
 docs/Makefile.am                    |   2 +
 docs/libssh2_session_config_get.3   |  27 ++++++++
 docs/libssh2_session_config_set.3   |  65 +++++++++++++++++
 docs/libssh2_session_flag.3         |   4 ++
 docs/libssh2_session_get_blocking.3 |   4 ++
 docs/libssh2_session_get_timeout.3  |   5 ++
 docs/libssh2_session_set_blocking.3 |   4 ++
 docs/libssh2_session_set_timeout.3  |   5 ++
 include/libssh2.h                   |  43 ++++++++----
 src/channel.c                       |   4 +-
 src/session.c                       | 135 +++++++++++++++++-------------------
 src/session.h                       |   3 -
 12 files changed, 215 insertions(+), 86 deletions(-)
 create mode 100644 docs/libssh2_session_config_get.3
 create mode 100644 docs/libssh2_session_config_set.3

diff --git a/docs/Makefile.am b/docs/Makefile.am
index e6ab394..a2196e5 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -96,6 +96,8 @@ dist_man_MANS = \
 	libssh2_session_banner_set.3 \
 	libssh2_session_block_directions.3 \
 	libssh2_session_callback_set.3 \
+	libssh2_session_config_set.3 \
+	libssh2_session_config_get.3 \
 	libssh2_session_disconnect.3 \
 	libssh2_session_disconnect_ex.3 \
 	libssh2_session_flag.3 \
diff --git a/docs/libssh2_session_config_get.3 b/docs/libssh2_session_config_get.3
new file mode 100644
index 0000000..e2fd6b6
--- /dev/null
+++ b/docs/libssh2_session_config_get.3
@@ -0,0 +1,27 @@
+.TH libssh2_session_config_get 3 "21 Oct 2013" "libssh2 1.4.4" "libssh2 manual"
+.SH NAME
+libssh2_session_config_get - get configurable session parameters
+.SH SYNOPSIS
+#include <libssh2.h>
+
+unsigned long
+libssh2_session_config_get(LIBSSH2_SESSION *session, int key);
+
+.SH DESCRIPTION
+This function returns the current value for the configurable parameter
+given by \fIkey\fP.
+
+See
+.BR libssh2_session_config_set(3)
+for the list of available parameters.
+
+.SH RETURN VALUE
+Returns the value of the given parameter.
+
+.SH AVAILABILITY
+This function has been available since version 1.4.4.
+
+.SH SEE ALSO
+
+.BR libssh2_session_config_set(3)
+
diff --git a/docs/libssh2_session_config_set.3 b/docs/libssh2_session_config_set.3
new file mode 100644
index 0000000..27ed16b
--- /dev/null
+++ b/docs/libssh2_session_config_set.3
@@ -0,0 +1,65 @@
+.TH libssh2_session_config_set 3 "21 Oct 2013" "libssh2 1.4.4" "libssh2 manual"
+.SH NAME
+libssh2_session_config_set - set configurable session parameters
+.SH SYNOPSIS
+#include <libssh2.h>
+
+unsigned long
+libssh2_session_config_set(LIBSSH2_SESSION *session, int key, unsigned long value);
+
+.SH DESCRIPTION
+This function allows one to set the session configurable
+parameters. \fIkey\fP is the parameter to set, and \fIvalue\fP is its
+new value.
+
+.SH KEYS
+The parameters that can be currently set are as follows:
+
+.IP LIBSSH2_SESSION_CONFIG_BLOCKING
+Sets or clears the session blocking mode. This will instantly affect any
+channels associated with this session.
+
+If a read is performed on a session with no data currently available,
+a blocking session will wait for data to arrive and return what it
+receives. A non-blocking session will return immediately with an empty
+buffer.
+
+If a write is performed on a session with no room for more data, a
+blocking session will wait for room.  A non-blocking session will
+return immediately without writing anything.
+
+.IP LIBSSH2_SESSION_CONFIG_SIGPIPE
+If set to a true value, libssh2 will not attempt to block SIGPIPEs but
+will let them trigger from the underlying socket layer.
+
+.IP LIBSSH2_SESSION_CONFIG_COMPRESS
+If set to a true value before the connection handshake is performed,
+libssh2 will try to use compression for the session negotiating it
+with the server.
+
+libssh2 does not attempt to use compression by default.
+
+.IP LIBSSH2_SESSION_TIMEOUT
+Sets the session timeout in miliseconds. The timeout repressents for
+how long a blocking libssh2 function call may wait before failing with
+a LIBSSH2_ERROR_TIMEOUT error.
+
+.IP LIBSSH2_SESSION_CHANNEL_WINDOW_SIZE
+Sets the window size in bytes used for new created channels. The
+default value is 2MB.
+
+.IP LIBSSH2_SESSION_CHANNEL_PACKET_SIZE
+Sets the maximum packet size in bytes for new created channels. The
+default value is 32KB.
+
+.SH RETURN VALUE
+Returns the value the parameter had previously.
+
+.SH AVAILABILITY
+This function has been available since version 1.4.4.
+
+.SH SEE ALSO
+.BR libssh2_session_config_get(3) ,
+.BR libssh2_session_flag(3) ,
+.BR libssh2_session_set_blocking(3) ,
+.BR libssh2_session_set_timeout(3) .
diff --git a/docs/libssh2_session_flag.3 b/docs/libssh2_session_flag.3
index 3a9e5e5..e52baad 100644
--- a/docs/libssh2_session_flag.3
+++ b/docs/libssh2_session_flag.3
@@ -5,6 +5,10 @@ libssh2_session_flag - TODO
 int
 libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int value);
 .SH DESCRIPTION
+
+This function is deprecated. Use the
+\fIlibssh2_session_config_set(3)\fP function instead!
+
 Set options for the created session. \fIflag\fP is the option to set, while
 \fIvalue\fP is typically set to 1 or 0 to enable or disable the option.
 .SH FLAGS
diff --git a/docs/libssh2_session_get_blocking.3 b/docs/libssh2_session_get_blocking.3
index 8d98fa3..f1f02af 100644
--- a/docs/libssh2_session_get_blocking.3
+++ b/docs/libssh2_session_get_blocking.3
@@ -4,6 +4,10 @@ libssh2_session_get_blocking - TODO
 .SH SYNOPSIS
 int libssh2_session_get_blocking(LIBSSH2_SESSION *session);
 .SH DESCRIPTION
+
+This function is deprecated. Use the
+\fIlibssh2_session_config_get(3)\fP function instead!
+
 Returns 0 if the state of the session has previously be set to non-blocking
 and it returns 1 if the state was set to blocking.
 .SH RETURN VALUE
diff --git a/docs/libssh2_session_get_timeout.3 b/docs/libssh2_session_get_timeout.3
index 94aacd6..4e6f2ad 100644
--- a/docs/libssh2_session_get_timeout.3
+++ b/docs/libssh2_session_get_timeout.3
@@ -5,7 +5,12 @@ libssh2_session_get_timeout - get the timeout for blocking functions
 #include <libssh2.h>
 .nf
 long libssh2_session_get_timeout(LIBSSH2_SESSION *session);
+
 .SH DESCRIPTION
+
+This function is deprecated. Use the
+\fIlibssh2_session_config_get(3)\fP function instead!
+
 Returns the \fBtimeout\fP (in milliseconds) for how long a blocking the
 libssh2 function calls may wait until they consider the situation an error and
 return LIBSSH2_ERROR_TIMEOUT.
diff --git a/docs/libssh2_session_set_blocking.3 b/docs/libssh2_session_set_blocking.3
index b16e009..d7ba251 100644
--- a/docs/libssh2_session_set_blocking.3
+++ b/docs/libssh2_session_set_blocking.3
@@ -8,6 +8,10 @@ void
 libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking);
 
 .SH DESCRIPTION
+
+This function is deprecated. Use the
+\fIlibssh2_session_config_set(3)\fP function instead!
+
 \fIsession\fP - session instance as returned by 
 .BR libssh2_session_init_ex(3)
 
diff --git a/docs/libssh2_session_set_timeout.3 b/docs/libssh2_session_set_timeout.3
index 2d4f10f..56fa02b 100644
--- a/docs/libssh2_session_set_timeout.3
+++ b/docs/libssh2_session_set_timeout.3
@@ -5,7 +5,12 @@ libssh2_session_set_timeout - set timeout for blocking functions
 #include <libssh2.h>
 .nf
 void libssh2_session_set_timeout(LIBSSH2_SESSION *session, long timeout);
+
 .SH DESCRIPTION
+
+This function is deprecated. Use the
+\fIlibssh2_session_config_set(3)\fP function instead!
+
 Set the \fBtimeout\fP in milliseconds for how long a blocking the libssh2
 function calls may wait until they consider the situation an error and return
 LIBSSH2_ERROR_TIMEOUT.
diff --git a/include/libssh2.h b/include/libssh2.h
index ea6d449..01ec0fe 100644
--- a/include/libssh2.h
+++ b/include/libssh2.h
@@ -267,9 +267,17 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE
 #define LIBSSH2_METHOD_LANG_CS      8
 #define LIBSSH2_METHOD_LANG_SC      9
 
-/* flags */
-#define LIBSSH2_FLAG_SIGPIPE        1
-#define LIBSSH2_FLAG_COMPRESS       2
+/* configurable keys */
+#define LIBSSH2_SESSION_CONFIG_SIGPIPE      1
+#define LIBSSH2_SESSION_CONFIG_COMPRESS     2
+#define LIBSSH2_SESSION_CONFIG_CHANNEL_WINDOW_SIZE 3
+#define LIBSSH2_SESSION_CONFIG_CHANNEL_PACKET_SIZE 4
+#define LIBSSH2_SESSION_CONFIG_TIMEOUT      5
+#define LIBSSH2_SESSION_CONFIG_BLOCKING     6
+
+/* flags, obsolete */
+#define LIBSSH2_FLAG_SIGPIPE        LIBSSH2_SESSION_CONFIG_SIGPIPE
+#define LIBSSH2_FLAG_COMPRESS       LIBSSH2_SESSION_CONFIG_COMPRESS
 
 typedef struct _LIBSSH2_SESSION                     LIBSSH2_SESSION;
 typedef struct _LIBSSH2_CHANNEL                     LIBSSH2_CHANNEL;
@@ -503,8 +511,6 @@ LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session,
 LIBSSH2_API int libssh2_session_last_errno(LIBSSH2_SESSION *session);
 LIBSSH2_API int libssh2_session_block_directions(LIBSSH2_SESSION *session);
 
-LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag,
-                                     int value);
 LIBSSH2_API const char *libssh2_session_banner_get(LIBSSH2_SESSION *session);
 
 /* Userauth API */
@@ -738,17 +744,30 @@ libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel,
 #define libssh2_channel_window_write(channel) \
   libssh2_channel_window_write_ex((channel), NULL)
 
-LIBSSH2_API void libssh2_session_set_blocking(LIBSSH2_SESSION* session,
-                                              int blocking);
-LIBSSH2_API int libssh2_session_get_blocking(LIBSSH2_SESSION* session);
+LIBSSH2_API unsigned long libssh2_session_config_set(LIBSSH2_SESSION *session,
+                                                     int key, unsigned long value);
+
+LIBSSH2_API unsigned long libssh2_session_config_get(LIBSSH2_SESSION *session,
+                                                     int key);
+
+#define libssh2_session_set_blocking(session, blocking) \
+  libssh2_session_config_set((session), LIBSSH2_SESSION_CONFIG_BLOCKING, (blocking))
+
+#define libssh2_session_get_blocking(session) \
+  libssh2_session_config_get((session), LIBSSH2_SESSION_CONFIG_BLOCKING)
+
+#define libssh2_session_set_timeout(session, timeout) \
+  libssh2_session_config_set((session), LIBSSH2_SESSION_CONFIG_TIMEOUT, (timeout))
+
+#define libssh2_session_get_timeout(session) \
+  libssh2_session_config_get((session), LIBSSH2_SESSION_CONFIG_TIMEOUT)
+
+#define libssh2_session_flag(session, flag, value) \
+  (libssh2_session_config_set((session), (flag), (value)), 1)
 
 LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel,
                                               int blocking);
 
-LIBSSH2_API void libssh2_session_set_timeout(LIBSSH2_SESSION* session,
-                                             long timeout);
-LIBSSH2_API long libssh2_session_get_timeout(LIBSSH2_SESSION* session);
-
 /* libssh2_channel_handle_extended_data is DEPRECATED, do not use! */
 LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
                                                       int ignore_mode);
diff --git a/src/channel.c b/src/channel.c
index b208530..f5c6092 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1360,7 +1360,9 @@ LIBSSH2_API void
 libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking)
 {
     if(channel)
-        (void) _libssh2_session_set_blocking(channel->session, blocking);
+        (void) libssh2_session_config_set(channel->session,
+                                          LIBSSH2_SESSION_CONFIG_BLOCKING,
+                                          blocking);
 }
 
 /*
diff --git a/src/session.c b/src/session.c
index e00b132..769d5ed 100644
--- a/src/session.c
+++ b/src/session.c
@@ -1269,88 +1269,83 @@ libssh2_session_last_errno(LIBSSH2_SESSION * session)
     return session->err_code;
 }
 
-/* libssh2_session_flag
+/* libssh2_session_config_set 
  *
- * Set/Get session flags
- *
- * Return error code.
+ * Sets the configurable value for the given session setting. Returns
+ * the previous value.
  */
-LIBSSH2_API int
-libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value)
+
+LIBSSH2_API unsigned long
+libssh2_session_config_set(LIBSSH2_SESSION *session, int key, unsigned long value)
 {
-    switch(flag) {
-    case LIBSSH2_FLAG_SIGPIPE:
-        session->flag.sigpipe = value;
+    unsigned int old = 0;
+    switch (key) {
+    case LIBSSH2_SESSION_CONFIG_BLOCKING:
+        old = session->api_block_mode;
+        session->api_block_mode = (value ? 1: 0);
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Setting blocking mode %s, was %s",
+                       (value ? "ON" : "OFF"),
+                       (old ? "ON" : "OFF") );
+        break;
+    case LIBSSH2_SESSION_CONFIG_SIGPIPE:
+        old = session->flag.sigpipe;
+        session->flag.sigpipe = (value ? 1 : 0);
+        break;
+    case LIBSSH2_SESSION_CONFIG_COMPRESS:
+        old = session->flag.compress;
+        session->flag.compress = (value ? 1 : 0);
         break;
-    case LIBSSH2_FLAG_COMPRESS:
-        session->flag.compress = value;
+    case LIBSSH2_SESSION_CONFIG_CHANNEL_WINDOW_SIZE:
+        old = session->channel_window_size;
+        session->channel_window_size = value;
+        break;
+    case LIBSSH2_SESSION_CONFIG_CHANNEL_PACKET_SIZE:
+        old = session->channel_packet_size;
+        session->channel_packet_size = value;
+        break;
+    case LIBSSH2_SESSION_CONFIG_TIMEOUT:
+        old = session->api_timeout;
+        session->api_timeout = value;
         break;
     default:
-        /* unknown flag */
-        return LIBSSH2_ERROR_INVAL;
+        old = 0;
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Error, can't set config, unknown setting %d, value %lu",
+                       key, value);
     }
-
-    return LIBSSH2_ERROR_NONE;
+    return old;
 }
 
-/* _libssh2_session_set_blocking
- *
- * Set a session's blocking mode on or off, return the previous status when
- * this function is called. Note this function does not alter the state of the
- * actual socket involved.
+/* libssh2_session_config_get
+ * 
+ * Returns the current value for the given session configurable
+ * setting
  */
-int
-_libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking)
-{
-    int bl = session->api_block_mode;
-    _libssh2_debug(session, LIBSSH2_TRACE_CONN,
-                   "Setting blocking mode %s", blocking?"ON":"OFF");
-    session->api_block_mode = blocking;
 
-    return bl;
-}
-
-/* libssh2_session_set_blocking
- *
- * Set a channel's blocking mode on or off, similar to a socket's
- * fcntl(fd, F_SETFL, O_NONBLOCK); type command
- */
-LIBSSH2_API void
-libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking)
+LIBSSH2_API unsigned long
+libssh2_session_config_get(LIBSSH2_SESSION *session, int key)
 {
-    (void) _libssh2_session_set_blocking(session, blocking);
-}
-
-/* libssh2_session_get_blocking
- *
- * Returns a session's blocking mode on or off
- */
-LIBSSH2_API int
-libssh2_session_get_blocking(LIBSSH2_SESSION * session)
-{
-    return session->api_block_mode;
-}
-
-
-/* libssh2_session_set_timeout
- *
- * Set a session's timeout (in msec) for blocking mode,
- * or 0 to disable timeouts.
- */
-LIBSSH2_API void
-libssh2_session_set_timeout(LIBSSH2_SESSION * session, long timeout)
-{
-    session->api_timeout = timeout;
-}
-
-/* libssh2_session_get_timeout
- *
- * Returns a session's timeout, or 0 if disabled
- */
-LIBSSH2_API long
-libssh2_session_get_timeout(LIBSSH2_SESSION * session)
-{
-    return session->api_timeout;
+    unsigned int old = 0;
+    switch (key) {
+    case LIBSSH2_SESSION_CONFIG_BLOCKING:
+        return session->api_block_mode;
+    case LIBSSH2_SESSION_CONFIG_SIGPIPE:
+        return session->flag.sigpipe;
+    case LIBSSH2_SESSION_CONFIG_COMPRESS:
+        return session->flag.compress;
+    case LIBSSH2_SESSION_CONFIG_CHANNEL_WINDOW_SIZE:
+        return session->channel_window_size;
+    case LIBSSH2_SESSION_CONFIG_CHANNEL_PACKET_SIZE:
+        return session->channel_packet_size;
+    case LIBSSH2_SESSION_CONFIG_TIMEOUT:
+        return session->api_timeout;
+    default:
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Error, can't get config, unknown setting %d",
+                       key);
+        return 0;
+    }
 }
 
 /*
diff --git a/src/session.h b/src/session.h
index aff4f2c..77aa4fa 100644
--- a/src/session.h
+++ b/src/session.h
@@ -87,7 +87,4 @@
 
 int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t entry_time);
 
-/* this is the lib-internal set blocking function */
-int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking);
-
 #endif /* LIBSSH2_SESSION_H */
-- 
1.8.3.2

>From 99c50ad042a968ef6a4a6bc27f97fc6835bc18c6 Mon Sep 17 00:00:00 2001
From: Salvador Fandino <[email protected]>
Date: Mon, 21 Oct 2013 17:22:10 +0200
Subject: [PATCH 5/5] modify examples to use the new
 libssh2_session_config_(set|get) functions

Signed-off-by: Salvador Fandino <[email protected]>
---
 example/direct_tcpip.c        | 2 +-
 example/scp_nonblock.c        | 2 +-
 example/scp_write_nonblock.c  | 2 +-
 example/sftp.c                | 2 +-
 example/sftp_RW_nonblock.c    | 2 +-
 example/sftp_append.c         | 2 +-
 example/sftp_mkdir.c          | 2 +-
 example/sftp_mkdir_nonblock.c | 2 +-
 example/sftp_nonblock.c       | 2 +-
 example/sftp_write.c          | 2 +-
 example/sftp_write_nonblock.c | 2 +-
 example/sftp_write_sliding.c  | 2 +-
 example/sftpdir.c             | 2 +-
 example/sftpdir_nonblock.c    | 2 +-
 example/ssh2_echo.c           | 2 +-
 example/ssh2_exec.c           | 2 +-
 example/tcpip-forward.c       | 2 +-
 17 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/example/direct_tcpip.c b/example/direct_tcpip.c
index e530199..513219f 100644
--- a/example/direct_tcpip.c
+++ b/example/direct_tcpip.c
@@ -210,7 +210,7 @@ int main(int argc, char *argv[])
     }
 
     /* Must use non-blocking IO hereafter due to the current libssh2 API */
-    libssh2_session_set_blocking(session, 0);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 0);
 
     while (1) {
         FD_ZERO(&fds);
diff --git a/example/scp_nonblock.c b/example/scp_nonblock.c
index 5d636c0..eddaa9e 100644
--- a/example/scp_nonblock.c
+++ b/example/scp_nonblock.c
@@ -142,7 +142,7 @@ int main(int argc, char *argv[])
         return -1;
 
     /* Since we have set non-blocking, tell libssh2 we are non-blocking */
-    libssh2_session_set_blocking(session, 0);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 0);
 
     gettimeofday(&start, NULL);
 
diff --git a/example/scp_write_nonblock.c b/example/scp_write_nonblock.c
index 0ac0f69..5e5b76c 100644
--- a/example/scp_write_nonblock.c
+++ b/example/scp_write_nonblock.c
@@ -148,7 +148,7 @@ int main(int argc, char *argv[])
         return -1;
 
     /* Since we have set non-blocking, tell libssh2 we are non-blocking */
-    libssh2_session_set_blocking(session, 0);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 0);
 
     /* ... start it up. This will trade welcome banners, exchange keys,
      * and setup crypto, compression, and MAC layers
diff --git a/example/sftp.c b/example/sftp.c
index 88ceba2..e963cdd 100644
--- a/example/sftp.c
+++ b/example/sftp.c
@@ -154,7 +154,7 @@ int main(int argc, char *argv[])
         return -1;
 
     /* Since we have set non-blocking, tell libssh2 we are blocking */
-    libssh2_session_set_blocking(session, 1);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 1);
 
     /* ... start it up. This will trade welcome banners, exchange keys,
      * and setup crypto, compression, and MAC layers
diff --git a/example/sftp_RW_nonblock.c b/example/sftp_RW_nonblock.c
index 77c2027..450f5e3 100644
--- a/example/sftp_RW_nonblock.c
+++ b/example/sftp_RW_nonblock.c
@@ -133,7 +133,7 @@ int main(int argc, char *argv[])
         return -1;
     }
 
-    libssh2_session_set_blocking(session, 0);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 0);
 
     /* At this point we havn't yet authenticated.  The first thing to do
      * is check the hostkey's fingerprint against our known hosts Your app
diff --git a/example/sftp_append.c b/example/sftp_append.c
index 7585d38..e6a01bf 100644
--- a/example/sftp_append.c
+++ b/example/sftp_append.c
@@ -112,7 +112,7 @@ int main(int argc, char *argv[])
         return -1;
 
     /* Since we have set non-blocking, tell libssh2 we are blocking */
-    libssh2_session_set_blocking(session, 1);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 1);
 
     /* ... start it up. This will trade welcome banners, exchange keys,
      * and setup crypto, compression, and MAC layers
diff --git a/example/sftp_mkdir.c b/example/sftp_mkdir.c
index 8747084..aae5790 100644
--- a/example/sftp_mkdir.c
+++ b/example/sftp_mkdir.c
@@ -141,7 +141,7 @@ int main(int argc, char *argv[])
     }
 
     /* Since we have not set non-blocking, tell libssh2 we are blocking */
-    libssh2_session_set_blocking(session, 1);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 1);
 
     /* Make a directory via SFTP */
     rc = libssh2_sftp_mkdir(sftp_session, sftppath,
diff --git a/example/sftp_mkdir_nonblock.c b/example/sftp_mkdir_nonblock.c
index 22a8f59..e9cd3fe 100644
--- a/example/sftp_mkdir_nonblock.c
+++ b/example/sftp_mkdir_nonblock.c
@@ -142,7 +142,7 @@ int main(int argc, char *argv[])
     }
 
     /* Since we have set non-blocking, tell libssh2 we are non-blocking */
-    libssh2_session_set_blocking(session, 0);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 0);
 
     fprintf(stderr, "libssh2_sftp_mkdirnb()!\n");
     /* Make a directory via SFTP */
diff --git a/example/sftp_nonblock.c b/example/sftp_nonblock.c
index 29cec8a..d1de94b 100644
--- a/example/sftp_nonblock.c
+++ b/example/sftp_nonblock.c
@@ -144,7 +144,7 @@ int main(int argc, char *argv[])
         return -1;
 
     /* Since we have set non-blocking, tell libssh2 we are non-blocking */
-    libssh2_session_set_blocking(session, 0);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 0);
 
     gettimeofday(&start, NULL);
 
diff --git a/example/sftp_write.c b/example/sftp_write.c
index 483f80a..da41a35 100644
--- a/example/sftp_write.c
+++ b/example/sftp_write.c
@@ -111,7 +111,7 @@ int main(int argc, char *argv[])
         return -1;
 
     /* Since we have set non-blocking, tell libssh2 we are blocking */
-    libssh2_session_set_blocking(session, 1);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 1);
 
     /* ... start it up. This will trade welcome banners, exchange keys,
      * and setup crypto, compression, and MAC layers
diff --git a/example/sftp_write_nonblock.c b/example/sftp_write_nonblock.c
index 0d66c40..ed90bf8 100644
--- a/example/sftp_write_nonblock.c
+++ b/example/sftp_write_nonblock.c
@@ -151,7 +151,7 @@ int main(int argc, char *argv[])
         return -1;
 
     /* Since we have set non-blocking, tell libssh2 we are non-blocking */
-    libssh2_session_set_blocking(session, 0);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 0);
 
     /* ... start it up. This will trade welcome banners, exchange keys,
         * and setup crypto, compression, and MAC layers
diff --git a/example/sftp_write_sliding.c b/example/sftp_write_sliding.c
index c2ba39d..6a6731c 100644
--- a/example/sftp_write_sliding.c
+++ b/example/sftp_write_sliding.c
@@ -151,7 +151,7 @@ int main(int argc, char *argv[])
         return -1;
 
     /* Since we have set non-blocking, tell libssh2 we are non-blocking */
-    libssh2_session_set_blocking(session, 0);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 0);
 
     /* ... start it up. This will trade welcome banners, exchange keys,
         * and setup crypto, compression, and MAC layers
diff --git a/example/sftpdir.c b/example/sftpdir.c
index cb9fb88..5c60459 100644
--- a/example/sftpdir.c
+++ b/example/sftpdir.c
@@ -162,7 +162,7 @@ int main(int argc, char *argv[])
     }
 
     /* Since we have not set non-blocking, tell libssh2 we are blocking */
-    libssh2_session_set_blocking(session, 1);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 1);
 
     fprintf(stderr, "libssh2_sftp_opendir()!\n");
     /* Request a dir listing via SFTP */
diff --git a/example/sftpdir_nonblock.c b/example/sftpdir_nonblock.c
index c8ad9f5..24cd4de 100644
--- a/example/sftpdir_nonblock.c
+++ b/example/sftpdir_nonblock.c
@@ -116,7 +116,7 @@ int main(int argc, char *argv[])
         return -1;
 
     /* Since we have set non-blocking, tell libssh2 we are non-blocking */
-    libssh2_session_set_blocking(session, 0);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 0);
 
     /* ... start it up. This will trade welcome banners, exchange keys,
      * and setup crypto, compression, and MAC layers
diff --git a/example/ssh2_echo.c b/example/ssh2_echo.c
index 2430e33..7c6c663 100644
--- a/example/ssh2_echo.c
+++ b/example/ssh2_echo.c
@@ -133,7 +133,7 @@ int main(int argc, char *argv[])
         return -1;
 
     /* tell libssh2 we want it all done non-blocking */
-    libssh2_session_set_blocking(session, 0);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 0);
 
     /* ... start it up. This will trade welcome banners, exchange keys,
      * and setup crypto, compression, and MAC layers
diff --git a/example/ssh2_exec.c b/example/ssh2_exec.c
index d47761c..3a93a95 100644
--- a/example/ssh2_exec.c
+++ b/example/ssh2_exec.c
@@ -137,7 +137,7 @@ int main(int argc, char *argv[])
         return -1;
 
     /* tell libssh2 we want it all done non-blocking */
-    libssh2_session_set_blocking(session, 0);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 0);
 
     /* ... start it up. This will trade welcome banners, exchange keys,
      * and setup crypto, compression, and MAC layers
diff --git a/example/tcpip-forward.c b/example/tcpip-forward.c
index 94d3cc8..dc90a30 100644
--- a/example/tcpip-forward.c
+++ b/example/tcpip-forward.c
@@ -211,7 +211,7 @@ int main(int argc, char *argv[])
         remote_listenhost, remote_listenport, local_destip, local_destport);
 
     /* Must use non-blocking IO hereafter due to the current libssh2 API */
-    libssh2_session_set_blocking(session, 0);
+    libssh2_session_config_set(session, LIBSSH2_SESSION_CONFIG_BLOCKING, 0);
 
     while (1) {
         FD_ZERO(&fds);
-- 
1.8.3.2

_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel

Reply via email to