001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.net.telnet; 019 020 import java.io.BufferedInputStream; 021 import java.io.IOException; 022 import java.io.InputStream; 023 import java.io.OutputStream; 024 025 import org.apache.commons.net.io.FromNetASCIIInputStream; 026 import org.apache.commons.net.io.ToNetASCIIOutputStream; 027 028 /*** 029 * The TelnetClient class implements the simple network virtual 030 * terminal (NVT) for the Telnet protocol according to RFC 854. It 031 * does not implement any of the extra Telnet options because it 032 * is meant to be used within a Java program providing automated 033 * access to Telnet accessible resources. 034 * <p> 035 * The class can be used by first connecting to a server using the 036 * SocketClient 037 * {@link org.apache.commons.net.SocketClient#connect connect} 038 * method. Then an InputStream and OutputStream for sending and 039 * receiving data over the Telnet connection can be obtained by 040 * using the {@link #getInputStream getInputStream() } and 041 * {@link #getOutputStream getOutputStream() } methods. 042 * When you finish using the streams, you must call 043 * {@link #disconnect disconnect } rather than simply 044 * closing the streams. 045 * <p> 046 * <p> 047 * @author Daniel F. Savarese 048 * @author Bruno D'Avanzo 049 ***/ 050 051 public class TelnetClient extends Telnet 052 { 053 private InputStream __input; 054 private OutputStream __output; 055 protected boolean readerThread = true; 056 057 /*** 058 * Default TelnetClient constructor. 059 ***/ 060 public TelnetClient() 061 { 062 /* TERMINAL-TYPE option (start)*/ 063 super ("VT100"); 064 /* TERMINAL-TYPE option (end)*/ 065 __input = null; 066 __output = null; 067 } 068 069 /* TERMINAL-TYPE option (start)*/ 070 public TelnetClient(String termtype) 071 { 072 super (termtype); 073 __input = null; 074 __output = null; 075 } 076 /* TERMINAL-TYPE option (end)*/ 077 078 void _flushOutputStream() throws IOException 079 { 080 _output_.flush(); 081 } 082 void _closeOutputStream() throws IOException 083 { 084 _output_.close(); 085 } 086 087 /*** 088 * Handles special connection requirements. 089 * <p> 090 * @exception IOException If an error occurs during connection setup. 091 ***/ 092 @Override 093 protected void _connectAction_() throws IOException 094 { 095 super._connectAction_(); 096 InputStream input; 097 TelnetInputStream tmp; 098 099 if (FromNetASCIIInputStream.isConversionRequired()) 100 input = new FromNetASCIIInputStream(_input_); 101 else 102 input = _input_; 103 104 105 tmp = new TelnetInputStream(input, this, readerThread); 106 if(readerThread) 107 { 108 tmp._start(); 109 } 110 // __input CANNOT refer to the TelnetInputStream. We run into 111 // blocking problems when some classes use TelnetInputStream, so 112 // we wrap it with a BufferedInputStream which we know is safe. 113 // This blocking behavior requires further investigation, but right 114 // now it looks like classes like InputStreamReader are not implemented 115 // in a safe manner. 116 __input = new BufferedInputStream(tmp); 117 __output = new ToNetASCIIOutputStream(new TelnetOutputStream(this)); 118 } 119 120 /*** 121 * Disconnects the telnet session, closing the input and output streams 122 * as well as the socket. If you have references to the 123 * input and output streams of the telnet connection, you should not 124 * close them yourself, but rather call disconnect to properly close 125 * the connection. 126 ***/ 127 @Override 128 public void disconnect() throws IOException 129 { 130 if (__input != null) 131 __input.close(); 132 if (__output != null) 133 __output.close(); 134 super.disconnect(); 135 } 136 137 /*** 138 * Returns the telnet connection output stream. You should not close the 139 * stream when you finish with it. Rather, you should call 140 * {@link #disconnect disconnect }. 141 * <p> 142 * @return The telnet connection output stream. 143 ***/ 144 public OutputStream getOutputStream() 145 { 146 return __output; 147 } 148 149 /*** 150 * Returns the telnet connection input stream. You should not close the 151 * stream when you finish with it. Rather, you should call 152 * {@link #disconnect disconnect }. 153 * <p> 154 * @return The telnet connection input stream. 155 ***/ 156 public InputStream getInputStream() 157 { 158 return __input; 159 } 160 161 /*** 162 * Returns the state of the option on the local side. 163 * <p> 164 * @param option - Option to be checked. 165 * <p> 166 * @return The state of the option on the local side. 167 ***/ 168 public boolean getLocalOptionState(int option) 169 { 170 /* BUG (option active when not already acknowledged) (start)*/ 171 return (_stateIsWill(option) && _requestedWill(option)); 172 /* BUG (option active when not already acknowledged) (end)*/ 173 } 174 175 /*** 176 * Returns the state of the option on the remote side. 177 * <p> 178 * @param option - Option to be checked. 179 * <p> 180 * @return The state of the option on the remote side. 181 ***/ 182 public boolean getRemoteOptionState(int option) 183 { 184 /* BUG (option active when not already acknowledged) (start)*/ 185 return (_stateIsDo(option) && _requestedDo(option)); 186 /* BUG (option active when not already acknowledged) (end)*/ 187 } 188 /* open TelnetOptionHandler functionality (end)*/ 189 190 /* Code Section added for supporting AYT (start)*/ 191 192 /*** 193 * Sends an Are You There sequence and waits for the result. 194 * <p> 195 * @param timeout - Time to wait for a response (millis.) 196 * <p> 197 * @return true if AYT received a response, false otherwise 198 * <p> 199 * @throws InterruptedException 200 * @throws IllegalArgumentException 201 * @throws IOException 202 ***/ 203 public boolean sendAYT(long timeout) 204 throws IOException, IllegalArgumentException, InterruptedException 205 { 206 return (_sendAYT(timeout)); 207 } 208 /* Code Section added for supporting AYT (start)*/ 209 210 /* open TelnetOptionHandler functionality (start)*/ 211 212 /*** 213 * Registers a new TelnetOptionHandler for this telnet client to use. 214 * <p> 215 * @param opthand - option handler to be registered. 216 * <p> 217 * @throws InvalidTelnetOptionException 218 ***/ 219 @Override 220 public void addOptionHandler(TelnetOptionHandler opthand) 221 throws InvalidTelnetOptionException 222 { 223 super.addOptionHandler(opthand); 224 } 225 /* open TelnetOptionHandler functionality (end)*/ 226 227 /*** 228 * Unregisters a TelnetOptionHandler. 229 * <p> 230 * @param optcode - Code of the option to be unregistered. 231 * <p> 232 * @throws InvalidTelnetOptionException 233 ***/ 234 @Override 235 public void deleteOptionHandler(int optcode) 236 throws InvalidTelnetOptionException 237 { 238 super.deleteOptionHandler(optcode); 239 } 240 241 /* Code Section added for supporting spystreams (start)*/ 242 /*** 243 * Registers an OutputStream for spying what's going on in 244 * the TelnetClient session. 245 * <p> 246 * @param spystream - OutputStream on which session activity 247 * will be echoed. 248 ***/ 249 public void registerSpyStream(OutputStream spystream) 250 { 251 super._registerSpyStream(spystream); 252 } 253 254 /*** 255 * Stops spying this TelnetClient. 256 * <p> 257 ***/ 258 public void stopSpyStream() 259 { 260 super._stopSpyStream(); 261 } 262 /* Code Section added for supporting spystreams (end)*/ 263 264 /*** 265 * Registers a notification handler to which will be sent 266 * notifications of received telnet option negotiation commands. 267 * <p> 268 * @param notifhand - TelnetNotificationHandler to be registered 269 ***/ 270 @Override 271 public void registerNotifHandler(TelnetNotificationHandler notifhand) 272 { 273 super.registerNotifHandler(notifhand); 274 } 275 276 /*** 277 * Unregisters the current notification handler. 278 * <p> 279 ***/ 280 @Override 281 public void unregisterNotifHandler() 282 { 283 super.unregisterNotifHandler(); 284 } 285 286 /*** 287 * Sets the status of the reader thread. 288 * The reader thread status will apply to all subsequent connections 289 * <p> 290 * @param flag - true switches the reader thread on, false switches it off 291 ***/ 292 public void setReaderThread(boolean flag) 293 { 294 readerThread = flag; 295 } 296 297 /*** 298 * Gets the status of the reader thread. 299 * <p> 300 * @return true if the reader thread is on, false otherwise 301 ***/ 302 public boolean getReaderThread() 303 { 304 return (readerThread); 305 } 306 }