aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/libssh.h5
-rw-r--r--src/poll.c64
2 files changed, 69 insertions, 0 deletions
diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h
index 2604b419..9dd6b495 100644
--- a/include/libssh/libssh.h
+++ b/include/libssh/libssh.h
@@ -475,7 +475,12 @@ LIBSSH_API void ssh_string_free_char(char *s);
LIBSSH_API int ssh_getpass(const char *prompt, char *buf, size_t len, int echo,
int verify);
+
+typedef int (*ssh_event_callback)(socket_t fd, int revents, void *userdata);
+
LIBSSH_API ssh_event ssh_event_new(void);
+LIBSSH_API int ssh_event_add_fd(ssh_event event, socket_t fd, short events,
+ ssh_event_callback cb, void *userdata);
LIBSSH_API int ssh_event_add_session(ssh_event event, ssh_session session);
LIBSSH_API int ssh_event_remove_session(ssh_event event, ssh_session session);
LIBSSH_API void ssh_event_free(ssh_event event);
diff --git a/src/poll.c b/src/poll.c
index 618ab01e..233e8c30 100644
--- a/src/poll.c
+++ b/src/poll.c
@@ -685,6 +685,11 @@ ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session){
/* public event API */
+struct ssh_event_fd_wrapper {
+ ssh_event_callback cb;
+ void * userdata;
+};
+
struct ssh_event_struct {
ssh_poll_ctx ctx;
#ifdef WITH_SERVER
@@ -727,6 +732,65 @@ ssh_event ssh_event_new(void) {
return event;
}
+static int ssh_event_fd_wrapper_callback(ssh_poll_handle p, socket_t fd, int revents,
+ void *userdata) {
+ struct ssh_event_fd_wrapper *pw = (struct ssh_event_fd_wrapper *)userdata;
+
+ (void)p;
+ if(pw->cb != NULL) {
+ return pw->cb(fd, revents, pw->userdata);
+ }
+ return 0;
+}
+
+/**
+ * @brief Add a fd to the event and assign it a callback,
+ * when used in blocking mode.
+ * @param event The ssh_event
+ * @param fd Socket that will be polled.
+ * @param events Poll events that will be monitored for the socket. i.e.
+ * POLLIN, POLLPRI, POLLOUT, POLLERR, POLLHUP, POLLNVAL
+ * @param cb Function to be called if any of the events are set.
+ * The prototype of cb is:
+ * int (*ssh_event_callback)(socket_t fd, int revents,
+ * void *userdata);
+ * @param userdata Userdata to be passed to the callback function. NULL if
+ * not needed.
+ *
+ * @returns SSH_OK on success
+ * SSH_ERROR on failure
+ */
+int ssh_event_add_fd(ssh_event event, socket_t fd, short events,
+ ssh_event_callback cb, void *userdata) {
+ ssh_poll_handle p;
+ struct ssh_event_fd_wrapper *pw;
+
+ if(event == NULL || event->ctx == NULL || cb == NULL
+ || fd == SSH_INVALID_SOCKET) {
+ return SSH_ERROR;
+ }
+ pw = malloc(sizeof(struct ssh_event_fd_wrapper));
+ if(pw == NULL) {
+ return SSH_ERROR;
+ }
+
+ pw->cb = cb;
+ pw->userdata = userdata;
+
+ p = ssh_poll_new(fd, events, ssh_event_fd_wrapper_callback, pw);
+ if(p == NULL) {
+ free(pw);
+ return SSH_ERROR;
+ }
+
+ if(ssh_poll_ctx_add(event->ctx, p) < 0) {
+ free(pw);
+ ssh_poll_free(p);
+ return SSH_ERROR;
+ }
+ return SSH_OK;
+}
+
/**
* @brief remove the poll handle from session and assign them to a event,
* when used in blocking mode.