aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormilo <milo@r0ot.me>2010-09-29 16:58:48 +0200
committerAris Adamantiadis <aris@0xbadc0de.be>2010-10-02 22:51:14 +0200
commitc4356531f78fdcf2f3b6a9861f6129eac81990f8 (patch)
treeb9250f0a5fff64564f1f859be7d6b8a30f2ca769
parent873e02fc6a0de3792a2a0a713ef21d4b67c308d2 (diff)
downloadlibssh-c4356531f78fdcf2f3b6a9861f6129eac81990f8.tar.gz
libssh-c4356531f78fdcf2f3b6a9861f6129eac81990f8.tar.xz
libssh-c4356531f78fdcf2f3b6a9861f6129eac81990f8.zip
Add new callbacks in session and channels
-rw-r--r--include/libssh/callbacks.h155
-rw-r--r--include/libssh/channels.h1
-rw-r--r--src/callbacks.c18
-rw-r--r--src/channels.c33
4 files changed, 204 insertions, 3 deletions
diff --git a/include/libssh/callbacks.h b/include/libssh/callbacks.h
index d2526694..0e18b81f 100644
--- a/include/libssh/callbacks.h
+++ b/include/libssh/callbacks.h
@@ -92,6 +92,16 @@ typedef void (*ssh_status_callback) (ssh_session session, float status,
void *userdata);
/**
+ * @brief SSH global request callback. All global request will go through this
+ * callback.
+ * @param session Current session handler
+ * @param message the actual message
+ * @param userdata Userdata to be passed to the callback function.
+ */
+typedef void (*ssh_global_request_callback) (ssh_session session,
+ ssh_message message, void *userdata);
+
+/**
* The structure to replace libssh functions with appropriate callbacks.
*/
struct ssh_callbacks_struct {
@@ -114,6 +124,10 @@ struct ssh_callbacks_struct {
* percentage of connection steps completed.
*/
void (*connect_status_function)(void *userdata, float status);
+ /**
+ * This function will be called each time a global request is received.
+ */
+ ssh_global_request_callback global_request_function;
};
typedef struct ssh_callbacks_struct *ssh_callbacks;
@@ -177,7 +191,7 @@ typedef struct ssh_socket_callbacks_struct *ssh_socket_callbacks;
* @returns nonzero if callback can be called
*/
#define ssh_callbacks_exists(p,c) (\
- ( (char *)&((p)-> c) < (char *)(p) + (p)->size ) && \
+ (p) && ( (char *)&((p)-> c) < (char *)(p) + (p)->size ) && \
((p)-> c != NULL) \
)
@@ -226,7 +240,7 @@ struct ssh_packet_callbacks_struct {
typedef struct ssh_packet_callbacks_struct *ssh_packet_callbacks;
/**
- * @brief Set the callback functions.
+ * @brief Set the session callback functions.
*
* This functions sets the callback structure to use your own callback
* functions for auth, logging and status.
@@ -242,12 +256,147 @@ typedef struct ssh_packet_callbacks_struct *ssh_packet_callbacks;
*
* @param session The session to set the callback structure.
*
- * @param cb The callback itself.
+ * @param cb The callback structure itself.
*
* @return SSH_OK on success, SSH_ERROR on error.
*/
LIBSSH_API int ssh_set_callbacks(ssh_session session, ssh_callbacks cb);
+/**
+ * @brief SSH channel data callback. Called when data is available on a channel
+ * @param session Current session handler
+ * @param channel the actual channel
+ * @param data the data that has been read on the channel
+ * @param len the length of the data
+ * @param is_stderr is 0 for stdout or 1 for stderr
+ * @param userdata Userdata to be passed to the callback function.
+ */
+typedef int (*ssh_channel_data_callback) (ssh_session session,
+ ssh_channel channel,
+ void *data,
+ uint32_t len,
+ int is_stderr,
+ void *userdata);
+
+/**
+ * @brief SSH channel eof callback. Called when a channel receives EOF
+ * @param session Current session handler
+ * @param channel the actual channel
+ * @param userdata Userdata to be passed to the callback function.
+ */
+typedef void (*ssh_channel_eof_callback) (ssh_session session,
+ ssh_channel channel,
+ void *userdata);
+
+/**
+ * @brief SSH channel close callback. Called when a channel is closed by remote peer
+ * @param session Current session handler
+ * @param channel the actual channel
+ * @param userdata Userdata to be passed to the callback function.
+ */
+typedef void (*ssh_channel_close_callback) (ssh_session session,
+ ssh_channel channel,
+ void *userdata);
+
+/**
+ * @brief SSH channel signal callback. Called when a channel has received a signal
+ * @param session Current session handler
+ * @param channel the actual channel
+ * @param signal the signal name (without the SIG prefix)
+ * @param userdata Userdata to be passed to the callback function.
+ */
+typedef void (*ssh_channel_signal_callback) (ssh_session session,
+ ssh_channel channel,
+ const char *signal,
+ void *userdata);
+
+/**
+ * @brief SSH channel exit status callback. Called when a channel has received an exit status
+ * @param session Current session handler
+ * @param channel the actual channel
+ * @param userdata Userdata to be passed to the callback function.
+ */
+typedef void (*ssh_channel_exit_status_callback) (ssh_session session,
+ ssh_channel channel,
+ int exit_status,
+ void *userdata);
+
+/**
+ * @brief SSH channel exit signal callback. Called when a channel has received an exit signal
+ * @param session Current session handler
+ * @param channel the actual channel
+ * @param signal the signal name (without the SIG prefix)
+ * @param core a boolean telling wether a core has been dumped or not
+ * @param errmsg the description of the exception
+ * @param lang the language of the description (format: RFC 3066)
+ * @param userdata Userdata to be passed to the callback function.
+ */
+typedef void (*ssh_channel_exit_signal_callback) (ssh_session session,
+ ssh_channel channel,
+ const char *signal,
+ int core,
+ const char *errmsg,
+ const char *lang,
+ void *userdata);
+
+struct ssh_channel_callbacks_struct {
+ /** DON'T SET THIS use ssh_callbacks_init() instead. */
+ size_t size;
+ /**
+ * User-provided data. User is free to set anything he wants here
+ */
+ void *userdata;
+ /**
+ * This functions will be called when there is data available.
+ */
+ ssh_channel_data_callback channel_data_function;
+ /**
+ * This functions will be called when the channel has received an EOF.
+ */
+ ssh_channel_eof_callback channel_eof_function;
+ /**
+ * This functions will be called when the channel has been closed by remote
+ */
+ ssh_channel_close_callback channel_close_function;
+ /**
+ * This functions will be called when a signal has been received
+ */
+ ssh_channel_signal_callback channel_signal_function;
+ /**
+ * This functions will be called when an exit status has been received
+ */
+ ssh_channel_exit_status_callback channel_exit_status_function;
+ /**
+ * This functions will be called when an exit signal has been received
+ */
+ ssh_channel_exit_signal_callback channel_exit_signal_function;
+};
+typedef struct ssh_channel_callbacks_struct *ssh_channel_callbacks;
+
+/**
+ * @brief Set the channel callback functions.
+ *
+ * This functions sets the callback structure to use your own callback
+ * functions for channel data and exceptions
+ *
+ * @code
+ * struct ssh_channel_callbacks_struct cb = {
+ * .userdata = data,
+ * .channel_data = my_channel_data_function
+ * };
+ * ssh_callbacks_init(&cb);
+ * ssh_set_channel_callbacks(channel, &cb);
+ * @endcode
+ *
+ * @param channel The channel to set the callback structure.
+ *
+ * @param cb The callback structure itself.
+ *
+ * @return SSH_OK on success, SSH_ERROR on error.
+ */
+LIBSSH_API int ssh_set_channel_callbacks(ssh_channel channel,
+ ssh_channel_callbacks cb);
+
/** @} */
/** @group libssh_threads
diff --git a/include/libssh/channels.h b/include/libssh/channels.h
index 7d8a05ba..2e1d9378 100644
--- a/include/libssh/channels.h
+++ b/include/libssh/channels.h
@@ -69,6 +69,7 @@ struct ssh_channel_struct {
int blocking;
int exit_status;
enum ssh_channel_request_state_e request_state;
+ ssh_channel_callbacks callbacks;
};
SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf);
diff --git a/src/callbacks.c b/src/callbacks.c
index 1568d516..bb42b4be 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -41,3 +41,21 @@ int ssh_set_callbacks(ssh_session session, ssh_callbacks cb) {
leave_function();
return 0;
}
+
+int ssh_set_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb) {
+ ssh_session session = NULL;
+ if (channel == NULL || cb == NULL) {
+ return SSH_ERROR;
+ }
+ session = channel->session;
+ enter_function();
+ if(cb->size <= 0 || cb->size > 1024 * sizeof(void *)){
+ ssh_set_error(session,SSH_FATAL,
+ "Invalid channel callback passed in (badly initialized)");
+ leave_function();
+ return SSH_ERROR;
+ }
+ channel->callbacks = cb;
+ leave_function();
+ return 0;
+}
diff --git a/src/channels.c b/src/channels.c
index 6bf8543d..83d01023 100644
--- a/src/channels.c
+++ b/src/channels.c
@@ -430,8 +430,10 @@ SSH_PACKET_CALLBACK(channel_rcv_change_window) {
SSH_PACKET_CALLBACK(channel_rcv_data){
ssh_channel channel;
ssh_string str;
+ ssh_buffer buf;
size_t len;
int is_stderr;
+ int rest;
(void)user;
enter_function();
if(type==SSH2_MSG_CHANNEL_DATA)
@@ -495,6 +497,25 @@ SSH_PACKET_CALLBACK(channel_rcv_data){
channel->remote_window);
ssh_string_free(str);
+
+ if(ssh_callbacks_exists(channel->callbacks, channel_data_function)) {
+ if(is_stderr) {
+ buf = channel->stderr_buffer;
+ } else {
+ buf = channel->stdout_buffer;
+ }
+ rest = channel->callbacks->channel_data_function(channel->session,
+ channel,
+ buffer_get_rest(buf),
+ buffer_get_rest_len(buf),
+ is_stderr,
+ channel->callbacks->userdata);
+ if(rest > 0) {
+ buffer_pass_bytes(buf, rest);
+ channel->local_window += rest;
+ }
+ }
+
leave_function();
return SSH_PACKET_USED;
}
@@ -519,6 +540,12 @@ SSH_PACKET_CALLBACK(channel_rcv_eof) {
/* channel->remote_window = 0; */
channel->remote_eof = 1;
+ if(ssh_callbacks_exists(channel->callbacks, channel_eof_function)) {
+ channel->callbacks->channel_eof_function(channel->session,
+ channel,
+ channel->callbacks->userdata);
+ }
+
leave_function();
return SSH_PACKET_USED;
}
@@ -560,6 +587,12 @@ SSH_PACKET_CALLBACK(channel_rcv_close) {
* buffer because the eof is ignored until the buffer is empty.
*/
+ if(ssh_callbacks_exists(channel->callbacks, channel_close_function)) {
+ channel->callbacks->channel_close_function(channel->session,
+ channel,
+ channel->callbacks->userdata);
+ }
+
leave_function();
return SSH_PACKET_USED;
}