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