# After sending data over SSH, "receive" times out

**URL:** <https://erlangforums.com/t/after-sending-data-over-ssh-receive-times-out/2671>\
**Category:** Questions / Help\
**Tags:** erlang-otp, ssh, netconf\
**Created:** [June 7, 2023, 2:28pm UTC](https://erlangforums.com/t/after-sending-data-over-ssh-receive-times-out/2671 "2023-06-07T14:28:02Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![bhuvan](https://erlangforums.com/letter_avatar_proxy/v4/letter/b/f4b2a3/32.png) [@bhuvan](https://erlangforums.com/u/bhuvan)\
**Post date:** [June 7, 2023, 2:28pm UTC](https://erlangforums.com/t/after-sending-data-over-ssh-receive-times-out/2671/1 "2023-06-07T14:28:02Z")

</div>

I have written an Erlang application to send data over SSH. After sending ssh\_connection:send, I asynchronously wait for the response by calling `receive` function. But, the `receive` function is timing out. I have tried with a higher timeout value of 2 minutes as well. What is wrong with my code? Please help me in debugging the issue.

I have debugged the issue as follows;

1. I checked the packets exchanged using Wireshark. I see packets in Wireshark for all steps performed by my Erlang application (namely `ssh:connect, ssh_connection:session_channel & ssh_connection:send`).

2. I have enabled `dbg` for relevant modules. I see debug logs in the Erlang shell for the steps `ssh:connect, ssh_connection:session_channel`. But, not for `ssh_connection:sen`d

```erlang
application: start(ssh).
crypto:start().
ssh:start().

%% Creation of SSH connection
{ok, Client} = ssh:connect("10.0.2.15", 2022, [{user, "admin"}, {password, "admin"}]).

%% Creation of SSH Channel
{ok, Channel} = ssh_connection:session_channel(Client, 30000).

NetconfMessage = <<"<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n<capabilities>\n<capability>urn:ietf:params:netconf:base:1.0</capability>\n</capabilities>\n</hello>\n">>.

%% Sending data over the SSH Channel
case ssh_connection:send(Client, Channel, NetconfMessage) of
	ok ->
        io:format("Netconf message sent successfully ~n"),
		
		%% Asynchronously wait for the response
    	receive
        		{ssh, Channel, Data} ->
                io:format("Received data: ~s~n", [Data])
		after 60000 ->
        		io:format("Timeout receiving data.~n")
		end;
		
	{error, Reason} ->
		io:format("Error sending Netconf message: ~p~n", [Reason])
end.

%% Closing the SSH connection
ssh:close(Client).

```

---

<div class="post-metadata">

**Author:** ![jchrist](https://erlangforums.com/letter_avatar_proxy/v4/letter/j/858c86/32.png) [@jchrist](https://erlangforums.com/u/jchrist)\
**Post date:** [June 7, 2023, 6:13pm UTC](https://erlangforums.com/t/after-sending-data-over-ssh-receive-times-out/2671/2 "2023-06-07T18:13:26Z")

</div>

XML-over-SSH, I have not seen that one before 🙂

> [@bhuvan](#):
>
> ```erlang
> %% Asynchronously wait for the response
> receive
> {ssh, Channel, Data} ->
> io:format("Received data: ~s~n", [Data])
> after 60000 ->
> io:format("Timeout receiving data.~n")
> end;
> 
> ```

If my reading of the docs is right, you won’t receive `{ssh, Channel, Data}` messages but rather `{ssh_cm, Connection, {data, Channel, DataTypeCode, Data}}`. The [user’s guide](https://www.erlang.org/doc/apps/ssh/using_ssh.html#one-time-execution) has an example of this:

```erl
1> ssh:start().
ok
2> {ok, ConnectionRef} = ssh:connect("tarlop", 22, []).
{ok,<0.57.0>}
3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
{ok,0}
4> success = ssh_connection:exec(ConnectionRef, ChannelId, "pwd", infinity).
5> flush(). % Get all pending messages. NOTE: ordering may vary!
Shell got {ssh_cm,<0.57.0>,{data,0,0,<<"/home/otptest\n">>}}
Shell got {ssh_cm,<0.57.0>,{eof,0}}
Shell got {ssh_cm,<0.57.0>,{exit_status,0,0}}
Shell got {ssh_cm,<0.57.0>,{closed,0}}
ok
6> ssh:connection_info(ConnectionRef, channels).
{channels,[]}
7>

```

Let me know if this works 🙂

---

<div class="post-metadata">

**Author:** ![bhuvan](https://erlangforums.com/letter_avatar_proxy/v4/letter/b/f4b2a3/32.png) [@bhuvan](https://erlangforums.com/u/bhuvan)\
**Post date:** [June 8, 2023, 4:53pm UTC](https://erlangforums.com/t/after-sending-data-over-ssh-receive-times-out/2671/3 "2023-06-08T16:53:15Z")

</div>

> [@jchrist](#):
>
> If my reading of the docs is right, you won’t receive `{ssh, Channel, Data}` messages but rather `{ssh_cm, Connection, {data, Channel, DataTypeCode, Data}}`. The [user’s guide](https://www.erlang.org/doc/apps/ssh/using_ssh.html#one-time-execution) has an example of this:

Thanks @jchrist.

I modified the pattern matching in the `receive..end` clause as explained in the SSH User guide shared by you. Additionally, I have added a catch-all pattern `_ ->` to handle unmatched messages. But, I am still facing the same issue. Any other suggestion to debug further?

**Modified code** is pasted below.

```erlang
ssh:start().

%% Creation of SSH connection
{ok, ConnectionRef} = ssh:connect("10.0.2.15", 2022, [{user, "admin"}, {password, "admin"}]).

%% Creation of SSH Channel
{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, 30000).

NetconfMessage = <<"<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n<capabilities>\n<capability>urn:ietf:params:netconf:base:1.0</capability>\n</capabilities>\n</hello>\n">>.

%% Sending data over the SSH Channel
case ssh_connection:send(ConnectionRef, ChannelId, NetconfMessage) of
	ok ->
		io:format("Netconf message sent successfully ~n"),
		
		%% Asynchronously wait for the response
		receive
			{ssh_cm, ConnectionRef, {data, ChannelId, Type, Result}} when Type == 0 ->
		        {ok,Result};
			{ssh_cm, ConnectionRef, {data, ChannelId, Type, Result}} when Type == 1 ->
		        {error,Result};
			_ ->
				io:format("Unexpected message received~n")
		        
		after 30000 ->
			io:format("Timeout receiving data.~n")
		end;
		
	{error, Reason} ->
		io:format("Error sending Netconf message: ~p~n", [Reason])
end.

%% Closing the SSH connection
ssh:close(ConnectionRef).

```

---

<div class="post-metadata">

**Author:** ![bhuvan](https://erlangforums.com/letter_avatar_proxy/v4/letter/b/f4b2a3/32.png) [@bhuvan](https://erlangforums.com/u/bhuvan)\
**Post date:** [June 8, 2023, 4:55pm UTC](https://erlangforums.com/t/after-sending-data-over-ssh-receive-times-out/2671/4 "2023-06-08T16:55:48Z")

</div>

> [@jchrist](#):
>
> XML-over-SSH, I have not seen that one before 🙂

Yes, XML data over SSH is a popular mode for Network management. It has been popularized and standardized by one protocol called Netconf.

---

<div class="post-metadata">

**Author:** ![jimdigriz](https://erlangforums.com/user_avatar/erlangforums.com/jimdigriz/32/1885_2.png) [@jimdigriz](https://erlangforums.com/u/jimdigriz)\
**Post date:** [June 9, 2023, 2:06pm UTC](https://erlangforums.com/t/after-sending-data-over-ssh-receive-times-out/2671/5 "2023-06-09T14:06:02Z")

</div>

> [@jchrist](#):
>
> XML-over-SSH, I have not seen that one before 🙂

If you want to see crazy, look at [JSONx](https://www.jsonx.org/)…

It is trivial to find a SAX parser in most if not all languages for XML whilst for other serialisation formats such as JSON this seems to rarely an option.

SAX parsers are useful as they allow you to avoid reading the entire document into RAM and only react to the elements you are interested in.

It feels ‘right’ to wire incoming HTTP body messages directly into a SAX parser plus it really works well with Erlang’s pattern matching.

---

<div class="post-metadata">

**Author:** ![jchrist](https://erlangforums.com/letter_avatar_proxy/v4/letter/j/858c86/32.png) [@jchrist](https://erlangforums.com/u/jchrist)\
**Post date:** [June 9, 2023, 6:12pm UTC](https://erlangforums.com/t/after-sending-data-over-ssh-receive-times-out/2671/6 "2023-06-09T18:12:08Z")

</div>

After some testing I think I figured this out.

If you `ssh_connection:send` a message to a channel and you’re not running in any subsystem on the remote side, the connection won’t do anything about it. In my test, I had the default Erlang SSH server running:

```erl
27> {ok, ChannelId4} = ssh_connection:session_channel(Conn2, infinity).                                                                                                  
{ok,0}                                                                                                                                                                   
28> ssh_connection:send(Conn2, ChannelId4, "2 + 2").                                                                                                                     
ok                                                                                                                                                                       
29> ssh_connection:send(Conn2, ChannelId4, "\n").                                                                                                                        
ok                                                                                                                                                                       
30> ssh_connection:send(Conn2, ChannelId4, "\n").
ok
31> flush().
ok

```

- so like you reported (same thing happened with binaries). But when I start a shell first:

```erl
32> ssh_connection:shell(Conn2, ChannelId4).     
ok
33> flush().
Shell got {ssh_cm,<0.208.0>,
                  {data,0,0,<<"Eshell V13.2.2 (abort with ^G)\n">>}}
Shell got {ssh_cm,<0.208.0>,{data,0,0,<<"1> ">>}}
ok
34> flush().
ok
35> flush().
ok
37> ssh_connection:send(Conn2, ChannelId4, <<"2 + 2.\n">>).
ok
38> flush().
Shell got {ssh_cm,<0.208.0>,{data,0,0,<<"2 + 2.\n">>}}
Shell got {ssh_cm,<0.208.0>,{data,0,0,<<"4">>}}
Shell got {ssh_cm,<0.208.0>,{data,0,0,<<"\n">>}}
Shell got {ssh_cm,<0.208.0>,{data,0,0,<<"2> ">>}}
ok

```

I’m not 100% sure this will work with Netconf, but it’s worth a try. If that doesn’t work, I think you need to implement your own subsystem via [`ssh_client_channel`](https://www.erlang.org/doc/man/ssh_client_channel.html) ([here](https://www.erlang.org/doc/apps/ssh/using_ssh.html#creating-a-subsystem) are the docs for implementing a server subsystem).

I’m not entirely sure what’s going inside the SSH connection here… maybe a documentation update would help

---

<div class="post-metadata">

**Author:** ![bhuvan](https://erlangforums.com/letter_avatar_proxy/v4/letter/b/f4b2a3/32.png) [@bhuvan](https://erlangforums.com/u/bhuvan)\
**Post date:** [June 10, 2023, 2:30pm UTC](https://erlangforums.com/t/after-sending-data-over-ssh-receive-times-out/2671/7 "2023-06-10T14:30:44Z")

</div>

Thanks @jchrist. I tried to establish a shell before sending data over the channel. And, I got an error " `Error sending Netconf message: Closed`. When I debugged it, I found that the channel was closed after creating the shell.

```erlang
(node1@vm-alarm)1> ssh:start().
ok
(node1@vm-alarm)2> 
(node1@vm-alarm)2> %% Creation of SSH connection
(node1@vm-alarm)2> {ok, ConnectionRef} = ssh:connect("10.0.2.15", 2022, [{user, "admin"}, {password, "admin"}]).
{ok,<0.107.0>}
(node1@vm-alarm)3> 
(node1@vm-alarm)3> %% Creation of SSH Channel
(node1@vm-alarm)3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, 30000).
{ok,0}
(node1@vm-alarm)4> 
(node1@vm-alarm)4> ssh:connection_info(ConnectionRef, [channels]).
[{channels,[[{type,"session"},
             {sys,"none"},
             {user,<0.90.0>},
             {flow_control,undefined},
             {local_id,0},
             {recv_window_size,425984},
             {recv_window_pending,0},
             {recv_packet_size,65536},
             {recv_close,false},
             {remote_id,0},
             {send_window_size,655360},
             {send_packet_size,65536},
             {sent_close,false},
             {send_buf,{[],[]}}]]}]
(node1@vm-alarm)5> ssh_connection:shell(ConnectionRef, ChannelId).     
ok
(node1@vm-alarm)6>     
(node1@vm-alarm)6> ssh:connection_info(ConnectionRef, [channels]).     
[{channels,[]}]
(node1@vm-alarm)7>

```

---

<div class="post-metadata">

**Author:** ![bhuvan](https://erlangforums.com/letter_avatar_proxy/v4/letter/b/f4b2a3/32.png) [@bhuvan](https://erlangforums.com/u/bhuvan)\
**Post date:** [June 10, 2023, 2:31pm UTC](https://erlangforums.com/t/after-sending-data-over-ssh-receive-times-out/2671/8 "2023-06-10T14:31:14Z")

</div>

> [@jchrist](#):
>
> If that doesn’t work, I think you need to implement your own subsystem via [`ssh_client_channel`](https://www.erlang.org/doc/man/ssh_client_channel.html)

Let me try this.
