All Downloads are FREE. Search and download functionalities are using the official Maven repository.

panda.net.telnet.TelnetClient Maven / Gradle / Ivy

Go to download

Panda Core is the core module of Panda Framework, it contains commonly used utility classes similar to apache-commons.

There is a newer version: 1.8.0
Show newest version
package panda.net.telnet;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/***
 * The TelnetClient class implements the simple network virtual terminal (NVT) for the Telnet
 * protocol according to RFC 854. It does not implement any of the extra Telnet options because it
 * is meant to be used within a Java program providing automated access to Telnet accessible
 * resources.
 * 

* The class can be used by first connecting to a server using the SocketClient * {@link panda.net.SocketClient#connect connect} method. Then an InputStream and OutputStream for * sending and receiving data over the Telnet connection can be obtained by using the * {@link #getInputStream getInputStream() } and {@link #getOutputStream getOutputStream() } * methods. When you finish using the streams, you must call {@link #disconnect disconnect } rather * than simply closing the streams. ***/ public class TelnetClient extends Telnet { private InputStream __input; private OutputStream __output; protected boolean readerThread = true; private TelnetInputListener inputListener; /*** * Default TelnetClient constructor, sets terminal-type {@code VT100}. ***/ public TelnetClient() { /* TERMINAL-TYPE option (start) */ super("VT100"); /* TERMINAL-TYPE option (end) */ __input = null; __output = null; } /** * Construct an instance with the specified terminal type. * * @param termtype the terminal type to use, e.g. {@code VT100} */ /* TERMINAL-TYPE option (start) */ public TelnetClient(String termtype) { super(termtype); __input = null; __output = null; } /* TERMINAL-TYPE option (end) */ void _flushOutputStream() throws IOException { _output_.flush(); } void _closeOutputStream() throws IOException { _output_.close(); } /*** * Handles special connection requirements. * * @exception IOException If an error occurs during connection setup. ***/ @Override protected void _connectAction_() throws IOException { super._connectAction_(); TelnetInputStream tmp = new TelnetInputStream(_input_, this, readerThread); if (readerThread) { tmp._start(); } // __input CANNOT refer to the TelnetInputStream. We run into // blocking problems when some classes use TelnetInputStream, so // we wrap it with a BufferedInputStream which we know is safe. // This blocking behavior requires further investigation, but right // now it looks like classes like InputStreamReader are not implemented // in a safe manner. __input = new BufferedInputStream(tmp); __output = new TelnetOutputStream(this); } /*** * Disconnects the telnet session, closing the input and output streams as well as the socket. * If you have references to the input and output streams of the telnet connection, you should * not close them yourself, but rather call disconnect to properly close the connection. ***/ @Override public void disconnect() throws IOException { if (__input != null) { __input.close(); } if (__output != null) { __output.close(); } super.disconnect(); } /*** * Returns the telnet connection output stream. You should not close the stream when you finish * with it. Rather, you should call {@link #disconnect disconnect }. * * @return The telnet connection output stream. ***/ public OutputStream getOutputStream() { return __output; } /*** * Returns the telnet connection input stream. You should not close the stream when you finish * with it. Rather, you should call {@link #disconnect disconnect }. * * @return The telnet connection input stream. ***/ public InputStream getInputStream() { return __input; } /*** * Returns the state of the option on the local side. * * @param option - Option to be checked. * @return The state of the option on the local side. ***/ public boolean getLocalOptionState(int option) { /* BUG (option active when not already acknowledged) (start) */ return (_stateIsWill(option) && _requestedWill(option)); /* BUG (option active when not already acknowledged) (end) */ } /*** * Returns the state of the option on the remote side. * * @param option - Option to be checked. * @return The state of the option on the remote side. ***/ public boolean getRemoteOptionState(int option) { /* BUG (option active when not already acknowledged) (start) */ return (_stateIsDo(option) && _requestedDo(option)); /* BUG (option active when not already acknowledged) (end) */ } /* open TelnetOptionHandler functionality (end) */ /* Code Section added for supporting AYT (start) */ /*** * Sends an Are You There sequence and waits for the result. * * @param timeout - Time to wait for a response (millis.) * @return true if AYT received a response, false otherwise * @throws InterruptedException on error * @throws IllegalArgumentException on error * @throws IOException on error ***/ public boolean sendAYT(long timeout) throws IOException, IllegalArgumentException, InterruptedException { return (_sendAYT(timeout)); } /* Code Section added for supporting AYT (start) */ /*** * Sends a protocol-specific subnegotiation message to the remote peer. {@link TelnetClient} * will add the IAC SB & IAC SE framing bytes; the first byte in {@code message} should be * the appropriate telnet option code. *

* This method does not wait for any response. Subnegotiation messages sent by the remote end * can be handled by registering an approrpriate {@link TelnetOptionHandler}. *

* * @param message option code followed by subnegotiation payload * @throws IllegalArgumentException if {@code message} has length zero * @throws IOException if an I/O error occurs while writing the message ***/ public void sendSubnegotiation(int[] message) throws IOException, IllegalArgumentException { if (message.length < 1) { throw new IllegalArgumentException("zero length message"); } _sendSubnegotiation(message); } /*** * Sends a command byte to the remote peer, adding the IAC prefix. *

* This method does not wait for any response. Messages sent by the remote end can be handled by * registering an approrpriate {@link TelnetOptionHandler}. *

* * @param command the code for the command * @throws IOException if an I/O error occurs while writing the message * @throws IllegalArgumentException on error ***/ public void sendCommand(byte command) throws IOException, IllegalArgumentException { _sendCommand(command); } /* open TelnetOptionHandler functionality (start) */ /*** * Registers a new TelnetOptionHandler for this telnet client to use. * * @param opthand - option handler to be registered. * @throws InvalidTelnetOptionException on error * @throws IOException on error ***/ @Override public void addOptionHandler(TelnetOptionHandler opthand) throws InvalidTelnetOptionException, IOException { super.addOptionHandler(opthand); } /* open TelnetOptionHandler functionality (end) */ /*** * Unregisters a TelnetOptionHandler. * * @param optcode - Code of the option to be unregistered. * @throws InvalidTelnetOptionException on error * @throws IOException on error ***/ @Override public void deleteOptionHandler(int optcode) throws InvalidTelnetOptionException, IOException { super.deleteOptionHandler(optcode); } /* Code Section added for supporting spystreams (start) */ /*** * Registers an OutputStream for spying what's going on in the TelnetClient session. * * @param spystream - OutputStream on which session activity will be echoed. ***/ public void registerSpyStream(OutputStream spystream) { super._registerSpyStream(spystream); } /*** * Stops spying this TelnetClient. ***/ public void stopSpyStream() { super._stopSpyStream(); } /* Code Section added for supporting spystreams (end) */ /*** * Registers a notification handler to which will be sent notifications of received telnet * option negotiation commands. * * @param notifhand - TelnetNotificationHandler to be registered ***/ @Override public void registerNotifHandler(TelnetNotificationHandler notifhand) { super.registerNotifHandler(notifhand); } /*** * Unregisters the current notification handler. ***/ @Override public void unregisterNotifHandler() { super.unregisterNotifHandler(); } /*** * Sets the status of the reader thread. *

* When enabled, a seaparate internal reader thread is created for new connections to read * incoming data as it arrives. This results in immediate handling of option negotiation, * notifications, etc. (at least until the fixed-size internal buffer fills up). Otherwise, no * thread is created an all negotiation and option handling is deferred until a read() is * performed on the {@link #getInputStream input stream}. *

*

* The reader thread must be enabled for {@link TelnetInputListener} support. *

*

* When this method is invoked, the reader thread status will apply to all subsequent * connections; the current connection (if any) is not affected. *

* * @param flag true to enable the reader thread, false to disable * @see #registerInputListener ***/ public void setReaderThread(boolean flag) { readerThread = flag; } /*** * Gets the status of the reader thread. * * @return true if the reader thread is enabled, false otherwise ***/ public boolean getReaderThread() { return (readerThread); } /*** * Register a listener to be notified when new incoming data is available to be read on the * {@link #getInputStream input stream}. Only one listener is supported at a time. *

* More precisely, notifications are issued whenever the number of bytes available for immediate * reading (i.e., the value returned by {@link InputStream#available}) transitions from zero to * non-zero. Note that (in general) multiple reads may be required to empty the buffer and reset * this notification, because incoming bytes are being added to the internal buffer * asynchronously. *

*

* Notifications are only supported when a {@link #setReaderThread reader thread} is enabled for * the connection. *

* * @param listener listener to be registered; replaces any previous ***/ public synchronized void registerInputListener(TelnetInputListener listener) { this.inputListener = listener; } /*** * Unregisters the current {@link TelnetInputListener}, if any. ***/ public synchronized void unregisterInputListener() { this.inputListener = null; } // Notify input listener void notifyInputListener() { TelnetInputListener listener; synchronized (this) { listener = this.inputListener; } if (listener != null) { listener.telnetInputAvailable(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy