View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.net.telnet;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.io.OutputStream;
22  import java.io.PipedInputStream;
23  import java.io.PipedOutputStream;
24  import java.time.Duration;
25  
26  import junit.framework.TestCase;
27  
28  /**
29   * JUnit test class for TelnetClient.s Implements protocol compliance tests
30   */
31  public class TelnetClientTest extends TestCase implements TelnetNotificationHandler {
32      /**
33       * Handy holder to hold both sides of the connection used in testing for clarity.
34       */
35      private class TestConnection {
36          private final TelnetTestSimpleServer server;
37          private final TelnetClient client;
38          private final int port;
39  
40          TestConnection(final TelnetTestSimpleServer server, final TelnetClient client, final int port) {
41              this.server = server;
42              this.client = client;
43              this.port = port;
44          }
45  
46          protected void close() {
47              TelnetClientTest.this.closeConnection(this.server, this.client, this.port);
48          }
49      }
50  
51      // four connections with different properties
52      // to use in tests.
53      private TestConnection STANDARD;
54      private TestConnection OPTIONS;
55      private TestConnection ANSI;
56      private TestConnection NOREAD;
57      private TestConnection SMALL_BUFFER;
58  
59      private final int NUM_CONNECTIONS = 5;
60  
61      protected int numdo;
62      protected int numdont;
63      protected int numwill;
64      protected int numwont;
65  
66      protected int[] lastSubnegotiation;
67      protected int lastSubnegotiationLength;
68  
69      void closeConnection(final TelnetTestSimpleServer server, final TelnetClient client, final int port) {
70          if (server != null) {
71              server.disconnect();
72              server.stop();
73          }
74          try {
75              if (client != null) {
76                  client.disconnect();
77              }
78          } catch (final IOException e) {
79              System.err.println("failed to close client-server connection on port " + port);
80              System.err.println("ERROR in closeConnection(), " + e.getMessage());
81          }
82  
83      }
84  
85      /*
86       * Helper method. compares two arrays of int
87       */
88      protected boolean equalBytes(final byte a1[], final byte a2[]) {
89          if (a1.length != a2.length) {
90              return false;
91          }
92          boolean result = true;
93          for (int ii = 0; ii < a1.length; ii++) {
94  
95              if (a1[ii] != a2[ii]) {
96                  result = false;
97              }
98          }
99          return result;
100     }
101 
102     /*
103      * Callback method called when TelnetClient receives an option negotiation command. <p>
104      *
105      * @param negotiation_code - type of negotiation command received (RECEIVED_DO, RECEIVED_DONT, RECEIVED_WILL, RECEIVED_WONT) <p>
106      *
107      * @param option_code - code of the option negotiated <p>
108      */
109     @Override
110     public void receivedNegotiation(final int negotiation_code, final int option_code) {
111         switch (negotiation_code) {
112         case TelnetNotificationHandler.RECEIVED_DO:
113             numdo++;
114             break;
115         case TelnetNotificationHandler.RECEIVED_DONT:
116             numdont++;
117             break;
118         case TelnetNotificationHandler.RECEIVED_WILL:
119             numwill++;
120             break;
121         case TelnetNotificationHandler.RECEIVED_WONT:
122             numwont++;
123             break;
124         default:
125             break;
126         }
127     }
128 
129     /*
130      * open connections needed for the tests for the test.
131      */
132     @Override
133     protected void setUp() throws Exception {
134         final SimpleOptionHandler subnegotiationSizeHandler = new SimpleOptionHandler(99, false, false, true, false) {
135             @Override
136             public int[] answerSubnegotiation(final int[] suboptionData, final int suboptionLength) {
137                 lastSubnegotiation = suboptionData;
138                 lastSubnegotiationLength = suboptionLength;
139                 return null;
140             }
141         };
142 
143         int socket = 0;
144         super.setUp();
145         for (int port = 3333; socket < NUM_CONNECTIONS && port < 4000; port++) {
146             TelnetTestSimpleServer server = null;
147             TelnetClient client = null;
148             try {
149                 server = new TelnetTestSimpleServer(port);
150                 switch (socket) {
151                 case 0:
152                     client = new TelnetClient();
153                     // redundant but makes code clearer.
154                     client.setReaderThread(true);
155                     client.addOptionHandler(subnegotiationSizeHandler);
156                     client.connect("127.0.0.1", port);
157                     STANDARD = new TestConnection(server, client, port);
158                     break;
159                 case 1:
160                     client = new TelnetClient();
161                     final TerminalTypeOptionHandler ttopt = new TerminalTypeOptionHandler("VT100", false, false, true, false);
162                     final EchoOptionHandler echoopt = new EchoOptionHandler(true, false, true, false);
163                     final SuppressGAOptionHandler gaopt = new SuppressGAOptionHandler(true, true, true, true);
164 
165                     client.addOptionHandler(ttopt);
166                     client.addOptionHandler(echoopt);
167                     client.addOptionHandler(gaopt);
168                     client.connect("127.0.0.1", port);
169                     OPTIONS = new TestConnection(server, client, port);
170                     break;
171                 case 2:
172                     client = new TelnetClient("ANSI");
173                     client.connect("127.0.0.1", port);
174                     ANSI = new TestConnection(server, client, port);
175                     break;
176                 case 3:
177                     client = new TelnetClient();
178                     client.setReaderThread(false);
179                     client.connect("127.0.0.1", port);
180                     NOREAD = new TestConnection(server, client, port);
181                     break;
182                 case 4:
183                     client = new TelnetClient(8);
184                     client.addOptionHandler(subnegotiationSizeHandler);
185                     client.connect("127.0.0.1", port);
186                     SMALL_BUFFER = new TestConnection(server, client, port);
187                     break;
188                 }
189                 // only increment socket number on success
190                 socket++;
191             } catch (final IOException e) {
192                 closeConnection(server, client, port);
193             }
194         }
195         if (socket < NUM_CONNECTIONS) {
196             System.err.println("Only created " + socket + " clients; wanted " + NUM_CONNECTIONS);
197         }
198         Thread.sleep(1000);
199     }
200 
201     /*
202      * @throws Exception
203      */
204     @Override
205     protected void tearDown() throws Exception {
206         NOREAD.close();
207         ANSI.close();
208         OPTIONS.close();
209         STANDARD.close();
210         SMALL_BUFFER.close();
211         try {
212             Thread.sleep(1000);
213         } catch (final InterruptedException ie) {
214             // do nothing
215         }
216         super.tearDown();
217     }
218 
219     /*
220      * test of AYT functionality
221      */
222     public void testAYT() throws Exception {
223         boolean ayt_true_ok = false;
224         boolean ayt_false_ok = false;
225 
226         final byte[] AYT = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.AYT };
227         final byte[] response = { (byte) '[', (byte) 'Y', (byte) 'e', (byte) 's', (byte) ']' };
228         final String[] inputs = new String[1];
229         final String[] outputs = new String[1];
230         inputs[0] = new String(AYT);
231         outputs[0] = new String(response);
232 
233         final OutputStream os = ANSI.server.getOutputStream();
234         final InputStream is = ANSI.server.getInputStream();
235         final TelnetTestResponder tr = new TelnetTestResponder(is, os, inputs, outputs, 30000);
236         assertNotNull(tr);
237         final boolean res1 = ANSI.client.sendAYT(Duration.ofSeconds(2));
238 
239         if (res1) {
240             ayt_true_ok = true;
241         }
242 
243         Thread.sleep(1000);
244         is.skip(is.available());
245 
246         final boolean res2 = ANSI.client.sendAYT(Duration.ofSeconds(2));
247 
248         if (!res2) {
249             ayt_false_ok = true;
250         }
251 
252         assertTrue(ayt_true_ok);
253         assertTrue(ayt_false_ok);
254     }
255 
256     /*
257      * protocol compliance test in case of option handler removal
258      */
259     public void testDeleteOptionHandler() throws Exception {
260         boolean remove_ok = false;
261         boolean remove_invalid_ok1 = false;
262         boolean remove_invalid_ok2 = false;
263 
264         final byte[] buffread = new byte[6];
265         final byte[] send = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.ECHO, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO,
266                 (byte) TelnetOption.SUPPRESS_GO_AHEAD, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) TelnetOption.SUPPRESS_GO_AHEAD };
267 
268         final byte[] expected = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD, (byte) TelnetCommand.IAC,
269                 (byte) TelnetCommand.DONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD };
270 
271         final InputStream is = OPTIONS.server.getInputStream();
272         final OutputStream os = OPTIONS.server.getOutputStream();
273         Thread.sleep(1000);
274         is.skip(is.available());
275         os.write(send);
276         os.flush();
277         Thread.sleep(1000);
278         if (is.available() == 0) {
279             OPTIONS.client.deleteOptionHandler(TelnetOption.SUPPRESS_GO_AHEAD);
280             Thread.sleep(1000);
281             if (is.available() == 6) {
282                 is.read(buffread);
283                 if (equalBytes(buffread, expected)) {
284                     remove_ok = true;
285                 }
286             }
287         }
288 
289         try {
290             OPTIONS.client.deleteOptionHandler(TelnetOption.SUPPRESS_GO_AHEAD);
291         } catch (final Exception e) {
292             remove_invalid_ok1 = true;
293         }
294 
295         try {
296             OPTIONS.client.deleteOptionHandler(550);
297         } catch (final Exception e) {
298             remove_invalid_ok2 = true;
299         }
300 
301         assertTrue(remove_ok);
302         assertTrue(remove_invalid_ok1);
303         assertTrue(remove_invalid_ok2);
304         assertTrue(OPTIONS.client.getLocalOptionState(TelnetOption.ECHO));
305         assertFalse(OPTIONS.client.getLocalOptionState(TelnetOption.SUPPRESS_GO_AHEAD));
306         assertFalse(OPTIONS.client.getLocalOptionState(TelnetOption.SUPPRESS_GO_AHEAD));
307     }
308 
309     /*
310      * tests the initial condition of the sessions
311      */
312     public void testInitial() throws Exception {
313         boolean connect1_ok = false;
314         boolean connect2_ok = false;
315         boolean connect3_ok = false;
316         boolean init2_ok = false;
317         boolean add_invalid_ok1 = false;
318         boolean add_invalid_ok2 = false;
319         final byte[] buffread2 = new byte[9];
320         final byte[] expected2 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) TelnetOption.ECHO, (byte) TelnetCommand.IAC,
321                 (byte) TelnetCommand.WILL, (byte) TelnetOption.SUPPRESS_GO_AHEAD, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO,
322                 (byte) TelnetOption.SUPPRESS_GO_AHEAD, };
323 
324         final SimpleOptionHandler hand = new SimpleOptionHandler(550);
325         try {
326             STANDARD.client.addOptionHandler(hand);
327         } catch (final Exception e) {
328             add_invalid_ok1 = true;
329         }
330 
331         try {
332             OPTIONS.client.addOptionHandler(hand);
333         } catch (final Exception e) {
334             add_invalid_ok2 = true;
335         }
336 
337         final InputStream is1 = STANDARD.server.getInputStream();
338         Thread.sleep(1000);
339         if (is1.available() == 0) {
340             connect1_ok = true;
341         }
342 
343         Thread.sleep(1000);
344         final InputStream is2 = OPTIONS.server.getInputStream();
345         if (is2.available() == 9) {
346             is2.read(buffread2);
347             connect2_ok = true;
348 
349             if (equalBytes(buffread2, expected2)) {
350                 init2_ok = true;
351             }
352         }
353 
354         final InputStream is3 = ANSI.server.getInputStream();
355         Thread.sleep(1000);
356         if (is3.available() == 0) {
357             connect3_ok = true;
358         }
359 
360         assertTrue(connect1_ok);
361         assertTrue(connect2_ok);
362         assertTrue(connect3_ok);
363         assertFalse(STANDARD.client.getLocalOptionState(TelnetOption.ECHO));
364         assertFalse(STANDARD.client.getRemoteOptionState(TelnetOption.ECHO));
365         assertFalse(OPTIONS.client.getLocalOptionState(TelnetOption.ECHO));
366         assertFalse(OPTIONS.client.getRemoteOptionState(TelnetOption.ECHO));
367         assertFalse(ANSI.client.getLocalOptionState(TelnetOption.TERMINAL_TYPE));
368         assertFalse(ANSI.client.getRemoteOptionState(TelnetOption.TERMINAL_TYPE));
369         assertTrue(init2_ok);
370         assertTrue(add_invalid_ok1);
371         assertTrue(add_invalid_ok2);
372     }
373 
374     /*
375      * test of max subnegotiation length
376      */
377     public void testMaxSubnegotiationLength() throws Exception {
378         final byte[] send = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.SB, (byte) 99, (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6,
379                 (byte) 7, (byte) 8, (byte) 9, (byte) 10, (byte) 11, (byte) 12, (byte) 13, (byte) 14, (byte) 15, (byte) TelnetCommand.IAC,
380                 (byte) TelnetCommand.SE, };
381 
382         final OutputStream os1 = SMALL_BUFFER.server.getOutputStream();
383         os1.write(send);
384         os1.flush();
385         Thread.sleep(500);
386 
387         // we sent 16 bytes, but the buffer size should just be 8
388         assertEquals(8, lastSubnegotiationLength);
389         assertEquals(8, lastSubnegotiation.length);
390         assertEquals(99, lastSubnegotiation[0]);
391         assertEquals(1, lastSubnegotiation[1]);
392         assertEquals(2, lastSubnegotiation[2]);
393         assertEquals(3, lastSubnegotiation[3]);
394         assertEquals(4, lastSubnegotiation[4]);
395         assertEquals(5, lastSubnegotiation[5]);
396         assertEquals(6, lastSubnegotiation[6]);
397         assertEquals(7, lastSubnegotiation[7]);
398 
399         final OutputStream os2 = STANDARD.server.getOutputStream();
400         os2.write(send);
401         os2.flush();
402         Thread.sleep(500);
403 
404         // the standard subnegotiation buffer size is 512
405         assertEquals(16, lastSubnegotiationLength);
406         assertEquals(512, lastSubnegotiation.length);
407         assertEquals(99, lastSubnegotiation[0]);
408         assertEquals(1, lastSubnegotiation[1]);
409         assertEquals(2, lastSubnegotiation[2]);
410         assertEquals(3, lastSubnegotiation[3]);
411         assertEquals(4, lastSubnegotiation[4]);
412         assertEquals(5, lastSubnegotiation[5]);
413         assertEquals(6, lastSubnegotiation[6]);
414         assertEquals(7, lastSubnegotiation[7]);
415     }
416 
417     /*
418      * test of option negotiation notification
419      */
420     public void testNotification() throws Exception {
421         final byte[] buffread1 = new byte[6];
422         final byte[] send1 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) 15, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) 15, };
423 
424         final byte[] buffread2 = new byte[9];
425         final byte[] send2 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.TERMINAL_TYPE, (byte) TelnetCommand.IAC,
426                 (byte) TelnetCommand.DONT, (byte) TelnetOption.ECHO, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.SUPPRESS_GO_AHEAD,
427                 (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD };
428 
429         final byte[] buffread2b = new byte[11];
430 
431         numdo = 0;
432         numdont = 0;
433         numwill = 0;
434         numwont = 0;
435         OPTIONS.client.registerNotifHandler(this);
436 
437         final InputStream is1 = STANDARD.server.getInputStream();
438         final OutputStream os1 = STANDARD.server.getOutputStream();
439         is1.skip(is1.available());
440         os1.write(send1);
441         os1.flush();
442         Thread.sleep(500);
443         if (is1.available() > 0) {
444             is1.read(buffread1);
445         }
446 
447         final InputStream is2 = OPTIONS.server.getInputStream();
448         final OutputStream os2 = OPTIONS.server.getOutputStream();
449         Thread.sleep(500);
450         is2.skip(is2.available());
451         os2.write(send2);
452         os2.flush();
453         Thread.sleep(500);
454         if (is2.available() > 0) {
455             is2.read(buffread2);
456             Thread.sleep(1000);
457             if (is2.available() > 0) {
458                 is2.read(buffread2b);
459             }
460         }
461 
462         assertEquals(2, numdo);
463         assertEquals(1, numdont);
464         assertEquals(1, numwont);
465         assertEquals(0, numwill);
466     }
467 
468     /*
469      * protocol compliance test for option negotiation
470      */
471     public void testOptionNegotiation() throws Exception {
472         boolean negotiation1_ok = false;
473         final byte[] buffread1 = new byte[6];
474         final byte[] send1 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) 15, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) 15, };
475         final byte[] expected1 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) 15, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT,
476                 (byte) 15, };
477 
478         boolean negotiation2_ok = false;
479         final byte[] buffread2 = new byte[9];
480         final byte[] send2 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.TERMINAL_TYPE, (byte) TelnetCommand.IAC,
481                 (byte) TelnetCommand.DONT, (byte) TelnetOption.ECHO, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.SUPPRESS_GO_AHEAD,
482                 (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD };
483         final byte[] expected2 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) TelnetOption.TERMINAL_TYPE, (byte) TelnetCommand.IAC,
484                 (byte) TelnetCommand.WONT, (byte) TelnetOption.ECHO, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT,
485                 (byte) TelnetOption.SUPPRESS_GO_AHEAD };
486 
487         final byte[] buffread2b = new byte[11];
488         final byte[] send2b = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.SB, (byte) TelnetOption.TERMINAL_TYPE, (byte) 1, (byte) TelnetCommand.IAC,
489                 (byte) TelnetCommand.SE, };
490         final byte[] expected2b = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.SB, (byte) TelnetOption.TERMINAL_TYPE, (byte) 0, (byte) 'V', (byte) 'T',
491                 (byte) '1', (byte) '0', (byte) '0', (byte) TelnetCommand.IAC, (byte) TelnetCommand.SE, };
492 
493         boolean negotiation3_ok = false;
494         final byte[] buffread3 = new byte[6];
495         final byte[] send3 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.TERMINAL_TYPE, (byte) TelnetCommand.IAC,
496                 (byte) TelnetCommand.DO, (byte) TelnetOption.SUPPRESS_GO_AHEAD };
497         final byte[] expected3 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) TelnetOption.TERMINAL_TYPE, (byte) TelnetCommand.IAC,
498                 (byte) TelnetCommand.WONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD };
499         final byte[] buffread3b = new byte[10];
500         final byte[] send3b = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.SB, (byte) TelnetOption.TERMINAL_TYPE, (byte) 1, (byte) TelnetCommand.IAC,
501                 (byte) TelnetCommand.SE, };
502         final byte[] expected3b = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.SB, (byte) TelnetOption.TERMINAL_TYPE, (byte) 0, (byte) 'A', (byte) 'N',
503                 (byte) 'S', (byte) 'I', (byte) TelnetCommand.IAC, (byte) TelnetCommand.SE, };
504 
505         final InputStream is1 = STANDARD.server.getInputStream();
506         final OutputStream os1 = STANDARD.server.getOutputStream();
507         is1.skip(is1.available());
508         os1.write(send1);
509         os1.flush();
510         Thread.sleep(1000);
511         if (is1.available() == 6) {
512             is1.read(buffread1);
513 
514             if (equalBytes(buffread1, expected1)) {
515                 negotiation1_ok = true;
516             }
517         }
518 
519         final InputStream is2 = OPTIONS.server.getInputStream();
520         final OutputStream os2 = OPTIONS.server.getOutputStream();
521         Thread.sleep(1000);
522         is2.skip(is2.available());
523         os2.write(send2);
524         os2.flush();
525         Thread.sleep(1000);
526         if (is2.available() == 9) {
527             is2.read(buffread2);
528 
529             if (equalBytes(buffread2, expected2)) {
530                 negotiation2_ok = true;
531             }
532 
533             if (negotiation2_ok) {
534                 negotiation2_ok = false;
535                 os2.write(send2b);
536                 os2.flush();
537                 Thread.sleep(1000);
538                 if (is2.available() == 11) {
539                     is2.read(buffread2b);
540 
541                     if (equalBytes(buffread2b, expected2b)) {
542                         negotiation2_ok = true;
543                     }
544                 }
545             }
546         }
547 
548         final InputStream is3 = ANSI.server.getInputStream();
549         final OutputStream os3 = ANSI.server.getOutputStream();
550         Thread.sleep(1000);
551         is3.skip(is3.available());
552         os3.write(send3);
553         os3.flush();
554         Thread.sleep(1000);
555         if (is3.available() == 6) {
556             is3.read(buffread3);
557 
558             if (equalBytes(buffread3, expected3)) {
559                 negotiation3_ok = true;
560             }
561 
562             if (negotiation3_ok) {
563                 negotiation3_ok = false;
564                 os3.write(send3b);
565                 os3.flush();
566                 Thread.sleep(1000);
567                 if (is3.available() == 10) {
568                     is3.read(buffread3b);
569                     if (equalBytes(buffread3b, expected3b)) {
570                         negotiation3_ok = true;
571                     }
572                 }
573             }
574         }
575 
576         assertTrue(negotiation1_ok);
577         assertTrue(negotiation2_ok);
578         assertTrue(negotiation3_ok);
579         assertFalse(STANDARD.client.getLocalOptionState(15));
580         assertFalse(STANDARD.client.getRemoteOptionState(15));
581         assertFalse(STANDARD.client.getLocalOptionState(TelnetOption.TERMINAL_TYPE));
582         assertFalse(OPTIONS.client.getLocalOptionState(TelnetOption.ECHO));
583         assertFalse(OPTIONS.client.getRemoteOptionState(TelnetOption.ECHO));
584         assertTrue(OPTIONS.client.getLocalOptionState(TelnetOption.SUPPRESS_GO_AHEAD));
585         assertFalse(OPTIONS.client.getRemoteOptionState(TelnetOption.SUPPRESS_GO_AHEAD));
586         assertTrue(OPTIONS.client.getLocalOptionState(TelnetOption.TERMINAL_TYPE));
587         assertTrue(ANSI.client.getLocalOptionState(TelnetOption.TERMINAL_TYPE));
588         assertFalse(OPTIONS.client.getLocalOptionState(TelnetOption.ECHO));
589     }
590 
591     /*
592      * protocol compliance test for option renegotiation
593      */
594     public void testOptionRenegotiation() throws Exception {
595         boolean negotiation1_ok = false;
596 
597         final byte[] buffread = new byte[6];
598         final byte[] send = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) TelnetOption.ECHO, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT,
599                 (byte) TelnetOption.SUPPRESS_GO_AHEAD, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD };
600         final byte[] expected = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD, (byte) TelnetCommand.IAC,
601                 (byte) TelnetCommand.DONT, (byte) TelnetOption.SUPPRESS_GO_AHEAD };
602 
603         final byte[] buffread2 = new byte[3];
604         final byte[] send2 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT, (byte) TelnetOption.ECHO, };
605         final byte[] expected2 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) TelnetOption.ECHO, };
606 
607         final InputStream is = OPTIONS.server.getInputStream();
608         final OutputStream os = OPTIONS.server.getOutputStream();
609         Thread.sleep(1000);
610         is.skip(is.available());
611         os.write(send);
612         os.flush();
613         Thread.sleep(1000);
614         if (is.available() == 6) {
615             is.read(buffread);
616 
617             if (equalBytes(buffread, expected)) {
618                 negotiation1_ok = true;
619             }
620 
621             if (negotiation1_ok) {
622                 negotiation1_ok = false;
623                 os.write(send2);
624                 os.flush();
625                 Thread.sleep(1000);
626                 if (is.available() == 3) {
627                     is.read(buffread2);
628                     if (equalBytes(buffread2, expected2)) {
629                         negotiation1_ok = true;
630                     }
631                 }
632             }
633         }
634 
635         assertTrue(negotiation1_ok);
636         assertFalse(OPTIONS.client.getLocalOptionState(TelnetOption.ECHO));
637     }
638 
639     /*
640      * test of setReaderThread
641      */
642     public void testSetReaderThread() throws Exception {
643         boolean negotiation1_ok = false;
644         boolean negotiation2_ok = false;
645         boolean read_ok = false;
646         final byte[] buffread1 = new byte[6];
647         final byte[] send1 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.DO, (byte) 15, (byte) TelnetCommand.IAC, (byte) TelnetCommand.WILL, (byte) 15, };
648         final byte[] expected1 = { (byte) TelnetCommand.IAC, (byte) TelnetCommand.WONT, (byte) 15, (byte) TelnetCommand.IAC, (byte) TelnetCommand.DONT,
649                 (byte) 15, };
650 
651         final InputStream is1 = NOREAD.server.getInputStream();
652         final OutputStream os1 = NOREAD.server.getOutputStream();
653         is1.skip(is1.available());
654         os1.write(send1);
655         os1.flush();
656         os1.write("A".getBytes());
657         os1.flush();
658         Thread.sleep(1000);
659         final InputStream instr = NOREAD.client.getInputStream();
660         final byte[] buff = new byte[4];
661 
662         final int ret_read = instr.read(buff);
663         if (ret_read == 1 && buff[0] == 'A') {
664             read_ok = true;
665         }
666 
667         // if (is1.available() == 6)
668         // {
669         int read = 0;
670         int pos = 0;
671 
672         byte[] tmp = new byte[16];
673         while (pos < 5) {
674             read = is1.read(tmp);
675             System.arraycopy(tmp, 0, buffread1, pos, read);
676             pos += read;
677         }
678 
679         if (equalBytes(buffread1, expected1)) {
680             negotiation1_ok = true;
681             // }
682         }
683 
684         final InputStream is2 = STANDARD.server.getInputStream();
685         final OutputStream os2 = STANDARD.server.getOutputStream();
686         Thread.sleep(1000);
687         is2.skip(is2.available());
688         os2.write(send1);
689         os2.flush();
690         Thread.sleep(1000);
691 
692         tmp = new byte[16];
693         while (pos < 5) {
694             read = is2.read(tmp);
695             System.arraycopy(tmp, 0, buffread1, pos, read);
696             pos += read;
697         }
698         // if (is2.available() == 6)
699         // {
700         is2.read(buffread1);
701 
702         if (equalBytes(buffread1, expected1)) {
703             negotiation2_ok = true;
704             // }
705         }
706 
707         assertFalse(NOREAD.client.getReaderThread());
708         assertTrue(STANDARD.client.getReaderThread());
709         assertTrue("Expected read_ok to be true, got " + read_ok, read_ok);
710         assertTrue("Expected negotiation1_ok to be true, got " + negotiation1_ok, negotiation1_ok);
711         assertTrue("Expected negotiation2_ok to be true, got " + negotiation2_ok, negotiation2_ok);
712     }
713 
714     /*
715      * test of Spy functionality
716      */
717     public void testSpy() throws Exception {
718         boolean test1spy_ok = false;
719         boolean test2spy_ok = false;
720         boolean stopspy_ok = false;
721         final byte[] expected1 = { (byte) 't', (byte) 'e', (byte) 's', (byte) 't', (byte) '1' };
722         final byte[] expected2 = { (byte) 't', (byte) 'e', (byte) 's', (byte) 't', (byte) '2' };
723 
724         try (final PipedOutputStream po = new PipedOutputStream(); final PipedInputStream pi = new PipedInputStream(po)) {
725 
726             final OutputStream os = STANDARD.server.getOutputStream();
727             final OutputStream ostc = STANDARD.client.getOutputStream();
728 
729             STANDARD.client.registerSpyStream(po);
730 
731             os.write("test1".getBytes());
732             os.flush();
733 
734             Thread.sleep(1000);
735             final byte[] buffer = new byte[5];
736 
737             if (pi.available() == 5) {
738                 pi.read(buffer);
739                 if (equalBytes(buffer, expected1)) {
740                     test1spy_ok = true;
741                 }
742             }
743 
744             ostc.write("test2".getBytes());
745             ostc.flush();
746 
747             Thread.sleep(1000);
748 
749             if (pi.available() == 5) {
750                 pi.read(buffer);
751                 if (equalBytes(buffer, expected2)) {
752                     test2spy_ok = true;
753                 }
754             }
755 
756             STANDARD.client.stopSpyStream();
757             os.write("test1".getBytes());
758             os.flush();
759             ostc.write("test2".getBytes());
760             ostc.flush();
761             Thread.sleep(1000);
762             if (pi.available() == 0) {
763                 stopspy_ok = true;
764             }
765 
766             assertTrue(test1spy_ok);
767             assertTrue(test2spy_ok);
768             assertTrue(stopspy_ok);
769         }
770     }
771 
772 }