diff options
-rw-r--r-- | include/libssh/session.h | 9 | ||||
-rw-r--r-- | src/client.c | 37 | ||||
-rw-r--r-- | src/session.c | 37 |
3 files changed, 68 insertions, 15 deletions
diff --git a/include/libssh/session.h b/include/libssh/session.h index 55eabcdd..3bbd0a8a 100644 --- a/include/libssh/session.h +++ b/include/libssh/session.h @@ -158,8 +158,15 @@ struct ssh_session_struct { char *ProxyCommand; }; +/** @internal + * @brief a termination function evaluates the status of an object + * @param user[in] object to evaluate + * @returns 1 if the polling routine should terminate, 0 instead + */ +typedef int (*ssh_termination_function)(void *user); int ssh_handle_packets(ssh_session session, int timeout); - +int ssh_handle_packets_termination(ssh_session session, int timeout, + ssh_termination_function fct, void *user); void ssh_socket_exception_callback(int code, int errno_code, void *user); #endif /* SESSION_H_ */ diff --git a/src/client.c b/src/client.c index c77e5828..a737ba80 100644 --- a/src/client.c +++ b/src/client.c @@ -588,6 +588,21 @@ static void ssh_client_connection_callback(ssh_session session){ leave_function(); } +/** @internal + * @brief describe under which conditions the ssh_connect function may stop + */ +static int ssh_connect_termination(void *user){ + ssh_session session = (ssh_session)user; + switch(session->session_state){ + case SSH_SESSION_STATE_ERROR: + case SSH_SESSION_STATE_AUTHENTICATING: + case SSH_SESSION_STATE_DISCONNECTED: + return 1; + default: + return 0; + } +} + /** * @brief Connect to the ssh server. * @@ -670,20 +685,14 @@ int ssh_connect(ssh_session session) { ssh_log(session,SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work"); pending: session->pending_call_state=SSH_PENDING_CALL_CONNECT; - while(session->session_state != SSH_SESSION_STATE_ERROR && - session->session_state != SSH_SESSION_STATE_AUTHENTICATING && - session->session_state != SSH_SESSION_STATE_DISCONNECTED){ - /* loop until SSH_SESSION_STATE_BANNER_RECEIVED or - * SSH_SESSION_STATE_ERROR */ - if(ssh_is_blocking(session)) - ssh_handle_packets(session,-1); - else - ssh_handle_packets(session,0); - ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state); - if(!ssh_is_blocking(session)){ - leave_function(); - return SSH_AGAIN; - } + if(ssh_is_blocking(session)) + ssh_handle_packets_termination(session,-1,ssh_connect_termination,session); + else + ssh_handle_packets_termination(session,0,ssh_connect_termination, session); + ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state); + if(!ssh_is_blocking(session) && !ssh_connect_termination(session)){ + leave_function(); + return SSH_AGAIN; } leave_function(); session->pending_call_state=SSH_PENDING_CALL_NONE; diff --git a/src/session.c b/src/session.c index c862e714..83436dc2 100644 --- a/src/session.c +++ b/src/session.c @@ -396,6 +396,43 @@ int ssh_handle_packets(ssh_session session, int timeout) { } /** + * @internal + * + * @brief Poll the current session for an event and call the appropriate + * callbacks. + * + * This will block until termination fuction returns true, or timeout expired. + * + * @param[in] session The session handle to use. + * + * @param[in] timeout Set an upper limit on the time for which this function + * will block, in milliseconds. Specifying a negative value + * means an infinite timeout. This parameter is passed to + * the poll() function. + * @param[in] fct Termination function to be used to determine if it is + * possible to stop polling. + * @param[in] user User parameter to be passed to fct termination function. + * @return SSH_OK on success, SSH_ERROR otherwise. + */ +int ssh_handle_packets_termination(ssh_session session, int timeout, + ssh_termination_function fct, void *user){ + int ret; + while(!fct(user)){ + ret = ssh_handle_packets(session, timeout); + if(ret == SSH_ERROR) + return SSH_ERROR; + if(timeout == 0){ + if(fct(user)) + return SSH_OK; + else + return SSH_AGAIN; + } + /* TODO: verify that total timeout has not expired and then return SSH_AGAIN */ + } + return ret; +} + +/** * @brief Get session status * * @param session The ssh session to use. |