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