tor 2011-08-11 klockan 11:43 +0200 skrev Daniel Stenberg:

> I can see how we can add support for user-provided send/recv functions and I 
> believe we've discussed that before and I'm for it. I would however prefer to 
> better hide that within the _libssh2_recv() and _libssh2_send() functions to 
> make the existing code (basically) unmodified and easier to read, make it 
> easier to have future code use the same concept and make it affect _all_ 
> reads/writes.

I think a simpler way is to make all SSH send/recv go via
session->send/recv set by default to _libssh2_send/recv

Additionally agent.c is also using _libssh2_send/recv with a slightly
different usage pattern, doing I/O on the agent fd and not the libssh2
session fd.

Reworked patch attached. Can also be found in my github repository where
various other small changes also resides while I am reading the code. 

  github.com/hno/libssh2

Regards
Henrik
commit a894d38506813138d7669d4867ff920643eaea38
Author: Henrik Nordstrom <hen...@henriknordstrom.net>
Date:   Thu Aug 11 22:26:56 2011 +0200

    Custom callbacks for performing low level socket I/O

diff --git a/docs/libssh2_session_callback_set.3 b/docs/libssh2_session_callback_set.3
index 4e5aa9c..1a42401 100644
--- a/docs/libssh2_session_callback_set.3
+++ b/docs/libssh2_session_callback_set.3
@@ -33,6 +33,12 @@ Called when a mismatched MAC has been detected in the transport layer. If the
 function returns 0, the packet will be accepted nonetheless.
 .IP LIBSSH2_CALLBACK_X11
 Called when an X11 connection has been accepted
+.IP LIBSSH2_CALLBACK_SEND
+Called when libssh2 wants to send some data on the connection.
+Can be set to a custom function to handle I/O your own way.
+.IP LIBSSH2_CALLBACK_RECV
+Called when libssh2 wants to receive some data from the connection.
+Can be set to a custom function to handle I/O your own way.
 .SH RETURN VALUE
 Pointer to previous callback handler. Returns NULL if no prior callback
 handler was set or the callback type was unknown.
diff --git a/include/libssh2.h b/include/libssh2.h
index 2a997ae..f5c791a 100644
--- a/include/libssh2.h
+++ b/include/libssh2.h
@@ -237,12 +237,22 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE
   void name(LIBSSH2_SESSION *session, void **session_abstract, \
             LIBSSH2_CHANNEL *channel, void **channel_abstract)
 
+/* I/O callbacks */
+#define LIBSSH2_RECV_FUNC(name)  ssize_t name(int socket, \
+                                              void *buffer, size_t length, \
+                                              int flags, void **abstract)
+#define LIBSSH2_SEND_FUNC(name)  ssize_t name(int socket, \
+                                              const void *buffer, size_t length,\
+                                              int flags, void **abstract)
+
 /* libssh2_session_callback_set() constants */
 #define LIBSSH2_CALLBACK_IGNORE             0
 #define LIBSSH2_CALLBACK_DEBUG              1
 #define LIBSSH2_CALLBACK_DISCONNECT         2
 #define LIBSSH2_CALLBACK_MACERROR           3
 #define LIBSSH2_CALLBACK_X11                4
+#define LIBSSH2_CALLBACK_SEND               5
+#define LIBSSH2_CALLBACK_RECV               6
 
 /* libssh2_session_method_pref() constants */
 #define LIBSSH2_METHOD_KEX          0
diff --git a/src/agent.c b/src/agent.c
index 7c6eaa3..5a9e81c 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -177,7 +177,7 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
     /* Send the length of the request */
     if (transctx->state == agent_NB_state_request_created) {
         _libssh2_htonu32(buf, transctx->request_len);
-        rc = _libssh2_send(agent->fd, buf, sizeof buf, 0);
+        rc = LIBSSH2_SEND_FD(agent->session, agent->fd, buf, sizeof buf, 0);
         if (rc == -EAGAIN)
             return LIBSSH2_ERROR_EAGAIN;
         else if (rc < 0)
@@ -188,7 +188,7 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
 
     /* Send the request body */
     if (transctx->state == agent_NB_state_request_length_sent) {
-        rc = _libssh2_send(agent->fd, transctx->request,
+        rc = LIBSSH2_SEND_FD(agent->session, agent->fd, transctx->request,
                            transctx->request_len, 0);
         if (rc == -EAGAIN)
             return LIBSSH2_ERROR_EAGAIN;
@@ -200,7 +200,7 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
 
     /* Receive the length of a response */
     if (transctx->state == agent_NB_state_request_sent) {
-        rc = _libssh2_recv(agent->fd, buf, sizeof buf, 0);
+        rc = LIBSSH2_RECV_FD(agent->session, agent->fd, buf, sizeof buf, 0);
         if (rc < 0) {
             if (rc == -EAGAIN)
                 return LIBSSH2_ERROR_EAGAIN;
@@ -218,7 +218,7 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
 
     /* Receive the response body */
     if (transctx->state == agent_NB_state_response_length_received) {
-        rc = _libssh2_recv(agent->fd, transctx->response,
+        rc = LIBSSH2_RECV_FD(agent->session, agent->fd, transctx->response,
                            transctx->response_len, 0);
         if (rc < 0) {
             if (rc == -EAGAIN)
diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h
index 473e9c3..d2f8054 100644
--- a/src/libssh2_priv.h
+++ b/src/libssh2_priv.h
@@ -171,6 +171,12 @@ static inline int writev(int sock, struct iovec *iov, int nvecs)
 
 #define LIBSSH2_CHANNEL_CLOSE(session, channel)                     channel->close_cb((session), &(session)->abstract, (channel), &(channel)->abstract)
 
+#define LIBSSH2_SEND_FD(session, fd, buffer, length, flags)                session->send(fd, buffer, length, flags, &session->abstract)
+#define LIBSSH2_RECV_FD(session, fd, buffer, length, flags)                session->recv(fd, buffer, length, flags, &session->abstract)
+
+#define LIBSSH2_SEND(session, buffer, length, flags)                LIBSSH2_SEND_FD(session, session->socket_fd, buffer, length, flags)
+#define LIBSSH2_RECV(session, buffer, length, flags)                LIBSSH2_SEND_FD(session, session->socket_fd, buffer, length, flags)
+
 typedef struct _LIBSSH2_KEX_METHOD LIBSSH2_KEX_METHOD;
 typedef struct _LIBSSH2_HOSTKEY_METHOD LIBSSH2_HOSTKEY_METHOD;
 typedef struct _LIBSSH2_CRYPT_METHOD LIBSSH2_CRYPT_METHOD;
@@ -539,6 +545,8 @@ struct _LIBSSH2_SESSION
       LIBSSH2_DISCONNECT_FUNC((*ssh_msg_disconnect));
       LIBSSH2_MACERROR_FUNC((*macerror));
       LIBSSH2_X11_OPEN_FUNC((*x11));
+      LIBSSH2_SEND_FUNC((*send));
+      LIBSSH2_RECV_FUNC((*recv));
 
     /* Method preferences -- NULL yields "load order" */
     char *kex_prefs;
@@ -972,9 +980,9 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
 #define SSH_OPEN_RESOURCE_SHORTAGE           4
 
 ssize_t _libssh2_recv(libssh2_socket_t socket, void *buffer,
-                      size_t length, int flags);
+                      size_t length, int flags, void **abstract);
 ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer,
-                      size_t length, int flags);
+                      size_t length, int flags, void **abstract);
 
 #define LIBSSH2_READ_TIMEOUT 60 /* generic timeout in seconds used when
                                    waiting for more data to arrive */
diff --git a/src/misc.c b/src/misc.c
index cc07fc6..a9f423a 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -94,7 +94,7 @@ static int wsa2errno(void)
  * Replacement for the standard recv, return -errno on failure.
  */
 ssize_t
-_libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, int flags)
+_libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, int flags, void **abstract)
 {
     ssize_t rc = recv(sock, buffer, length, flags);
 #ifdef WIN32
@@ -126,7 +126,7 @@ _libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, int flags)
  */
 ssize_t
 _libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length,
-              int flags)
+              int flags, void **abstract)
 {
     ssize_t rc = send(sock, buffer, length, flags);
 #ifdef WIN32
diff --git a/src/session.c b/src/session.c
index 46ef016..50d08ee 100644
--- a/src/session.c
+++ b/src/session.c
@@ -115,7 +115,7 @@ banner_receive(LIBSSH2_SESSION * session)
         /* no incoming block yet! */
         session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
 
-        ret = _libssh2_recv(session->socket_fd, &c, 1,
+        ret = LIBSSH2_RECV(session, &c, 1,
                             LIBSSH2_SOCKET_RECV_FLAGS(session));
         if (ret < 0) {
             if(session->api_block_mode || (ret != -EAGAIN))
@@ -227,7 +227,7 @@ banner_send(LIBSSH2_SESSION * session)
     /* no outgoing block yet! */
     session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
 
-    ret = _libssh2_send(session->socket_fd,
+    ret = LIBSSH2_SEND(session,
                         banner + session->banner_TxRx_total_send,
                         banner_len - session->banner_TxRx_total_send,
                         LIBSSH2_SOCKET_SEND_FLAGS(session));
@@ -481,6 +481,8 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
         session->alloc = local_alloc;
         session->free = local_free;
         session->realloc = local_realloc;
+        session->send = _libssh2_send;
+        session->recv = _libssh2_recv;
         session->abstract = abstract;
         session->api_timeout = 0; /* timeout-free API by default */
         session->api_block_mode = 1; /* blocking API by default */
@@ -532,6 +534,15 @@ libssh2_session_callback_set(LIBSSH2_SESSION * session,
         session->x11 = callback;
         return oldcb;
 
+    case LIBSSH2_CALLBACK_SEND:
+        oldcb = session->send;
+        session->send = callback;
+        return oldcb;
+
+    case LIBSSH2_CALLBACK_RECV:
+        oldcb = session->recv;
+        session->recv = callback;
+        return oldcb;
     }
     _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting Callback %d", cbtype);
 
diff --git a/src/transport.c b/src/transport.c
index 0cb7b63..29be2a2 100644
--- a/src/transport.c
+++ b/src/transport.c
@@ -357,9 +357,9 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
 
             /* now read a big chunk from the network into the temp buffer */
             nread =
-                _libssh2_recv(session->socket_fd, &p->buf[remainbuf],
+                session->recv(session->socket_fd, &p->buf[remainbuf],
                               PACKETBUFSIZE - remainbuf,
-                              LIBSSH2_SOCKET_RECV_FLAGS(session));
+                              LIBSSH2_SOCKET_RECV_FLAGS(session),&session->abstract);
             if (nread <= 0) {
                 /* check if this is due to EAGAIN and return the special
                    return code if so, error out normally otherwise */
@@ -610,7 +610,7 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data,
     /* number of bytes left to send */
     length = p->ototal_num - p->osent;
 
-    rc = _libssh2_send(session->socket_fd, &p->outbuf[p->osent], length,
+    rc = LIBSSH2_SEND(session, &p->outbuf[p->osent], length,
                        LIBSSH2_SOCKET_SEND_FLAGS(session));
     if (rc < 0)
         _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
@@ -823,7 +823,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
 
     session->local.seqno++;
 
-    ret = _libssh2_send(session->socket_fd, p->outbuf, total_length,
+    ret = LIBSSH2_SEND(session, p->outbuf, total_length,
                         LIBSSH2_SOCKET_SEND_FLAGS(session));
     if (ret < 0)
         _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel

Reply via email to