Archived Forum Post

Index of archived forum posts

Question:

SSH OpenSessionChannel/SendReqExec fails on subsequent requests

Jun 01 '16 at 18:24

I'm having an issue trying to execute multiple commands over SSH using the OpenSessionChannel/SendReqExec pattern. It always works on the first command, but the second always fails, with OpenSessionChannel returning -1.

The LastErrorText property contains "SocketError: WSAECONNABORTED An established connection was aborted by the software in your host machine. For more information see this Chilkat Blog post: http://www.cknotes.com/?p=91. No longer connected to the SSH server."

If of course followed the link but in my case I'm not sending or processing large amounts of data. Anyways, the documentation states that this should be possible (SendReqExec). Has anyone actually gotten this to work?

A channel only exists for a single request. You may not call SendReqExec multiple times on the same open channel. The reason is that the SSH server automatically closes the channel at the end of the exec. The solution is to call OpenSessionChannel to get a new channel, and then call SendReqExec using the new channel. It is OK to have more than one channel open simultaneously.

To be explicit, the calls I'm making (after connecting and authenticating) are:

// Open a session channel to send commands over
var channelNum = _sshClient.OpenSessionChannel();
if (channelNum < 0)
{
    throw new LoginFailedException($"Failed to open a session channel: {_sshClient.LastErrorText}");
}

// Execute the command
if (!_sshClient.SendReqExec(channelNum, commandText))
{
    throw new CommandFailedException($"The command failed to execute: {_sshClient.LastErrorText}");
}

// Read the response
if (!_sshClient.ChannelReceiveToClose(channelNum))
{
    throw new CommandFailedException($"Failed to receive the command response: {_sshClient.LastErrorText}");
}

LastRead = _sshClient.GetReceivedText(channelNum, "ansi");

Does anyone have a clue?


Answer

Thanks, I'll have a look tomorrow morning.. It should be possible to have multiple channels open at once, and it should be possible to SendReqExec on a channel, and then do it again on a new channel on the same SSH connection..


Answer

I tested it and found no problem. If you're not using the latest version of Chilkat, then download and test with the latest. If you already are using the latest version, I can provide a pre-release of the next version, but I need to know the exact build required.

Here's the C++ code I used for testing:

bool SshTesting::do_sendReqExec(const char testName, CkSsh &ssh, const char command)
    {
    int channelNum = ssh.OpenSessionChannel();
    if (channelNum < 0) return failed(testName,ssh);
    printf("channelNum = %dn",channelNum);

//  Request a directory listing on the remote server:
//  If your server is Windows, change the string from "ls" to "dir"
bool success = ssh.SendReqExec(channelNum,command);
if (success != true) return failed(testName,ssh);

// Read some of the response...
int retval = ssh.ChannelRead(channelNum);
if (retval == -1) return failed(testName,ssh);
printf("ChannelRead retval = %d\n",retval);

success = ssh.ChannelReceiveToClose(channelNum);
if (success != true) return failed(testName,ssh);

const char *cmdOutput = ssh.getReceivedText(channelNum,"ansi");
if (cmdOutput == 0 ) return failed(testName,ssh);

success = ssh.ChannelSendClose(channelNum);
if (success != true) return failed(testName,ssh);

//  Display the remote shell's command output:
printf("----\n%s\n----\n",cmdOutput);

return true;
}

bool SshTesting::qa_sendReqExec(void) { const char *testName = "qa_sendReqExec";

CkSsh ssh;

bool success;

// Connect and authenticate with the QA_SSH_SERVER
if (!sshConnectAndLogin(ssh,0)) return failed(testName,ssh);

ssh.put_IdleTimeoutMs(5000);

// Send one "exec" after another on the same connection, but on separate channels.
success = do_sendReqExec(testName,ssh,"ls -l");
if (success != true) return false;

success = do_sendReqExec(testName,ssh,"ps");
if (success != true) return false;

success = do_sendReqExec(testName,ssh,"hostname");
if (success != true) return false;

//  Disconnect
ssh.Disconnect();

return succeeded(testName,ssh);
}

Answer

I'm connecting to Cisco switches in my application, so I tested a local SSH server to see if I would get different behavior and did, so I guess these switches don't support this way of operation. I'll have to create a shell I suppose. Thanks for the help!


Answer

Were you using the latest version of Chilkat? If not, I can send you a new build if I know exactly what you need..