Custom callbacks for performing low level socket I/O

This commit is contained in:
Henrik Nordstrom 2011-08-11 22:26:56 +02:00 committed by Daniel Stenberg
parent 462996b064
commit 7aa4bfc671
7 changed files with 48 additions and 13 deletions

View File

@ -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. function returns 0, the packet will be accepted nonetheless.
.IP LIBSSH2_CALLBACK_X11 .IP LIBSSH2_CALLBACK_X11
Called when an X11 connection has been accepted 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 .SH RETURN VALUE
Pointer to previous callback handler. Returns NULL if no prior callback Pointer to previous callback handler. Returns NULL if no prior callback
handler was set or the callback type was unknown. handler was set or the callback type was unknown.

View File

@ -237,12 +237,22 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE
void name(LIBSSH2_SESSION *session, void **session_abstract, \ void name(LIBSSH2_SESSION *session, void **session_abstract, \
LIBSSH2_CHANNEL *channel, void **channel_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 */ /* libssh2_session_callback_set() constants */
#define LIBSSH2_CALLBACK_IGNORE 0 #define LIBSSH2_CALLBACK_IGNORE 0
#define LIBSSH2_CALLBACK_DEBUG 1 #define LIBSSH2_CALLBACK_DEBUG 1
#define LIBSSH2_CALLBACK_DISCONNECT 2 #define LIBSSH2_CALLBACK_DISCONNECT 2
#define LIBSSH2_CALLBACK_MACERROR 3 #define LIBSSH2_CALLBACK_MACERROR 3
#define LIBSSH2_CALLBACK_X11 4 #define LIBSSH2_CALLBACK_X11 4
#define LIBSSH2_CALLBACK_SEND 5
#define LIBSSH2_CALLBACK_RECV 6
/* libssh2_session_method_pref() constants */ /* libssh2_session_method_pref() constants */
#define LIBSSH2_METHOD_KEX 0 #define LIBSSH2_METHOD_KEX 0

View File

@ -177,7 +177,7 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
/* Send the length of the request */ /* Send the length of the request */
if (transctx->state == agent_NB_state_request_created) { if (transctx->state == agent_NB_state_request_created) {
_libssh2_htonu32(buf, transctx->request_len); _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) if (rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN; return LIBSSH2_ERROR_EAGAIN;
else if (rc < 0) else if (rc < 0)
@ -188,7 +188,7 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
/* Send the request body */ /* Send the request body */
if (transctx->state == agent_NB_state_request_length_sent) { 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); transctx->request_len, 0);
if (rc == -EAGAIN) if (rc == -EAGAIN)
return LIBSSH2_ERROR_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 */ /* Receive the length of a response */
if (transctx->state == agent_NB_state_request_sent) { 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 < 0) {
if (rc == -EAGAIN) if (rc == -EAGAIN)
return LIBSSH2_ERROR_EAGAIN; return LIBSSH2_ERROR_EAGAIN;
@ -218,7 +218,7 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
/* Receive the response body */ /* Receive the response body */
if (transctx->state == agent_NB_state_response_length_received) { 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); transctx->response_len, 0);
if (rc < 0) { if (rc < 0) {
if (rc == -EAGAIN) if (rc == -EAGAIN)

View File

@ -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_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_KEX_METHOD LIBSSH2_KEX_METHOD;
typedef struct _LIBSSH2_HOSTKEY_METHOD LIBSSH2_HOSTKEY_METHOD; typedef struct _LIBSSH2_HOSTKEY_METHOD LIBSSH2_HOSTKEY_METHOD;
typedef struct _LIBSSH2_CRYPT_METHOD LIBSSH2_CRYPT_METHOD; typedef struct _LIBSSH2_CRYPT_METHOD LIBSSH2_CRYPT_METHOD;
@ -539,6 +545,8 @@ struct _LIBSSH2_SESSION
LIBSSH2_DISCONNECT_FUNC((*ssh_msg_disconnect)); LIBSSH2_DISCONNECT_FUNC((*ssh_msg_disconnect));
LIBSSH2_MACERROR_FUNC((*macerror)); LIBSSH2_MACERROR_FUNC((*macerror));
LIBSSH2_X11_OPEN_FUNC((*x11)); LIBSSH2_X11_OPEN_FUNC((*x11));
LIBSSH2_SEND_FUNC((*send));
LIBSSH2_RECV_FUNC((*recv));
/* Method preferences -- NULL yields "load order" */ /* Method preferences -- NULL yields "load order" */
char *kex_prefs; char *kex_prefs;
@ -972,9 +980,9 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
#define SSH_OPEN_RESOURCE_SHORTAGE 4 #define SSH_OPEN_RESOURCE_SHORTAGE 4
ssize_t _libssh2_recv(libssh2_socket_t socket, void *buffer, 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, 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 #define LIBSSH2_READ_TIMEOUT 60 /* generic timeout in seconds used when
waiting for more data to arrive */ waiting for more data to arrive */

View File

@ -94,7 +94,7 @@ static int wsa2errno(void)
* Replacement for the standard recv, return -errno on failure. * Replacement for the standard recv, return -errno on failure.
*/ */
ssize_t 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); ssize_t rc = recv(sock, buffer, length, flags);
#ifdef WIN32 #ifdef WIN32
@ -126,7 +126,7 @@ _libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, int flags)
*/ */
ssize_t ssize_t
_libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length, _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); ssize_t rc = send(sock, buffer, length, flags);
#ifdef WIN32 #ifdef WIN32

View File

@ -115,7 +115,7 @@ banner_receive(LIBSSH2_SESSION * session)
/* no incoming block yet! */ /* no incoming block yet! */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND; 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)); LIBSSH2_SOCKET_RECV_FLAGS(session));
if (ret < 0) { if (ret < 0) {
if(session->api_block_mode || (ret != -EAGAIN)) if(session->api_block_mode || (ret != -EAGAIN))
@ -227,7 +227,7 @@ banner_send(LIBSSH2_SESSION * session)
/* no outgoing block yet! */ /* no outgoing block yet! */
session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND; 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 + session->banner_TxRx_total_send,
banner_len - session->banner_TxRx_total_send, banner_len - session->banner_TxRx_total_send,
LIBSSH2_SOCKET_SEND_FLAGS(session)); LIBSSH2_SOCKET_SEND_FLAGS(session));
@ -481,6 +481,8 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
session->alloc = local_alloc; session->alloc = local_alloc;
session->free = local_free; session->free = local_free;
session->realloc = local_realloc; session->realloc = local_realloc;
session->send = _libssh2_send;
session->recv = _libssh2_recv;
session->abstract = abstract; session->abstract = abstract;
session->api_timeout = 0; /* timeout-free API by default */ session->api_timeout = 0; /* timeout-free API by default */
session->api_block_mode = 1; /* blocking 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; session->x11 = callback;
return oldcb; 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); _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting Callback %d", cbtype);

View File

@ -357,7 +357,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
/* now read a big chunk from the network into the temp buffer */ /* now read a big chunk from the network into the temp buffer */
nread = nread =
_libssh2_recv(session->socket_fd, &p->buf[remainbuf], LIBSSH2_RECV(session, &p->buf[remainbuf],
PACKETBUFSIZE - remainbuf, PACKETBUFSIZE - remainbuf,
LIBSSH2_SOCKET_RECV_FLAGS(session)); LIBSSH2_SOCKET_RECV_FLAGS(session));
if (nread <= 0) { if (nread <= 0) {
@ -610,7 +610,7 @@ send_existing(LIBSSH2_SESSION *session, const unsigned char *data,
/* number of bytes left to send */ /* number of bytes left to send */
length = p->ototal_num - p->osent; 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)); LIBSSH2_SOCKET_SEND_FLAGS(session));
if (rc < 0) if (rc < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET, _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
@ -823,7 +823,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
session->local.seqno++; 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)); LIBSSH2_SOCKET_SEND_FLAGS(session));
if (ret < 0) if (ret < 0)
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET, _libssh2_debug(session, LIBSSH2_TRACE_SOCKET,