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:
@@ -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...");
|
||||||
goto out;
|
rc = ssh_handle_packets(session, timeout);
|
||||||
|
if (rc == SSH_ERROR || (channel->remote_window == 0 && timeout==0))
|
||||||
|
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,
|
||||||
|
Reference in New Issue
Block a user