aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/session.h5
-rw-r--r--src/client.c25
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;