Miron Aseev created SSHD-744:
--------------------------------

             Summary: An SSH client receives an echo as a response from the 
server
                 Key: SSHD-744
                 URL: https://issues.apache.org/jira/browse/SSHD-744
             Project: MINA SSHD
          Issue Type: Question
    Affects Versions: 1.4.0
            Reporter: Miron Aseev
            Priority: Minor


I'm trying to integrate my Java application with a device which provides a 
custom protocol over SSH.

The whole point of this protocol is about exchanging XML documents back and 
forth. It can be described with the following steps:

# a client connects to the server
# the client sends an XML document which contains the request data
# the client waits for the XML document which contains a response data from a 
server
# the server receives the XML document that was sent by the client and sends 
the response XML document back to the client
# the client receives the XML response from the server and closes the connection

The recommended way to send requests to this device is to use `cat` and `ssh` 
tools. Here's a simple example:

{code}
cat example.xml | ssh <user_id>@<device_ip>
{code}

where `example.xml` is a file that contains an XML document with the request 
data.

Calling directly 'cat' and 'ssh' via Runtime.exec would be very problematic 
because this approach has a lot of drawbacks. So, I decided to implement this 
protocol using MINA SSHD library.

The problem I've run into is I receive my own request as a response from the 
server. So there's some kind of echoing stuff going on, I think.

For example, when I send this XML document as a request to the server:

{code}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xg-request>
    <action-request>
        <action-name>test</action-name>
    </action-request>
</xg-request>

{code}

I receive the following data as a response:

{code}
Last login: Wed May 3 07:33:43 2017 from ip

Header
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xg-request>
    <action-request>
        <action-name>test</action-name>
    </action-request>
</xg-request>

{code}

The funny this is when I send the same request via cat and ssh (the example I 
mentioned above), I receive the correct response from the device.

Here's an excerpt from my application:

{code}
public class Test {

  private static final long AWAIT_TIMEOUT = TimeUnit.SECONDS.toMillis(5);
  private static final String XML_PAYLOAD_HEADER = "<?xml";

  public void init() throws IOException, JAXBException {
    try (SshClient client = initSshClient();
         ClientSession session =
           initClientSession(client, "test", "localhost", 22, "pass")) {
      sendRequest(session);
    }
  }

  private static SshClient initSshClient() {
    SshClient client = SshClient.setUpDefaultClient();
    client.start();

    return client;
  }

  private ClientSession initClientSession(SshClient client, String user, 
                                          String host, int port, 
                                          String password) throws IOException {
    ClientSession session =
      client.connect(user, host, port).verify(AWAIT_TIMEOUT).getSession();

    session.addPasswordIdentity(password);
    session.auth().verify(AWAIT_TIMEOUT);

    return session;
  }

  private void sendRequest(ClientSession session) throws IOException {
    try (PipedOutputStream out = new PipedOutputStream();
         PipedInputStream channelIn = new PipedInputStream(out);
         PipedOutputStream channelOut = new PipedOutputStream();
         PipedInputStream in = new PipedInputStream(channelOut);
         BufferedReader reader = new BufferedReader(new InputStreamReader(in));
         BufferedWriter writer = new BufferedWriter(new 
OutputStreamWriter(out));
         ClientChannel channel = initClientChannel(session, channelIn, 
channelOut)) {
      String xmlRequest = ""; // Here goes a real XML document;

      writer.write(xmlRequest);
      writer.newLine();
      writer.flush();

      String response = readFully(reader);
    }
  }

  private static ClientChannel initClientChannel(ClientSession session, 
InputStream input,
                                                 OutputStream output) throws 
IOException {
    ClientChannel channel = session.createChannel(Channel.CHANNEL_SHELL);

    channel.setIn(input);
    channel.setOut(output);
    channel.setErr(new ByteArrayOutputStream());
    channel.open().verify(AWAIT_TIMEOUT);

    return channel;
  }

  private static String readFully(BufferedReader reader) throws IOException {
    StringBuilder builder = new StringBuilder();
    String line;
    boolean foundXmlPayload = false;

    while ((line = reader.readLine()) != null) {
      if (foundXmlPayload && line.isEmpty()) {
        break;
      }

      builder.append(line);

      if (!foundXmlPayload && builder.indexOf(XML_PAYLOAD_HEADER) != -1) {
        foundXmlPayload = true;
      }
    }

    return builder.toString();
  }
}
{code}

Any suggestions would be greatly appreciated.



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

Reply via email to