title: Java telnet login: stuck after sending user name
body: <p>I'm trying to perform a programmatic telnet session in Java. I'm using <code>commons-net</code> <code>TelnetClient</code>, but I've also experimented with a direct socket. In either case I'm having the same problem.</p>
  
  <p>I read up to "login :", then send the user name followed by CRLF. Then nothing, no other data is read, or written by server.</p>
  
  <p>The telnet server is on an embedded device (a Star printer), so I'm wondering if there are some peculiar options required that I'm not setting, or that aren't supported by the <code>commons-net</code> <code>TelnetClient</code> class.</p>
  
  <p>I can use Linux <code>telnet</code> without problems, and I can run my code against the telnet server in OSX and it works fine.</p>
  
  <pre><code>  TelnetClient client = new TelnetClient();
    client.registerNotifHandler(new TelnetNotificationHandler() {
      @Override
      public void receivedNegotiation(int negotiation_code, int option_code) {
        ALog.i(this, "negotiation code: %d, option code: %d", negotiation_code, option_code);
      }
    });
    try {
      client.addOptionHandler(new TerminalTypeOptionHandler("VT100", false, false, true, false));
      client.addOptionHandler(new SuppressGAOptionHandler(true, false, true, false));
      client.addOptionHandler(new EchoOptionHandler(true, true, true, true));
    } catch (InvalidTelnetOptionException e) {
      e.printStackTrace();
    }
  
    try {
      FileOutputStream fos = new FileOutputStream("/sdcard/spy.out");
      client.registerSpyStream(fos);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
  
    InputStream in = null;
    PrintWriter out = null;
  
    String ip = getIpAddress(p);
    ALog.i(this, "connecting to: %s", ip);
    try {
      client.connect(ip);
      in = client.getInputStream();
      out = new PrintWriter(client.getOutputStream(), true);
  
      if (!expect(in, "login: ", 5000)) {
        return;
      }
      if (!send(out, "root")) {
        return;
      }
      if (!expect(in, "password: ", 5000)) {
        return;
      }
      if (!send(out, "password")) {
        return;
      }
  </code></pre>
  
  <p>Here's the <code>expect()</code> and <code>send()</code> methods,</p>
  
  <pre><code>  protected boolean expect(InputStream in, String s, long timeout) {
      ALog.i(this, "expecting: %s", s);
  
      final AtomicBoolean lock = new AtomicBoolean(false);
      final ExpectThread t = new ExpectThread(in, s, lock, timeout);
      t.start();
      synchronized (lock) {
        try {
          lock.wait(timeout);
        } catch (InterruptedException e) {
        }
      }
      t.interrupt();
      return lock.get();
    }
  
    protected boolean send(PrintWriter out, String s) {
      out.println(s);
      out.flush();
      ALog.i(this, "sent: %s", s);
      return true;
    }
  </code></pre>
  
  <p>And here's <code>ExpectThread</code>,</p>
  
  <pre><code>  private class ExpectThread extends Thread {
      private final InputStream in;
      private final String expected;
      private final AtomicBoolean lock;
      private final long start;
      private final long timeout;
  
      ExpectThread(InputStream in, String expected, AtomicBoolean lock, long timeout) {
        this.in = in;
        this.expected = expected.toLowerCase();
        this.lock = lock;
        this.timeout = timeout;
        this.start = System.currentTimeMillis();
      }
  
      @Override
      public void run() {
        final StringBuilder b = new StringBuilder();
        final byte[] buffer = new byte[1024];
        int c;
  
        try {
          while (!isInterrupted() &amp;&amp; System.currentTimeMillis() &lt; start + timeout) {
            ALog.i(this, "starting read ...");
            while ((c = in.read(buffer)) != -1) {
              String s = new String(buffer, 0, c);
              b.append(s.toLowerCase());
              ALog.i(this, "read string: %s, buffer: %s", s, b.toString());
              if (b.toString().contains(expected)) {
                ALog.i(this, "found expected");
                lock.set(true);
                return;
              }
            }
            ALog.i(this, "waiting for read ...");
            SystemClock.sleep(1000);
          }
        } catch (IOException e) {
          e.printStackTrace();
        } finally {
          synchronized (lock) {
            lock.notifyAll();
          }
        }
      }
    }
  </code></pre>
  
  <p>here's a wireshark pcap of the FAILED programmatic session,
  <a href="https://drive.google.com/file/d/0B5iST80rpTN9c1RsRTNFaE5GZHM/view?usp=sharing" rel="nofollow">https://drive.google.com/file/d/0B5iST80rpTN9c1RsRTNFaE5GZHM/view?usp=sharing</a></p>
  
  <p>here's a pcap of a successful terminal (linux telnet client) session,
  <a href="https://drive.google.com/file/d/0B5iST80rpTN9bDZFOHhkSHlPSE0/view?usp=sharing" rel="nofollow">https://drive.google.com/file/d/0B5iST80rpTN9bDZFOHhkSHlPSE0/view?usp=sharing</a></p>
  
  <p>I see the Linux client sends a "WILL AUTHENTICATE", where my code does not. I'd try it if I could figure out how to get <code>TelnetClient</code> to send such commands.</p>