diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2010-01-03 23:16:14 +0100 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2010-01-03 23:16:14 +0100 |
commit | 804bb44edaba78d0181b1d85d2e7fa832027f393 (patch) | |
tree | fbb99c6bd8b37a77d1c6370fb416019cf038c621 /libssh/channels.c | |
parent | 1b15896e8b29561447fff9a7bcaa028179eab51b (diff) | |
download | libssh-804bb44edaba78d0181b1d85d2e7fa832027f393.tar.gz libssh-804bb44edaba78d0181b1d85d2e7fa832027f393.tar.xz libssh-804bb44edaba78d0181b1d85d2e7fa832027f393.zip |
Channel requests are asynchronous
Exec example also runs perfectly now.
Diffstat (limited to 'libssh/channels.c')
-rw-r--r-- | libssh/channels.c | 90 |
1 files changed, 77 insertions, 13 deletions
diff --git a/libssh/channels.c b/libssh/channels.c index 2ec1a8b..ab2e6df 100644 --- a/libssh/channels.c +++ b/libssh/channels.c @@ -1078,11 +1078,64 @@ void channel_set_blocking(ssh_channel channel, int blocking) { channel->blocking = (blocking == 0 ? 0 : 1); } +/** @internal + * @brief handle a SSH_CHANNEL_SUCCESS packet and set the channel + * state. + */ SSH_PACKET_CALLBACK(ssh_packet_channel_success){ + ssh_channel channel; + (void)type; + (void)user; + enter_function(); + channel=channel_from_msg(session,packet); + if (channel == NULL) { + ssh_log(session, SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session)); + leave_function(); + return SSH_PACKET_USED; + } + + ssh_log(session, SSH_LOG_PACKET, + "Received SSH_CHANNEL_SUCCESS on channel (%d:%d)", + channel->local_channel, + channel->remote_channel); + if(channel->request_state != SSH_CHANNEL_REQ_STATE_PENDING){ + ssh_log(session, SSH_LOG_RARE, "SSH_CHANNEL_SUCCESS received in incorrect state %d", + channel->request_state); + } else { + channel->request_state=SSH_CHANNEL_REQ_STATE_ACCEPTED; + } + + leave_function(); return SSH_PACKET_USED; } +/** @internal + * @brief handle a SSH_CHANNEL_FAILURE packet and set the channel + * state. + */ SSH_PACKET_CALLBACK(ssh_packet_channel_failure){ + ssh_channel channel; + (void)type; + (void)user; + enter_function(); + channel=channel_from_msg(session,packet); + if (channel == NULL) { + ssh_log(session, SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session)); + leave_function(); + return SSH_PACKET_USED; + } + + ssh_log(session, SSH_LOG_PACKET, + "Received SSH_CHANNEL_FAILURE on channel (%d:%d)", + channel->local_channel, + channel->remote_channel); + if(channel->request_state != SSH_CHANNEL_REQ_STATE_PENDING){ + ssh_log(session, SSH_LOG_RARE, "SSH_CHANNEL_FAILURE received in incorrect state %d", + channel->request_state); + } else { + channel->request_state=SSH_CHANNEL_REQ_STATE_DENIED; + } + leave_function(); return SSH_PACKET_USED; } @@ -1127,25 +1180,36 @@ static int channel_request(ssh_channel channel, const char *request, ssh_log(session, SSH_LOG_PACKET, "Sent a SSH_MSG_CHANNEL_REQUEST %s", request); if (reply == 0) { + channel->request_state = SSH_CHANNEL_REQ_STATE_NONE; leave_function(); return SSH_OK; } - - rc = packet_wait(session, SSH2_MSG_CHANNEL_SUCCESS, 1); - if (rc == SSH_ERROR) { - if (session->in_packet.type == SSH2_MSG_CHANNEL_FAILURE) { - ssh_log(session, SSH_LOG_PACKET, - "%s channel request failed", request); + while(channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING){ + ssh_handle_packets(session); + } + /* we received something */ + switch (channel->request_state){ + case SSH_CHANNEL_REQ_STATE_ERROR: + rc=SSH_ERROR; + break; + case SSH_CHANNEL_REQ_STATE_DENIED: ssh_set_error(session, SSH_REQUEST_DENIED, "Channel request %s failed", request); - } else { - ssh_log(session, SSH_LOG_RARE, - "Received an unexpected %d message", session->in_packet.type); - } - } else { - ssh_log(session, SSH_LOG_RARE, "Received a SUCCESS"); + rc=SSH_ERROR; + break; + case SSH_CHANNEL_REQ_STATE_ACCEPTED: + ssh_log(session, SSH_LOG_PROTOCOL, + "Channel request %s success",request); + rc=SSH_OK; + break; + case SSH_CHANNEL_REQ_STATE_NONE: + case SSH_CHANNEL_REQ_STATE_PENDING: + /* Never reached */ + ssh_set_error(session, SSH_FATAL, "Invalid state in channel_request()"); + rc=SSH_ERROR; + break; } - + channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; leave_function(); return rc; error: |