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.
.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.

View File

@ -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

View File

@ -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)

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_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 */

View File

@ -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

View File

@ -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);

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 */
nread =
_libssh2_recv(session->socket_fd, &p->buf[remainbuf],
LIBSSH2_RECV(session, &p->buf[remainbuf],
PACKETBUFSIZE - remainbuf,
LIBSSH2_SOCKET_RECV_FLAGS(session));
if (nread <= 0) {
@ -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,