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  
18  package org.apache.commons.net.examples.telnet;
19  
20  import java.io.FileOutputStream;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.OutputStream;
24  import java.nio.charset.Charset;
25  import java.time.Duration;
26  import java.util.StringTokenizer;
27  
28  import org.apache.commons.net.telnet.EchoOptionHandler;
29  import org.apache.commons.net.telnet.InvalidTelnetOptionException;
30  import org.apache.commons.net.telnet.SimpleOptionHandler;
31  import org.apache.commons.net.telnet.SuppressGAOptionHandler;
32  import org.apache.commons.net.telnet.TelnetClient;
33  import org.apache.commons.net.telnet.TelnetNotificationHandler;
34  import org.apache.commons.net.telnet.TerminalTypeOptionHandler;
35  
36  /**
37   * This is a simple example of use of TelnetClient. An external option handler (SimpleTelnetOptionHandler) is used. Initial configuration requested by
38   * TelnetClient will be: WILL ECHO, WILL SUPPRESS-GA, DO SUPPRESS-GA. VT100 terminal type will be subnegotiated.
39   * <p>
40   * Also, use of the sendAYT(), getLocalOptionState(), getRemoteOptionState() is demonstrated. When connected, type AYT to send an AYT command to the server and
41   * see the result. Type OPT to see a report of the state of the first 25 options.
42   */
43  public class TelnetClientExample implements Runnable, TelnetNotificationHandler {
44      private static TelnetClient tc;
45  
46      /**
47       * Main for the TelnetClientExample.
48       *
49       * @param args input params
50       * @throws Exception on error
51       */
52      public static void main(final String[] args) throws Exception {
53          FileOutputStream fout = null;
54  
55          if (args.length < 1) {
56              System.err.println("Usage: TelnetClientExample <remote-ip> [<remote-port>]");
57              System.exit(1);
58          }
59  
60          final String remoteip = args[0];
61  
62          final int remoteport;
63  
64          if (args.length > 1) {
65              remoteport = Integer.parseInt(args[1]);
66          } else {
67              remoteport = 23;
68          }
69  
70          try {
71              fout = new FileOutputStream("spy.log", true);
72          } catch (final IOException e) {
73              System.err.println("Exception while opening the spy file: " + e.getMessage());
74          }
75  
76          tc = new TelnetClient();
77  
78          final TerminalTypeOptionHandler ttopt = new TerminalTypeOptionHandler("VT100", false, false, true, false);
79          final EchoOptionHandler echoopt = new EchoOptionHandler(true, false, true, false);
80          final SuppressGAOptionHandler gaopt = new SuppressGAOptionHandler(true, true, true, true);
81  
82          try {
83              tc.addOptionHandler(ttopt);
84              tc.addOptionHandler(echoopt);
85              tc.addOptionHandler(gaopt);
86          } catch (final InvalidTelnetOptionException e) {
87              System.err.println("Error registering option handlers: " + e.getMessage());
88          }
89  
90          while (true) {
91              boolean end_loop = false;
92              try {
93                  tc.connect(remoteip, remoteport);
94  
95                  final Thread reader = new Thread(new TelnetClientExample());
96                  tc.registerNotifHandler(new TelnetClientExample());
97                  System.out.println("TelnetClientExample");
98                  System.out.println("Type AYT to send an AYT telnet command");
99                  System.out.println("Type OPT to print a report of status of options (0-24)");
100                 System.out.println("Type REGISTER to register a new SimpleOptionHandler");
101                 System.out.println("Type UNREGISTER to unregister an OptionHandler");
102                 System.out.println("Type SPY to register the spy (connect to port 3333 to spy)");
103                 System.out.println("Type UNSPY to stop spying the connection");
104                 System.out.println("Type ^[A-Z] to send the control character; use ^^ to send ^");
105 
106                 reader.start();
107                 final OutputStream outstr = tc.getOutputStream();
108 
109                 final byte[] buff = new byte[1024];
110                 int readCount = 0;
111 
112                 do {
113                     try {
114                         readCount = System.in.read(buff);
115                         if (readCount > 0) {
116                             final Charset charset = Charset.defaultCharset();
117                             final String line = new String(buff, 0, readCount, charset); // deliberate use of default charset
118                             if (line.startsWith("AYT")) {
119                                 try {
120                                     System.out.println("Sending AYT");
121 
122                                     System.out.println("AYT response:" + tc.sendAYT(Duration.ofSeconds(5)));
123                                 } catch (final IOException e) {
124                                     System.err.println("Exception waiting AYT response: " + e.getMessage());
125                                 }
126                             } else if (line.startsWith("OPT")) {
127                                 System.out.println("Status of options:");
128                                 for (int ii = 0; ii < 25; ii++) {
129                                     System.out.println("Local Option " + ii + ":" + tc.getLocalOptionState(ii) + " Remote Option " + ii + ":"
130                                             + tc.getRemoteOptionState(ii));
131                                 }
132                             } else if (line.startsWith("REGISTER")) {
133                                 final StringTokenizer st = new StringTokenizer(new String(buff, charset));
134                                 try {
135                                     st.nextToken();
136                                     final int opcode = Integer.parseInt(st.nextToken());
137                                     final boolean initlocal = Boolean.parseBoolean(st.nextToken());
138                                     final boolean initremote = Boolean.parseBoolean(st.nextToken());
139                                     final boolean acceptlocal = Boolean.parseBoolean(st.nextToken());
140                                     final boolean acceptremote = Boolean.parseBoolean(st.nextToken());
141                                     final SimpleOptionHandler opthand = new SimpleOptionHandler(opcode, initlocal, initremote, acceptlocal, acceptremote);
142                                     tc.addOptionHandler(opthand);
143                                 } catch (final Exception e) {
144                                     if (e instanceof InvalidTelnetOptionException) {
145                                         System.err.println("Error registering option: " + e.getMessage());
146                                     } else {
147                                         System.err.println("Invalid REGISTER command.");
148                                         System.err.println("Use REGISTER optcode initlocal initremote acceptlocal acceptremote");
149                                         System.err.println("(optcode is an integer.)");
150                                         System.err.println("(initlocal, initremote, acceptlocal, acceptremote are boolean)");
151                                     }
152                                 }
153                             } else if (line.startsWith("UNREGISTER")) {
154                                 final StringTokenizer st = new StringTokenizer(new String(buff, charset));
155                                 try {
156                                     st.nextToken();
157                                     final int opcode = Integer.parseInt(st.nextToken());
158                                     tc.deleteOptionHandler(opcode);
159                                 } catch (final Exception e) {
160                                     if (e instanceof InvalidTelnetOptionException) {
161                                         System.err.println("Error unregistering option: " + e.getMessage());
162                                     } else {
163                                         System.err.println("Invalid UNREGISTER command.");
164                                         System.err.println("Use UNREGISTER optcode");
165                                         System.err.println("(optcode is an integer)");
166                                     }
167                                 }
168                             } else if (line.startsWith("SPY")) {
169                                 tc.registerSpyStream(fout);
170                             } else if (line.startsWith("UNSPY")) {
171                                 tc.stopSpyStream();
172                             } else if (line.matches("^\\^[A-Z^]\\r?\\n?$")) {
173                                 final byte toSend = buff[1];
174                                 if (toSend == '^') {
175                                     outstr.write(toSend);
176                                 } else {
177                                     outstr.write(toSend - 'A' + 1);
178                                 }
179                                 outstr.flush();
180                             } else {
181                                 try {
182                                     outstr.write(buff, 0, readCount);
183                                     outstr.flush();
184                                 } catch (final IOException e) {
185                                     end_loop = true;
186                                 }
187                             }
188                         }
189                     } catch (final IOException e) {
190                         System.err.println("Exception while reading keyboard:" + e.getMessage());
191                         end_loop = true;
192                     }
193                 } while (readCount > 0 && !end_loop);
194 
195                 try {
196                     tc.disconnect();
197                 } catch (final IOException e) {
198                     System.err.println("Exception while connecting:" + e.getMessage());
199                 }
200             } catch (final IOException e) {
201                 System.err.println("Exception while connecting:" + e.getMessage());
202                 System.exit(1);
203             }
204         }
205     }
206 
207     /**
208      * Callback method called when TelnetClient receives an option negotiation command.
209      *
210      * @param negotiation_code - type of negotiation command received (RECEIVED_DO, RECEIVED_DONT, RECEIVED_WILL, RECEIVED_WONT, RECEIVED_COMMAND)
211      * @param option_code      - code of the option negotiated
212      */
213     @Override
214     public void receivedNegotiation(final int negotiation_code, final int option_code) {
215         String command;
216         switch (negotiation_code) {
217         case TelnetNotificationHandler.RECEIVED_DO:
218             command = "DO";
219             break;
220         case TelnetNotificationHandler.RECEIVED_DONT:
221             command = "DONT";
222             break;
223         case TelnetNotificationHandler.RECEIVED_WILL:
224             command = "WILL";
225             break;
226         case TelnetNotificationHandler.RECEIVED_WONT:
227             command = "WONT";
228             break;
229         case TelnetNotificationHandler.RECEIVED_COMMAND:
230             command = "COMMAND";
231             break;
232         default:
233             command = Integer.toString(negotiation_code); // Should not happen
234             break;
235         }
236         System.out.println("Received " + command + " for option code " + option_code);
237     }
238 
239     /**
240      * Reader thread: Reads lines from the TelnetClient and echoes them on the screen.
241      */
242     @Override
243     public void run() {
244         final InputStream instr = tc.getInputStream();
245 
246         try {
247             final byte[] buff = new byte[1024];
248             int readCount = 0;
249 
250             do {
251                 readCount = instr.read(buff);
252                 if (readCount > 0) {
253                     System.out.print(new String(buff, 0, readCount, Charset.defaultCharset()));
254                 }
255             } while (readCount >= 0);
256         } catch (final IOException e) {
257             System.err.println("Exception while reading socket:" + e.getMessage());
258         }
259 
260         try {
261             tc.disconnect();
262         } catch (final IOException e) {
263             System.err.println("Exception while closing telnet:" + e.getMessage());
264         }
265     }
266 }