diff options
-rw-r--r-- | include/libssh/session.h | 5 | ||||
-rw-r--r-- | src/client.c | 25 |
2 files changed, 28 insertions, 2 deletions
diff --git a/include/libssh/session.h b/include/libssh/session.h index 406ba139..55eabcdd 100644 --- a/include/libssh/session.h +++ b/include/libssh/session.h @@ -51,6 +51,10 @@ enum ssh_dh_state_e { DH_STATE_FINISHED }; +enum ssh_pending_call_e { + SSH_PENDING_CALL_NONE = 0, + SSH_PENDING_CALL_CONNECT +}; /* libssh calls may block an undefined amount of time */ #define SSH_SESSION_FLAG_BLOCKING 1 @@ -89,6 +93,7 @@ struct ssh_session_struct { /* the states are used by the nonblocking stuff to remember */ /* where it was before being interrupted */ + enum ssh_pending_call_e pending_call_state; enum ssh_session_state_e session_state; int packet_state; enum ssh_dh_state_e dh_handshake_state; diff --git a/src/client.c b/src/client.c index 7a96d6ae..c77e5828 100644 --- a/src/client.c +++ b/src/client.c @@ -594,6 +594,8 @@ static void ssh_client_connection_callback(ssh_session session){ * @param[in] session The ssh session to connect. * * @returns SSH_OK on success, SSH_ERROR on error. + * @returns SSH_AGAIN, if the session is in nonblocking mode, + * and call must be done again. * * @see ssh_new() * @see ssh_disconnect() @@ -607,7 +609,16 @@ int ssh_connect(ssh_session session) { } enter_function(); - + switch(session->pending_call_state){ + case SSH_PENDING_CALL_NONE: + break; + case SSH_PENDING_CALL_CONNECT: + goto pending; + default: + ssh_set_error(session,SSH_FATAL,"Bad call during pending SSH call in ssh_connect"); + leave_function(); + return SSH_ERROR; + } session->alive = 0; session->client = 1; @@ -657,15 +668,25 @@ int ssh_connect(ssh_session session) { session->alive = 1; 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 */ - ssh_handle_packets(session,-1); + 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; + } } leave_function(); + session->pending_call_state=SSH_PENDING_CALL_NONE; if(session->session_state == SSH_SESSION_STATE_ERROR || session->session_state == SSH_SESSION_STATE_DISCONNECTED) return SSH_ERROR; return SSH_OK; |