1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-08-08 19:02:06 +03:00

channels: made the remaining calls nonblocking + fix #52

This commit is contained in:
Aris Adamantiadis
2011-08-25 17:42:22 +03:00
parent 510c741229
commit a2c94abb92

View File

@@ -1169,6 +1169,8 @@ int channel_write_common(ssh_channel channel, const void *data,
uint32_t origlen = len; uint32_t origlen = len;
size_t effectivelen; size_t effectivelen;
size_t maxpacketlen; size_t maxpacketlen;
int timeout;
int rc;
if(channel == NULL) { if(channel == NULL) {
return -1; return -1;
@@ -1186,7 +1188,10 @@ int channel_write_common(ssh_channel channel, const void *data,
} }
enter_function(); enter_function();
if(ssh_is_blocking(session))
timeout = -2;
else
timeout = 0;
/* /*
* Handle the max packet len from remote side, be nice * Handle the max packet len from remote side, be nice
* 10 bytes for the headers * 10 bytes for the headers
@@ -1227,7 +1232,10 @@ int channel_write_common(ssh_channel channel, const void *data,
/* nothing can be written */ /* nothing can be written */
ssh_log(session, SSH_LOG_PROTOCOL, ssh_log(session, SSH_LOG_PROTOCOL,
"Wait for a growing window message..."); "Wait for a growing window message...");
rc = ssh_handle_packets(session, timeout);
if (rc == SSH_ERROR || (channel->remote_window == 0 && timeout==0))
goto out; goto out;
continue;
} }
effectivelen = len > channel->remote_window ? channel->remote_window : len; effectivelen = len > channel->remote_window ? channel->remote_window : len;
} else { } else {
@@ -1266,7 +1274,10 @@ int channel_write_common(ssh_channel channel, const void *data,
len -= effectivelen; len -= effectivelen;
data = ((uint8_t*)data + effectivelen); data = ((uint8_t*)data + effectivelen);
} }
/* it's a good idea to flush the socket now */
do {
rc = ssh_handle_packets(session, timeout);
} while(ssh_socket_buffered_write_bytes(session->socket) > 0 && timeout != 0);
out: out:
leave_function(); leave_function();
return (int)(origlen - len); return (int)(origlen - len);
@@ -1985,19 +1996,20 @@ SSH_PACKET_CALLBACK(ssh_request_denied){
* *
* @param[in] reply Set if you expect a reply from server. * @param[in] reply Set if you expect a reply from server.
* *
* @return SSH_OK on success, SSH_ERROR if an error occured. * @return SSH_OK on success,
* SSH_ERROR if an error occurred,
* SSH_AGAIN if in nonblocking mode and call has
* to be done again.
*/ */
static int global_request(ssh_session session, const char *request, static int global_request(ssh_session session, const char *request,
ssh_buffer buffer, int reply) { ssh_buffer buffer, int reply) {
ssh_string req = NULL; ssh_string req = NULL;
int rc = SSH_ERROR; int rc = SSH_ERROR;
int timeout;
enter_function(); enter_function();
if(session->global_req_state != SSH_CHANNEL_REQ_STATE_NONE){ if(session->global_req_state != SSH_CHANNEL_REQ_STATE_NONE)
ssh_set_error(session,SSH_FATAL,"Invalid state in start of global_request()"); goto pending;
leave_function();
return rc;
}
req = ssh_string_from_char(request); req = ssh_string_from_char(request);
if (req == NULL) { if (req == NULL) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
@@ -2033,12 +2045,20 @@ static int global_request(ssh_session session, const char *request,
leave_function(); leave_function();
return SSH_OK; return SSH_OK;
} }
pending:
if(ssh_is_blocking(session))
timeout=-2;
else
timeout=0;
while(session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING){ while(session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING){
rc=ssh_handle_packets(session, -2); rc=ssh_handle_packets(session, timeout);
if(rc==SSH_ERROR){ if(rc==SSH_ERROR){
session->global_req_state = SSH_CHANNEL_REQ_STATE_ERROR; session->global_req_state = SSH_CHANNEL_REQ_STATE_ERROR;
break; break;
} }
if(session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
&& timeout == 0)
break;
} }
switch(session->global_req_state){ switch(session->global_req_state){
case SSH_CHANNEL_REQ_STATE_ACCEPTED: case SSH_CHANNEL_REQ_STATE_ACCEPTED:
@@ -2054,10 +2074,11 @@ static int global_request(ssh_session session, const char *request,
break; break;
case SSH_CHANNEL_REQ_STATE_ERROR: case SSH_CHANNEL_REQ_STATE_ERROR:
case SSH_CHANNEL_REQ_STATE_NONE: case SSH_CHANNEL_REQ_STATE_NONE:
case SSH_CHANNEL_REQ_STATE_PENDING:
rc=SSH_ERROR; rc=SSH_ERROR;
break; break;
case SSH_CHANNEL_REQ_STATE_PENDING:
rc=SSH_AGAIN;
break;
} }
leave_function(); leave_function();
@@ -2093,6 +2114,9 @@ int ssh_forward_listen(ssh_session session, const char *address, int port, int *
int rc = SSH_ERROR; int rc = SSH_ERROR;
uint32_t tmp; uint32_t tmp;
if(session->global_req_state != SSH_CHANNEL_REQ_STATE_NONE)
goto pending;
buffer = ssh_buffer_new(); buffer = ssh_buffer_new();
if (buffer == NULL) { if (buffer == NULL) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
@@ -2110,9 +2134,11 @@ int ssh_forward_listen(ssh_session session, const char *address, int port, int *
ssh_set_error_oom(session); ssh_set_error_oom(session);
goto error; goto error;
} }
pending:
rc = global_request(session, "tcpip-forward", buffer, 1); rc = global_request(session, "tcpip-forward", buffer, 1);
/* TODO: FIXME no guarantee the last packet we received contains
* that info */
if (rc == SSH_OK && port == 0 && bound_port) { if (rc == SSH_OK && port == 0 && bound_port) {
buffer_get_u32(session->in_buffer, &tmp); buffer_get_u32(session->in_buffer, &tmp);
*bound_port = ntohl(tmp); *bound_port = ntohl(tmp);
@@ -2155,6 +2181,9 @@ int ssh_forward_cancel(ssh_session session, const char *address, int port) {
ssh_string addr = NULL; ssh_string addr = NULL;
int rc = SSH_ERROR; int rc = SSH_ERROR;
if(session->global_req_state != SSH_CHANNEL_REQ_STATE_NONE)
goto pending;
buffer = ssh_buffer_new(); buffer = ssh_buffer_new();
if (buffer == NULL) { if (buffer == NULL) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
@@ -2172,7 +2201,7 @@ int ssh_forward_cancel(ssh_session session, const char *address, int port) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
goto error; goto error;
} }
pending:
rc = global_request(session, "cancel-tcpip-forward", buffer, 1); rc = global_request(session, "cancel-tcpip-forward", buffer, 1);
error: error:
@@ -2726,17 +2755,21 @@ ssh_session ssh_channel_get_session(ssh_channel channel) {
* or eof not sent. * or eof not sent.
*/ */
int ssh_channel_get_exit_status(ssh_channel channel) { int ssh_channel_get_exit_status(ssh_channel channel) {
int timeout;
if(channel == NULL) { if(channel == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
if (channel->local_eof == 0) { if (channel->local_eof == 0) {
return -1; return channel->exit_status;
} }
if(ssh_is_blocking(channel->session))
timeout = -2;
else
timeout = 0;
while ((channel->remote_eof == 0 || channel->exit_status == -1) && channel->session->alive) { while ((channel->remote_eof == 0 || channel->exit_status == -1) && channel->session->alive) {
/* Parse every incoming packet */ /* Parse every incoming packet */
if (ssh_handle_packets(channel->session, -2) != SSH_OK) { if (ssh_handle_packets(channel->session, timeout) != SSH_OK) {
return -1; return -1;
} }
/* XXX We should actually wait for a close packet and not a close /* XXX We should actually wait for a close packet and not a close
@@ -2747,6 +2780,8 @@ int ssh_channel_get_exit_status(ssh_channel channel) {
* come anymore */ * come anymore */
break; break;
} }
if (timeout == 0)
break;
} }
return channel->exit_status; return channel->exit_status;
@@ -3022,7 +3057,8 @@ int ssh_channel_open_reverse_forward(ssh_channel channel, const char *remotehost
session = channel->session; session = channel->session;
enter_function(); enter_function();
if(channel->state != SSH_CHANNEL_STATE_NOT_OPEN)
goto pending;
payload = ssh_buffer_new(); payload = ssh_buffer_new();
if (payload == NULL) { if (payload == NULL) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
@@ -3052,7 +3088,7 @@ int ssh_channel_open_reverse_forward(ssh_channel channel, const char *remotehost
ssh_set_error_oom(session); ssh_set_error_oom(session);
goto error; goto error;
} }
pending:
rc = channel_open(channel, rc = channel_open(channel,
"forwarded-tcpip", "forwarded-tcpip",
CHANNEL_INITIAL_WINDOW, CHANNEL_INITIAL_WINDOW,
@@ -3096,12 +3132,13 @@ int ssh_channel_open_x11(ssh_channel channel,
ssh_set_error_invalid(channel->session, __FUNCTION__); ssh_set_error_invalid(channel->session, __FUNCTION__);
return rc; return rc;
} }
session = channel->session; session = channel->session;
enter_function(); enter_function();
if(channel->state != SSH_CHANNEL_STATE_NOT_OPEN)
goto pending;
payload = ssh_buffer_new(); payload = ssh_buffer_new();
if (payload == NULL) { if (payload == NULL) {
ssh_set_error_oom(session); ssh_set_error_oom(session);
@@ -3119,7 +3156,7 @@ int ssh_channel_open_x11(ssh_channel channel,
ssh_set_error_oom(session); ssh_set_error_oom(session);
goto error; goto error;
} }
pending:
rc = channel_open(channel, rc = channel_open(channel,
"x11", "x11",
CHANNEL_INITIAL_WINDOW, CHANNEL_INITIAL_WINDOW,