Async connection + banner fetch is working

This commit is contained in:
Aris Adamantiadis
2009-12-11 23:26:25 +01:00
parent 0de35ca8f0
commit 3ace7817b4
4 changed files with 37 additions and 37 deletions

View File

@@ -65,8 +65,6 @@ struct ssh_session_struct {
ssh_string banner; /* that's the issue banner from ssh_string banner; /* that's the issue banner from
the server */ the server */
char *remotebanner; /* that's the SSH- banner from
remote host. */
char *discon_msg; /* disconnect message from char *discon_msg; /* disconnect message from
the remote host */ the remote host */
ssh_buffer in_buffer; ssh_buffer in_buffer;

View File

@@ -65,6 +65,21 @@ static void socket_callback_connected(int code, int errno, void *user){
leave_function(); 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 * @internal
* *
@@ -96,8 +111,9 @@ static int callback_receive_banner(const void *data, size_t len, void *user) {
str=strdup(buffer); str=strdup(buffer);
/* number of bytes read */ /* number of bytes read */
ret=i+1; ret=i+1;
session->remotebanner=str; session->serverbanner=str;
session->session_state=SSH_SESSION_STATE_BANNER_RECEIVED; session->session_state=SSH_SESSION_STATE_BANNER_RECEIVED;
ssh_log(session,SSH_LOG_PACKET,"Received banner: %s",str);
connection_callback(session); connection_callback(session);
leave_function(); leave_function();
return ret; return ret;
@@ -510,6 +526,7 @@ static void connection_callback(ssh_session session){
case SSH_SESSION_STATE_NONE: case SSH_SESSION_STATE_NONE:
case SSH_SESSION_STATE_CONNECTING: case SSH_SESSION_STATE_CONNECTING:
case SSH_SESSION_STATE_SOCKET_CONNECTED: case SSH_SESSION_STATE_SOCKET_CONNECTED:
break;
case SSH_SESSION_STATE_BANNER_RECEIVED: case SSH_SESSION_STATE_BANNER_RECEIVED:
if (session->serverbanner == NULL) { if (session->serverbanner == NULL) {
goto error; goto error;
@@ -535,9 +552,11 @@ static void connection_callback(ssh_session session){
} }
/* from now, the packet layer is handling incoming packets */ /* from now, the packet layer is handling incoming packets */
session->socket_callbacks.data=ssh_packet_socket_callback; session->socket_callbacks.data=ssh_packet_socket_callback;
ssh_packet_set_default_callbacks(session);
ssh_send_banner(session, 0); ssh_send_banner(session, 0);
set_status(session, 0.5); set_status(session, 0.5);
session->session_state=SSH_SESSION_STATE_INITIAL_KEX; session->session_state=SSH_SESSION_STATE_INITIAL_KEX;
break;
case SSH_SESSION_STATE_INITIAL_KEX: case SSH_SESSION_STATE_INITIAL_KEX:
switch (session->version) { switch (session->version) {
case 2: case 2:
@@ -614,6 +633,7 @@ int ssh_connect(ssh_session session) {
ssh_socket_set_callbacks(session->socket,&session->socket_callbacks); ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
session->socket_callbacks.connected=socket_callback_connected; session->socket_callbacks.connected=socket_callback_connected;
session->socket_callbacks.data=callback_receive_banner; session->socket_callbacks.data=callback_receive_banner;
session->socket_callbacks.exception=socket_callback_exception;
session->socket_callbacks.user=session; session->socket_callbacks.user=session;
if (session->fd != -1) { if (session->fd != -1) {
ssh_socket_set_fd(session->socket, session->fd); ssh_socket_set_fd(session->socket, session->fd);
@@ -631,11 +651,13 @@ int ssh_connect(ssh_session session) {
set_status(session, 0.2); set_status(session, 0.2);
session->alive = 1; 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 && while(session->session_state != SSH_SESSION_STATE_ERROR &&
session->session_state != SSH_SESSION_STATE_AUTHENTICATING){ session->session_state != SSH_SESSION_STATE_AUTHENTICATING){
/* loop until SSH_SESSION_STATE_BANNER_RECEIVED or /* loop until SSH_SESSION_STATE_BANNER_RECEIVED or
* SSH_SESSION_STATE_ERROR */ * SSH_SESSION_STATE_ERROR */
ssh_handle_packets(session);
ssh_log(session,SSH_LOG_PACKET,"ssh_connect: Actual state : %d",session->session_state);
} }
leave_function(); leave_function();
return 0; return 0;

View File

@@ -311,7 +311,7 @@ void ssh_packet_set_default_callbacks(ssh_session session){
*/ */
void ssh_packet_process(ssh_session session, uint8_t type){ void ssh_packet_process(ssh_session session, uint8_t type){
struct ssh_iterator *i; struct ssh_iterator *i;
int r; int r=SSH_PACKET_NOT_USED;
ssh_packet_callbacks cb; ssh_packet_callbacks cb;
enter_function(); enter_function();
ssh_log(session,SSH_LOG_PACKET, "Dispatching handler for packet type %d",type); 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) if(r==SSH_PACKET_USED)
break; break;
} }
if(r==SSH_PACKET_NOT_USED)
ssh_log(session,SSH_LOG_RARE,"Couldn't do anything with packet type %d",type);
error: error:
leave_function(); leave_function();
} }

View File

@@ -163,7 +163,7 @@ int ssh_socket_pollcallback(ssh_poll_handle p, int fd, int revents, void *v_s){
if(r<0){ if(r<0){
if(p != NULL) if(p != NULL)
ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN); ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN);
if(s->callbacks){ if(s->callbacks && s->callbacks->exception){
s->callbacks->exception( s->callbacks->exception(
SSH_SOCKET_EXCEPTION_ERROR, SSH_SOCKET_EXCEPTION_ERROR,
s->last_errno,s->callbacks->user); 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){ if(r==0){
ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN); ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN);
if(s->callbacks){ if(s->callbacks && s->callbacks->exception){
s->callbacks->exception( s->callbacks->exception(
SSH_SOCKET_EXCEPTION_EOF, SSH_SOCKET_EXCEPTION_EOF,
0,s->callbacks->user); 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){ if(r>0){
/* Bufferize the data and then call the callback */ /* Bufferize the data and then call the callback */
buffer_add_data(s->in_buffer,buffer,r); 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), r= s->callbacks->data(buffer_get_rest(s->in_buffer),
buffer_get_rest_len(s->in_buffer), buffer_get_rest_len(s->in_buffer),
s->callbacks->user); 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)); buffer_get_rest_len(s->out_buffer));
if(w>0) if(w>0)
buffer_pass_bytes(s->out_buffer,w); 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 */ /* Otherwise advertise the upper level that write can be done */
s->callbacks->controlflow(SSH_SOCKET_FLOW_WRITEWONTBLOCK,s->callbacks->user); 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; 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){ int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bind_addr){
socket_t fd; socket_t fd;
ssh_session session=s->session; ssh_session session=s->session;
ssh_poll_ctx ctx;
enter_function(); enter_function();
if(s->state != SSH_SOCKET_NONE) if(s->state != SSH_SOCKET_NONE)
return SSH_ERROR; 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; return SSH_ERROR;
ssh_socket_set_fd(s,fd); ssh_socket_set_fd(s,fd);
s->state=SSH_SOCKET_CONNECTING; s->state=SSH_SOCKET_CONNECTING;
if(s->callbacks && s->callbacks->connected && s->poll){ /* POLLOUT is the event to wait for in a nonblocking connect */
/* POLLOUT is the event to wait for in a nonblocking connect */ ssh_poll_set_events(ssh_socket_get_poll_handle(s),POLLOUT);
ssh_poll_set_events(s->poll,POLLOUT); leave_function();
leave_function(); return SSH_OK;
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;
}
}
} }
/** @} /** @}
*/ */