Async connection + banner fetch is working
Этот коммит содержится в:
родитель
0de35ca8f0
Коммит
3ace7817b4
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
/** @}
|
||||
*/
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user