diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2015-07-05 16:56:20 +0200 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2015-07-17 22:25:12 +0200 |
commit | 13c0395dd5dc6865412be6c151398f9b14788898 (patch) | |
tree | f5f0dc665989bfc9f21abc2ea6504265c32a8659 | |
parent | 30f2a4a96fb3df38466e317bf107a73f38ddc161 (diff) | |
download | libssh-13c0395dd5dc6865412be6c151398f9b14788898.tar.gz libssh-13c0395dd5dc6865412be6c151398f9b14788898.tar.xz libssh-13c0395dd5dc6865412be6c151398f9b14788898.zip |
packets: handle flow control callbacks
-rw-r--r-- | include/libssh/callbacks.h | 16 | ||||
-rw-r--r-- | src/packet.c | 21 |
2 files changed, 36 insertions, 1 deletions
diff --git a/include/libssh/callbacks.h b/include/libssh/callbacks.h index 20c540e5..21e04540 100644 --- a/include/libssh/callbacks.h +++ b/include/libssh/callbacks.h @@ -694,6 +694,18 @@ typedef int (*ssh_channel_subsystem_request_callback) (ssh_session session, const char *subsystem, void *userdata); +/** + * @brief SSH channel write will not block (flow control). + * @param channel the channel + * @param[in] bytes size of the remote window in bytes. Writing as much data + * will not block. + * @param[in] userdata Userdata to be passed to the callback function. + * @returns 0 default return value (other return codes may be added in future). + */ +typedef int (*ssh_channel_write_wontblock_callback) (ssh_session session, + ssh_channel channel, + size_t bytes, + void *userdata); struct ssh_channel_callbacks_struct { /** DON'T SET THIS use ssh_callbacks_init() instead. */ @@ -758,6 +770,10 @@ struct ssh_channel_callbacks_struct { * (like sftp). */ ssh_channel_subsystem_request_callback channel_subsystem_request_function; + /** This function will be called when the channel write is guaranteed + * not to block. + */ + ssh_channel_write_wontblock_callback channel_write_wontblock_function; }; typedef struct ssh_channel_callbacks_struct *ssh_channel_callbacks; diff --git a/src/packet.c b/src/packet.c index d16cd165..5c9bd5ab 100644 --- a/src/packet.c +++ b/src/packet.c @@ -360,10 +360,29 @@ error: return processed; } +static void ssh_packet_socket_controlflow_callback(int code, void *userdata){ + ssh_session session=userdata; + struct ssh_iterator *it; + ssh_channel channel; + if (code == SSH_SOCKET_FLOW_WRITEWONTBLOCK){ + /* the out pipe is empty so we can forward this to channels */ + it = ssh_list_get_iterator(session->channels); + while (it != NULL){ + channel = ssh_iterator_value(ssh_channel, it); + if (ssh_callbacks_exists(channel->callbacks, channel_write_wontblock_function)){ + SSH_LOG(SSH_LOG_TRACE, "Executing write_wontblock callback for channel"); + channel->callbacks->channel_write_wontblock_function(session, channel, + channel->remote_window, channel->callbacks->userdata); + } + it = it->next; + } + } +} + void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s){ session->socket_callbacks.data=ssh_packet_socket_callback; session->socket_callbacks.connected=NULL; - session->socket_callbacks.controlflow=NULL; + session->socket_callbacks.controlflow=ssh_packet_socket_controlflow_callback; session->socket_callbacks.exception=NULL; session->socket_callbacks.userdata=session; ssh_socket_set_callbacks(s,&session->socket_callbacks); |