[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] channel: add ssh_channel_write timeout family


Hi,

Attached is a patch which adds timeout versions of the ssh_channel_write
functions.

The thinking is that these complement ssh_read_channel_timeout, and provide
a way for clients to specify their own timeouts to be used for each of the
'waitsession_unblocked' and 'waitwindow_termination' loops that take place
before the write.

There should be no behavior change for the existing ssh_channel_write
functions.


-Jon
From 172504dfdb57629b0dd9f8c6d5b37b4814e10250 Mon Sep 17 00:00:00 2001
From: Jon Simons <jon@xxxxxxxxxxxxx>
Date: Tue, 28 Jan 2014 21:06:24 -0800
Subject: [PATCH] channel: add ssh_channel_write timeout family

---
 include/libssh/channels.h |  2 +-
 include/libssh/libssh.h   |  1 +
 include/libssh/server.h   |  6 +++-
 src/channels.c            | 77 ++++++++++++++++++++++++++++++++++++++---------
 4 files changed, 69 insertions(+), 17 deletions(-)

diff --git a/include/libssh/channels.h b/include/libssh/channels.h
index 4515223..f155287 100644
--- a/include/libssh/channels.h
+++ b/include/libssh/channels.h
@@ -97,7 +97,7 @@ int ssh_channel_flush(ssh_channel channel);
 uint32_t ssh_channel_new_id(ssh_session session);
 ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id);
 int channel_write_common(ssh_channel channel, const void *data,
-    uint32_t len, int is_stderr);
+    uint32_t len, int is_stderr, int timeout_ms);
 void ssh_channel_do_free(ssh_channel channel);
 #ifdef WITH_SSH1
 SSH_PACKET_CALLBACK(ssh_packet_data1);
diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h
index 31bcc86..1456495 100644
--- a/include/libssh/libssh.h
+++ b/include/libssh/libssh.h
@@ -396,6 +396,7 @@ LIBSSH_API int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechan
         timeval * timeout);
 LIBSSH_API void ssh_channel_set_blocking(ssh_channel channel, int blocking);
 LIBSSH_API int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len);
+LIBSSH_API int ssh_channel_write_timeout(ssh_channel channel, const void *data, uint32_t len, int timeout_ms);
 LIBSSH_API uint32_t ssh_channel_window_size(ssh_channel channel);
 
 LIBSSH_API char *ssh_basename (const char *path);
diff --git a/include/libssh/server.h b/include/libssh/server.h
index 9d095fe..af60596 100644
--- a/include/libssh/server.h
+++ b/include/libssh/server.h
@@ -379,8 +379,12 @@ LIBSSH_API int ssh_channel_request_send_exit_signal(ssh_channel channel,
                                                 const char *errmsg,
                                                 const char *lang);
 LIBSSH_API int ssh_channel_write_stderr(ssh_channel channel,
+                                        const void *data,
+                                        uint32_t len);
+LIBSSH_API int ssh_channel_write_stderr_timeout(ssh_channel channel,
                                                 const void *data,
-                                                uint32_t len);
+                                                uint32_t len,
+                                                int timeout_ms);
 
 LIBSSH_API int ssh_send_keepalive(ssh_session session);
 
diff --git a/src/channels.c b/src/channels.c
index b77ad0a..eb111fc 100644
--- a/src/channels.c
+++ b/src/channels.c
@@ -1271,8 +1271,24 @@ int ssh_channel_flush(ssh_channel channel){
   return ssh_blocking_flush(channel->session, SSH_TIMEOUT_DEFAULT);
 }
 
+/**
+ * @internal
+ * @brief Write to the given channel's stdout or stderr, specifying
+ *        a timeout in millseconds or any of the SSH_TIMEOUT* values.
+ *
+ * @param[in]  channel     The channel to write to.
+ * @param[in]  data        A pointer to the data to write.
+ * @param[in]  len         The length of the source buffer.
+ * @param[in]  is_stderr   Whether to write to stderr or stdout.
+ * @param[in]  timeout_ms  Timeout in millseconds, or any of the
+ *                         SSH_TIMEOUT* values.
+ *
+ * @return The number of bytes written, 0 upon timeout, SSH_ERROR on error.
+ *
+ * @see ssh_channel_read()
+ */
 int channel_write_common(ssh_channel channel, const void *data,
-    uint32_t len, int is_stderr) {
+    uint32_t len, int is_stderr, int timeout_ms) {
   ssh_session session;
   uint32_t origlen = len;
   size_t effectivelen;
@@ -1325,7 +1341,7 @@ int channel_write_common(ssh_channel channel, const void *data,
   }
 #endif
   if (ssh_waitsession_unblocked(session) == 0){
-    rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_DEFAULT,
+    rc = ssh_handle_packets_termination(session, timeout_ms,
             ssh_waitsession_unblocked, session);
     if (rc == SSH_ERROR || !ssh_waitsession_unblocked(session))
         goto out;
@@ -1341,7 +1357,7 @@ int channel_write_common(ssh_channel channel, const void *data,
           /* nothing can be written */
           SSH_LOG(SSH_LOG_PROTOCOL,
                 "Wait for a growing window message...");
-          rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_DEFAULT,
+          rc = ssh_handle_packets_termination(session, timeout_ms,
               ssh_channel_waitwindow_termination,channel);
           if (rc == SSH_ERROR ||
               !ssh_channel_waitwindow_termination(channel) ||
@@ -1403,20 +1419,35 @@ uint32_t ssh_channel_window_size(ssh_channel channel) {
 }
 
 /**
- * @brief Blocking write on a channel.
+ * @brief Write to the given channel's stdout.
  *
  * @param[in]  channel  The channel to write to.
- *
  * @param[in]  data     A pointer to the data to write.
+ * @param[in]  len      The length of the source buffer.
  *
- * @param[in]  len      The length of the buffer to write to.
- *
- * @return              The number of bytes written, SSH_ERROR on error.
+ * @return The number of bytes written, SSH_ERROR on error.
  *
  * @see ssh_channel_read()
  */
 int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len) {
-  return channel_write_common(channel, data, len, 0);
+  return channel_write_common(channel, data, len, 0, SSH_TIMEOUT_DEFAULT);
+}
+
+/**
+ * @brief Write to the given channel's stdout with timeout.
+ *
+ * @param[in]  channel     The channel to write to.
+ * @param[in]  data        A pointer to the data to write.
+ * @param[in]  len         The length of the source buffer.
+ * @param[in]  timeout_ms  Timeout in millseconds.
+ *
+ * @return The number of bytes written, 0 upon timeout, SSH_ERROR on error.
+ *
+ * @see ssh_channel_read()
+ */
+int ssh_channel_write_timeout(ssh_channel channel, const void *data,
+                              uint32_t len, int timeout_ms) {
+  return channel_write_common(channel, data, len, 0, timeout_ms);
 }
 
 /**
@@ -3240,20 +3271,36 @@ int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans,
 
 #if WITH_SERVER
 /**
- * @brief Blocking write on a channel stderr.
+ * @brief Write to the given channel's stderr.
  *
  * @param[in]  channel  The channel to write to.
- *
  * @param[in]  data     A pointer to the data to write.
+ * @param[in]  len      The length of the source buffer.
+ *
+ * @return The number of bytes written, SSH_ERROR on error.
+ *
+ * @see ssh_channel_read()
+ */
+int ssh_channel_write_stderr(ssh_channel channel, const void *data,
+                             uint32_t len) {
+  return channel_write_common(channel, data, len, 1, SSH_TIMEOUT_DEFAULT);
+}
+
+/**
+ * @brief Write to the given channel's stderr with timeout.
  *
- * @param[in]  len      The length of the buffer to write to.
+ * @param[in]  channel     The channel to write to.
+ * @param[in]  data        A pointer to the data to write.
+ * @param[in]  len         The length of the source buffer.
+ * @param[in]  timeout_ms  Timeout in millseconds.
  *
- * @return              The number of bytes written, SSH_ERROR on error.
+ * @return The number of bytes written, 0 upon timeout, SSH_ERROR on error.
  *
  * @see ssh_channel_read()
  */
-int ssh_channel_write_stderr(ssh_channel channel, const void *data, uint32_t len) {
-  return channel_write_common(channel, data, len, 1);
+int ssh_channel_write_stderr_timeout(ssh_channel channel, const void *data,
+                                     uint32_t len, int timeout_ms) {
+  return channel_write_common(channel, data, len, 1, timeout_ms);
 }
 
 /**
-- 
1.8.4.21.g992c386



Archive administrator: postmaster@lists.cynapses.org