0

I followed the tutorial found on link. Everything's working fine, I can execute commands on remote hosts. However when I try to call ssh_channel_request_exec() function on session with Zhone MXK 198 (it's a network device) I get the following error:

Writing packet: error on socket (or connection closed): Operation now in progress.

I can however connect to that device manually (by using openssh). I think that this error has something to do with the fact, that CLI on the MXK is slightly different than the usual CLI known from Linux. For example backspace is interpreted as delete, so something's wrong with keymapping. I'm assuming that I need to change the format of data which is sent to the socket. Or maybe I'm wrong? Can you give me some ideas?

Tomasz Kasperczyk
  • 1,991
  • 3
  • 22
  • 43
  • It looks like the issue is caused by underlying socket unexpectedly being in non-blocked mode. I have never dealt with libssh, but the documentation mentions at least [ssh_set_blocking](http://api.libssh.org/master/group__libssh__session.html#ga2a29cff08855611be84d050e5bec73bc) and [ssh_channel_set_blocking](http://api.libssh.org/master/group__libssh__channel.html#ga1c00ed18679d9a8c5b971260b5df13a2). You could try to turn it off or on and look through your code for anything nonblocking-related. – dewaffled Sep 26 '14 at 13:22
  • I tried to force the blocking mode on session and channel, but it didn't help - still the same error. Here's the code: http://pastebin.com/AXq36P3e – Tomasz Kasperczyk Sep 26 '14 at 15:11
  • 1
    It seems you can use [ssh_get_fd](http://api.libssh.org/stable/group__libssh__session.html#gafe509fcea47714b5cd277d1e35e83276) to access underlying socket. After error occurred try to retrieve socket object and print fcntl(sock,F_GETFL) result to see if O_NONBLOCK flag is really set. See for instance (this question)[http://stackoverflow.com/questions/2149798/how-to-reset-a-socket-back-to-blocking-mode-after-i-set-it-to-nonblocking-mode] for the example of how to set socket mode back to blocking. – dewaffled Sep 26 '14 at 22:27
  • You can also try to work in non-blocking mode with ssh_set_blocking(session, 0) but the existing code will not work - functions will return SSH_AGAIN errors which require to retry the operation. – dewaffled Sep 26 '14 at 22:28

1 Answers1

0

I don't think you have gone so far for keycodes to be a problem. From the message you gave, I suspect you called an async function, but treated it as sync, erroring out instead of waiting.

Suppose we have the following code snippet:

n = recv(socket, buffer, sizeof buffer, 0);
if (n == -1) {
    err(1, "Error receiving data from socket");
}
<work with the n bytes received on buffer>

This is perfectly fine for a synchronous socket in most cases¹, but if it is an asynchronous operation (you passed MSG_DONTWAIT on flags, or set O_NONBLOCK with fcntl/setsockopt) you should expect that it returns -1 with EAGAIN as error number.

¹ On a real application you should also be handling EINTR (eg. the process received a signal).

In this case you are receiving EINPROGRESS, from which we can gather that the "failing" function that didn't complete is connect(). See what are possible reason for socket error einprogress?

The connect(2) man page is also very explicit about this error:

EINPROGRESS
    The socket is nonblocking and the connection cannot be completed immediately.  
    It is possible to  select(2)  or  poll(2) for  completion  by  selecting the 
    socket for writing.  After select(2) indicates writability, use getsockopt(2) 
    to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() 
    completed  successfully  (SO_ERROR  is  zero)  or unsuccessfully (SO_ERROR is 
    one of the usual error codes listed here, explaining the reason for the failure).

You can either change libssh to blocking with ssh_set_blocking() or use select/poll on the socket with ssh_get_poll_flags() flags.

Ángel
  • 890
  • 7
  • 12
  • When I set the session to nonblocking mode with ssh_set_blocking(session, 0) it fails to connect (ssh_connect() is not returning SSH_OK). And when I set it to blocking mode with ssh_set_blocking(session, 1) it returns the error which I described above when calling the ssh_channel_request_exec() function. I would gladly use the select and poll but I have completely no experience in playing with the sockets so it's a little too complicated for me. – Tomasz Kasperczyk Sep 26 '14 at 15:05