diff --git a/include/libssh/session.h b/include/libssh/session.h index 09ed655d..2dae9ccb 100644 --- a/include/libssh/session.h +++ b/include/libssh/session.h @@ -65,8 +65,6 @@ struct ssh_session_struct { ssh_string banner; /* that's the issue banner from the server */ - char *remotebanner; /* that's the SSH- banner from - remote host. */ char *discon_msg; /* disconnect message from the remote host */ ssh_buffer in_buffer; diff --git a/libssh/client.c b/libssh/client.c index 580a7d5c..117afe90 100644 --- a/libssh/client.c +++ b/libssh/client.c @@ -65,6 +65,21 @@ static void socket_callback_connected(int code, int errno, void *user){ leave_function(); } +/** + * @internal + * @brief Callback to be called when the socket received an exception code. + * @param user is a pointer to session + */ +static void socket_callback_exception(int code, int errno, void *user){ + ssh_session session=(ssh_session)user; + enter_function(); + ssh_log(session,SSH_LOG_RARE,"Socket exception callback: %d (%d)",code, errno); + session->session_state=SSH_SESSION_STATE_ERROR; + ssh_set_error(session,SSH_FATAL,"Socket error: %s",strerror(errno)); + connection_callback(session); + leave_function(); +} + /** * @internal * @@ -96,8 +111,9 @@ static int callback_receive_banner(const void *data, size_t len, void *user) { str=strdup(buffer); /* number of bytes read */ ret=i+1; - session->remotebanner=str; + session->serverbanner=str; session->session_state=SSH_SESSION_STATE_BANNER_RECEIVED; + ssh_log(session,SSH_LOG_PACKET,"Received banner: %s",str); connection_callback(session); leave_function(); return ret; @@ -510,6 +526,7 @@ static void connection_callback(ssh_session session){ case SSH_SESSION_STATE_NONE: case SSH_SESSION_STATE_CONNECTING: case SSH_SESSION_STATE_SOCKET_CONNECTED: + break; case SSH_SESSION_STATE_BANNER_RECEIVED: if (session->serverbanner == NULL) { goto error; @@ -535,9 +552,11 @@ static void connection_callback(ssh_session session){ } /* from now, the packet layer is handling incoming packets */ session->socket_callbacks.data=ssh_packet_socket_callback; + ssh_packet_set_default_callbacks(session); ssh_send_banner(session, 0); set_status(session, 0.5); session->session_state=SSH_SESSION_STATE_INITIAL_KEX; + break; case SSH_SESSION_STATE_INITIAL_KEX: switch (session->version) { case 2: @@ -614,6 +633,7 @@ int ssh_connect(ssh_session session) { ssh_socket_set_callbacks(session->socket,&session->socket_callbacks); session->socket_callbacks.connected=socket_callback_connected; session->socket_callbacks.data=callback_receive_banner; + session->socket_callbacks.exception=socket_callback_exception; session->socket_callbacks.user=session; if (session->fd != -1) { ssh_socket_set_fd(session->socket, session->fd); @@ -631,11 +651,13 @@ int ssh_connect(ssh_session session) { set_status(session, 0.2); session->alive = 1; + ssh_log(session,SSH_LOG_PROTOCOL,"Socket connecting, now waiting for the callbacks to work"); while(session->session_state != SSH_SESSION_STATE_ERROR && session->session_state != SSH_SESSION_STATE_AUTHENTICATING){ /* loop until SSH_SESSION_STATE_BANNER_RECEIVED or * SSH_SESSION_STATE_ERROR */ - + ssh_handle_packets(session); + ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state); } leave_function(); return 0; diff --git a/libssh/packet.c b/libssh/packet.c index ef406bcc..09b0a745 100644 --- a/libssh/packet.c +++ b/libssh/packet.c @@ -311,7 +311,7 @@ void ssh_packet_set_default_callbacks(ssh_session session){ */ void ssh_packet_process(ssh_session session, uint8_t type){ struct ssh_iterator *i; - int r; + int r=SSH_PACKET_NOT_USED; ssh_packet_callbacks cb; enter_function(); ssh_log(session,SSH_LOG_PACKET, "Dispatching handler for packet type %d",type); @@ -335,6 +335,8 @@ void ssh_packet_process(ssh_session session, uint8_t type){ if(r==SSH_PACKET_USED) break; } + if(r==SSH_PACKET_NOT_USED) + ssh_log(session,SSH_LOG_RARE,"Couldn't do anything with packet type %d",type); error: leave_function(); } diff --git a/libssh/socket.c b/libssh/socket.c index 93e76a0d..85afe81a 100644 --- a/libssh/socket.c +++ b/libssh/socket.c @@ -163,7 +163,7 @@ int ssh_socket_pollcallback(ssh_poll_handle p, int fd, int revents, void *v_s){ if(r<0){ if(p != NULL) ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN); - if(s->callbacks){ + if(s->callbacks && s->callbacks->exception){ s->callbacks->exception( SSH_SOCKET_EXCEPTION_ERROR, s->last_errno,s->callbacks->user); @@ -171,7 +171,7 @@ int ssh_socket_pollcallback(ssh_poll_handle p, int fd, int revents, void *v_s){ } if(r==0){ ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN); - if(s->callbacks){ + if(s->callbacks && s->callbacks->exception){ s->callbacks->exception( SSH_SOCKET_EXCEPTION_EOF, 0,s->callbacks->user); @@ -180,7 +180,7 @@ int ssh_socket_pollcallback(ssh_poll_handle p, int fd, int revents, void *v_s){ if(r>0){ /* Bufferize the data and then call the callback */ buffer_add_data(s->in_buffer,buffer,r); - if(s->callbacks){ + if(s->callbacks && s->callbacks->data){ r= s->callbacks->data(buffer_get_rest(s->in_buffer), buffer_get_rest_len(s->in_buffer), s->callbacks->user); @@ -206,12 +206,12 @@ int ssh_socket_pollcallback(ssh_poll_handle p, int fd, int revents, void *v_s){ buffer_get_rest_len(s->out_buffer)); if(w>0) buffer_pass_bytes(s->out_buffer,w); - } else if(s->callbacks){ + } else if(s->callbacks && s->callbacks->controlflow){ /* Otherwise advertise the upper level that write can be done */ s->callbacks->controlflow(SSH_SOCKET_FLOW_WRITEWONTBLOCK,s->callbacks->user); - ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLOUT); - /* TODO: Find a way to put back POLLOUT when buffering occurs */ } + ssh_poll_remove_events(p,POLLOUT); + /* TODO: Find a way to put back POLLOUT when buffering occurs */ } return 0; } @@ -785,7 +785,6 @@ int ssh_socket_get_status(ssh_socket s) { int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bind_addr){ socket_t fd; ssh_session session=s->session; - ssh_poll_ctx ctx; enter_function(); if(s->state != SSH_SOCKET_NONE) return SSH_ERROR; @@ -795,31 +794,10 @@ int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bin return SSH_ERROR; ssh_socket_set_fd(s,fd); s->state=SSH_SOCKET_CONNECTING; - if(s->callbacks && s->callbacks->connected && s->poll){ - /* POLLOUT is the event to wait for in a nonblocking connect */ - ssh_poll_set_events(s->poll,POLLOUT); - leave_function(); - return SSH_OK; - } else { - /* we have to do the connect ourselves */ - ssh_poll_set_events(ssh_socket_get_poll_handle(s),POLLOUT); - ctx=ssh_poll_ctx_new(1); - ssh_poll_ctx_add(ctx,s->poll); - while(s->state == SSH_SOCKET_CONNECTING){ - ssh_poll_ctx_dopoll(ctx,-1); - } - ssh_poll_ctx_free(ctx); - if(s->state == SSH_SOCKET_CONNECTED){ - ssh_log(session,SSH_LOG_PACKET,"ssh_socket_connect blocking: connected"); - leave_function(); - return SSH_OK; - } else { - ssh_log(session,SSH_LOG_PACKET,"ssh_socket_connect blocking: not connected"); - ssh_set_error(session,SSH_FATAL,"Error during blocking connect: %d",s->last_errno); - leave_function(); - return SSH_ERROR; - } - } + /* POLLOUT is the event to wait for in a nonblocking connect */ + ssh_poll_set_events(ssh_socket_get_poll_handle(s),POLLOUT); + leave_function(); + return SSH_OK; } /** @} */