summaryrefslogtreecommitdiff
path: root/org/apache/commons/net/telnet/Telnet.java
diff options
context:
space:
mode:
Diffstat (limited to 'org/apache/commons/net/telnet/Telnet.java')
-rw-r--r--org/apache/commons/net/telnet/Telnet.java1317
1 files changed, 1317 insertions, 0 deletions
diff --git a/org/apache/commons/net/telnet/Telnet.java b/org/apache/commons/net/telnet/Telnet.java
new file mode 100644
index 0000000..c05b563
--- /dev/null
+++ b/org/apache/commons/net/telnet/Telnet.java
@@ -0,0 +1,1317 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import org.apache.commons.net.SocketClient;
+
+/**
+ * @author Daniel F. Savarese
+ * @author Bruno D'Avanzo
+ */
+
+class Telnet extends SocketClient
+{
+ static final boolean debug = /*true;*/ false;
+
+ static final boolean debugoptions = /*true;*/ false;
+
+ static final byte[] _COMMAND_DO = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.DO
+ };
+
+ static final byte[] _COMMAND_DONT = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.DONT
+ };
+
+ static final byte[] _COMMAND_WILL = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.WILL
+ };
+
+ static final byte[] _COMMAND_WONT = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.WONT
+ };
+
+ static final byte[] _COMMAND_SB = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.SB
+ };
+
+ static final byte[] _COMMAND_SE = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.SE
+ };
+
+ static final int _WILL_MASK = 0x01, _DO_MASK = 0x02,
+ _REQUESTED_WILL_MASK = 0x04, _REQUESTED_DO_MASK = 0x08;
+
+ /* public */
+ static final int DEFAULT_PORT = 23;
+
+ int[] _doResponse, _willResponse, _options;
+
+ /* TERMINAL-TYPE option (start)*/
+ /***
+ * Terminal type option
+ ***/
+ protected static final int TERMINAL_TYPE = 24;
+
+ /***
+ * Send (for subnegotiation)
+ ***/
+ protected static final int TERMINAL_TYPE_SEND = 1;
+
+ /***
+ * Is (for subnegotiation)
+ ***/
+ protected static final int TERMINAL_TYPE_IS = 0;
+
+ /***
+ * Is sequence (for subnegotiation)
+ ***/
+ static final byte[] _COMMAND_IS = {
+ (byte) TERMINAL_TYPE, (byte) TERMINAL_TYPE_IS
+ };
+
+ /***
+ * Terminal type
+ ***/
+ private String terminalType = null;
+ /* TERMINAL-TYPE option (end)*/
+
+ /* open TelnetOptionHandler functionality (start)*/
+ /***
+ * Array of option handlers
+ ***/
+ private TelnetOptionHandler optionHandlers[];
+
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /* Code Section added for supporting AYT (start)*/
+ /***
+ * AYT sequence
+ ***/
+ static final byte[] _COMMAND_AYT = {
+ (byte) TelnetCommand.IAC, (byte) TelnetCommand.AYT
+ };
+
+ /***
+ * monitor to wait for AYT
+ ***/
+ private Object aytMonitor = new Object();
+
+ /***
+ * flag for AYT
+ ***/
+ private boolean aytFlag = true;
+ /* Code Section added for supporting AYT (end)*/
+
+ /***
+ * The stream on which to spy
+ ***/
+ private OutputStream spyStream = null;
+
+ /***
+ * The notification handler
+ ***/
+ private TelnetNotificationHandler __notifhand = null;
+ /***
+ * Empty Constructor
+ ***/
+ Telnet()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ optionHandlers =
+ new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
+ }
+
+ /* TERMINAL-TYPE option (start)*/
+ /***
+ * This constructor lets you specify the terminal type.
+ * <p>
+ * @param termtype - terminal type to be negotiated (ej. VT100)
+ ***/
+ Telnet(String termtype)
+ {
+ setDefaultPort(DEFAULT_PORT);
+ _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ terminalType = termtype;
+ optionHandlers =
+ new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
+ }
+ /* TERMINAL-TYPE option (end)*/
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a will has been acknowledged
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _stateIsWill(int option)
+ {
+ return ((_options[option] & _WILL_MASK) != 0);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a wont has been acknowledged
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _stateIsWont(int option)
+ {
+ return !_stateIsWill(option);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a do has been acknowledged
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _stateIsDo(int option)
+ {
+ return ((_options[option] & _DO_MASK) != 0);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a dont has been acknowledged
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _stateIsDont(int option)
+ {
+ return !_stateIsDo(option);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a will has been reuqested
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _requestedWill(int option)
+ {
+ return ((_options[option] & _REQUESTED_WILL_MASK) != 0);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a wont has been reuqested
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _requestedWont(int option)
+ {
+ return !_requestedWill(option);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a do has been reuqested
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _requestedDo(int option)
+ {
+ return ((_options[option] & _REQUESTED_DO_MASK) != 0);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a dont has been reuqested
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _requestedDont(int option)
+ {
+ return !_requestedDo(option);
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setWill(int option)
+ {
+ _options[option] |= _WILL_MASK;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (_requestedWill(option))
+ {
+ if (optionHandlers[option] != null)
+ {
+ optionHandlers[option].setWill(true);
+
+ int subneg[] =
+ optionHandlers[option].startSubnegotiationLocal();
+
+ if (subneg != null)
+ {
+ try
+ {
+ _sendSubnegotiation(subneg);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception in option subnegotiation"
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setDo(int option)
+ {
+ _options[option] |= _DO_MASK;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (_requestedDo(option))
+ {
+ if (optionHandlers[option] != null)
+ {
+ optionHandlers[option].setDo(true);
+
+ int subneg[] =
+ optionHandlers[option].startSubnegotiationRemote();
+
+ if (subneg != null)
+ {
+ try
+ {
+ _sendSubnegotiation(subneg);
+ }
+ catch (IOException e)
+ {
+ System.err.println("Exception in option subnegotiation"
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setWantWill(int option)
+ {
+ _options[option] |= _REQUESTED_WILL_MASK;
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setWantDo(int option)
+ {
+ _options[option] |= _REQUESTED_DO_MASK;
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setWont(int option)
+ {
+ _options[option] &= ~_WILL_MASK;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (optionHandlers[option] != null)
+ {
+ optionHandlers[option].setWill(false);
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setDont(int option)
+ {
+ _options[option] &= ~_DO_MASK;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (optionHandlers[option] != null)
+ {
+ optionHandlers[option].setDo(false);
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setWantWont(int option)
+ {
+ _options[option] &= ~_REQUESTED_WILL_MASK;
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setWantDont(int option)
+ {
+ _options[option] &= ~_REQUESTED_DO_MASK;
+ }
+
+ /**
+ * Processes a DO request.
+ *
+ * @param option - option code to be set.
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processDo(int option) throws IOException
+ {
+ if (debugoptions)
+ {
+ System.err.println("RECEIVED DO: "
+ + TelnetOption.getOption(option));
+ }
+
+ if (__notifhand != null)
+ {
+ __notifhand.receivedNegotiation(
+ TelnetNotificationHandler.RECEIVED_DO,
+ option);
+ }
+
+ boolean acceptNewState = false;
+
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (optionHandlers[option] != null)
+ {
+ acceptNewState = optionHandlers[option].getAcceptLocal();
+ }
+ else
+ {
+ /* open TelnetOptionHandler functionality (end)*/
+ /* TERMINAL-TYPE option (start)*/
+ if (option == TERMINAL_TYPE)
+ {
+ if ((terminalType != null) && (terminalType.length() > 0))
+ {
+ acceptNewState = true;
+ }
+ }
+ /* TERMINAL-TYPE option (end)*/
+ /* open TelnetOptionHandler functionality (start)*/
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ if (_willResponse[option] > 0)
+ {
+ --_willResponse[option];
+ if (_willResponse[option] > 0 && _stateIsWill(option))
+ {
+ --_willResponse[option];
+ }
+ }
+
+ if (_willResponse[option] == 0)
+ {
+ if (_requestedWont(option))
+ {
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+
+ if (acceptNewState)
+ {
+ _setWantWill(option);
+ _sendWill(option);
+ }
+ else
+ {
+ ++_willResponse[option];
+ _sendWont(option);
+ }
+ }
+ else
+ {
+ // Other end has acknowledged option.
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+ }
+ }
+
+ _setWill(option);
+ }
+
+ /**
+ * Processes a DONT request.
+ *
+ * @param option - option code to be set.
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processDont(int option) throws IOException
+ {
+ if (debugoptions)
+ {
+ System.err.println("RECEIVED DONT: "
+ + TelnetOption.getOption(option));
+ }
+ if (__notifhand != null)
+ {
+ __notifhand.receivedNegotiation(
+ TelnetNotificationHandler.RECEIVED_DONT,
+ option);
+ }
+ if (_willResponse[option] > 0)
+ {
+ --_willResponse[option];
+ if (_willResponse[option] > 0 && _stateIsWont(option))
+ {
+ --_willResponse[option];
+ }
+ }
+
+ if (_willResponse[option] == 0 && _requestedWill(option))
+ {
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+ /* FIX for a BUG in the negotiation (start)*/
+ if ((_stateIsWill(option)) || (_requestedWill(option)))
+ {
+ _sendWont(option);
+ }
+
+ _setWantWont(option);
+ /* FIX for a BUG in the negotiation (end)*/
+ }
+
+ _setWont(option);
+ }
+
+
+ /**
+ * Processes a WILL request.
+ *
+ * @param option - option code to be set.
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processWill(int option) throws IOException
+ {
+ if (debugoptions)
+ {
+ System.err.println("RECEIVED WILL: "
+ + TelnetOption.getOption(option));
+ }
+
+ if (__notifhand != null)
+ {
+ __notifhand.receivedNegotiation(
+ TelnetNotificationHandler.RECEIVED_WILL,
+ option);
+ }
+
+ boolean acceptNewState = false;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (optionHandlers[option] != null)
+ {
+ acceptNewState = optionHandlers[option].getAcceptRemote();
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ if (_doResponse[option] > 0)
+ {
+ --_doResponse[option];
+ if (_doResponse[option] > 0 && _stateIsDo(option))
+ {
+ --_doResponse[option];
+ }
+ }
+
+ if (_doResponse[option] == 0 && _requestedDont(option))
+ {
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+
+ if (acceptNewState)
+ {
+ _setWantDo(option);
+ _sendDo(option);
+ }
+ else
+ {
+ ++_doResponse[option];
+ _sendDont(option);
+ }
+ }
+
+ _setDo(option);
+ }
+
+ /**
+ * Processes a WONT request.
+ *
+ * @param option - option code to be set.
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processWont(int option) throws IOException
+ {
+ if (debugoptions)
+ {
+ System.err.println("RECEIVED WONT: "
+ + TelnetOption.getOption(option));
+ }
+
+ if (__notifhand != null)
+ {
+ __notifhand.receivedNegotiation(
+ TelnetNotificationHandler.RECEIVED_WONT,
+ option);
+ }
+
+ if (_doResponse[option] > 0)
+ {
+ --_doResponse[option];
+ if (_doResponse[option] > 0 && _stateIsDont(option))
+ {
+ --_doResponse[option];
+ }
+ }
+
+ if (_doResponse[option] == 0 && _requestedDo(option))
+ {
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+ /* FIX for a BUG in the negotiation (start)*/
+ if ((_stateIsDo(option)) || (_requestedDo(option)))
+ {
+ _sendDont(option);
+ }
+
+ _setWantDont(option);
+ /* FIX for a BUG in the negotiation (end)*/
+ }
+
+ _setDont(option);
+ }
+
+ /* TERMINAL-TYPE option (start)*/
+ /**
+ * Processes a suboption negotiation.
+ *
+ * @param suboption - subnegotiation data received
+ * @param suboptionLength - length of data received
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processSuboption(int suboption[], int suboptionLength)
+ throws IOException
+ {
+ if (debug)
+ {
+ System.err.println("PROCESS SUBOPTION.");
+ }
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (suboptionLength > 0)
+ {
+ if (optionHandlers[suboption[0]] != null)
+ {
+ int responseSuboption[] =
+ optionHandlers[suboption[0]].answerSubnegotiation(suboption,
+ suboptionLength);
+ _sendSubnegotiation(responseSuboption);
+ }
+ else
+ {
+ if (suboptionLength > 1)
+ {
+ if (debug)
+ {
+ for (int ii = 0; ii < suboptionLength; ii++)
+ {
+ System.err.println("SUB[" + ii + "]: "
+ + suboption[ii]);
+ }
+ }
+ if ((suboption[0] == TERMINAL_TYPE)
+ && (suboption[1] == TERMINAL_TYPE_SEND))
+ {
+ _sendTerminalType();
+ }
+ }
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sends terminal type information.
+ * <p>
+ * @throws IOException - Exception in I/O.
+ ***/
+ final synchronized void _sendTerminalType()
+ throws IOException
+ {
+ if (debug)
+ {
+ System.err.println("SEND TERMINAL-TYPE: " + terminalType);
+ }
+ if (terminalType != null)
+ {
+ _output_.write(_COMMAND_SB);
+ _output_.write(_COMMAND_IS);
+ _output_.write(terminalType.getBytes());
+ _output_.write(_COMMAND_SE);
+ _output_.flush();
+ }
+ }
+
+ /* TERMINAL-TYPE option (end)*/
+
+ /* open TelnetOptionHandler functionality (start)*/
+ /**
+ * Manages subnegotiation for Terminal Type.
+ *
+ * @param subn - subnegotiation data to be sent
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendSubnegotiation(int subn[])
+ throws IOException
+ {
+ if (debug)
+ {
+ System.err.println("SEND SUBNEGOTIATION: ");
+ if (subn != null)
+ {
+ for (int ii = 0; ii < subn.length; ii++)
+ {
+ System.err.println("subn[" + ii + "]=" + subn[ii]);
+ }
+ }
+ }
+ if (subn != null)
+ {
+ byte byteresp[] = new byte[subn.length];
+ for (int ii = 0; ii < subn.length; ii++)
+ {
+ byteresp[ii] = (byte) subn[ii];
+ }
+
+ _output_.write(_COMMAND_SB);
+ _output_.write(byteresp);
+ _output_.write(_COMMAND_SE);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /* Code Section added for supporting AYT (start)*/
+ /***
+ * Processes the response of an AYT
+ ***/
+ final synchronized void _processAYTResponse()
+ {
+ if (!aytFlag)
+ {
+ synchronized (aytMonitor)
+ {
+ aytFlag = true;
+ try
+ {
+ aytMonitor.notifyAll();
+ }
+ catch (IllegalMonitorStateException e)
+ {
+ System.err.println("Exception notifying:" + e.getMessage());
+ }
+ }
+ }
+ }
+ /* Code Section added for supporting AYT (end)*/
+
+ /***
+ * Called upon connection.
+ * <p>
+ * @throws IOException - Exception in I/O.
+ ***/
+ @Override
+ protected void _connectAction_() throws IOException
+ {
+ /* (start). BUGFIX: clean the option info for each connection*/
+ for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++)
+ {
+ _doResponse[ii] = 0;
+ _willResponse[ii] = 0;
+ _options[ii] = 0;
+ if (optionHandlers[ii] != null)
+ {
+ optionHandlers[ii].setDo(false);
+ optionHandlers[ii].setWill(false);
+ }
+ }
+ /* (end). BUGFIX: clean the option info for each connection*/
+
+ super._connectAction_();
+ _input_ = new BufferedInputStream(_input_);
+ _output_ = new BufferedOutputStream(_output_);
+
+ /* open TelnetOptionHandler functionality (start)*/
+ for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++)
+ {
+ if (optionHandlers[ii] != null)
+ {
+ if (optionHandlers[ii].getInitLocal())
+ {
+ try
+ {
+ _requestWill(optionHandlers[ii].getOptionCode());
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while initializing option: "
+ + e.getMessage());
+ }
+ }
+
+ if (optionHandlers[ii].getInitRemote())
+ {
+ try
+ {
+ _requestDo(optionHandlers[ii].getOptionCode());
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while initializing option: "
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /**
+ * Sends a DO.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendDo(int option)
+ throws IOException
+ {
+ if (debug || debugoptions)
+ {
+ System.err.println("DO: " + TelnetOption.getOption(option));
+ }
+ _output_.write(_COMMAND_DO);
+ _output_.write(option);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+
+ /**
+ * Requests a DO.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _requestDo(int option)
+ throws IOException
+ {
+ if ((_doResponse[option] == 0 && _stateIsDo(option))
+ || _requestedDo(option))
+ {
+ return ;
+ }
+ _setWantDo(option);
+ ++_doResponse[option];
+ _sendDo(option);
+ }
+
+ /**
+ * Sends a DONT.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendDont(int option)
+ throws IOException
+ {
+ if (debug || debugoptions)
+ {
+ System.err.println("DONT: " + TelnetOption.getOption(option));
+ }
+ _output_.write(_COMMAND_DONT);
+ _output_.write(option);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+
+ /**
+ * Requests a DONT.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _requestDont(int option)
+ throws IOException
+ {
+ if ((_doResponse[option] == 0 && _stateIsDont(option))
+ || _requestedDont(option))
+ {
+ return ;
+ }
+ _setWantDont(option);
+ ++_doResponse[option];
+ _sendDont(option);
+ }
+
+
+ /**
+ * Sends a WILL.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendWill(int option)
+ throws IOException
+ {
+ if (debug || debugoptions)
+ {
+ System.err.println("WILL: " + TelnetOption.getOption(option));
+ }
+ _output_.write(_COMMAND_WILL);
+ _output_.write(option);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+
+ /**
+ * Requests a WILL.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _requestWill(int option)
+ throws IOException
+ {
+ if ((_willResponse[option] == 0 && _stateIsWill(option))
+ || _requestedWill(option))
+ {
+ return ;
+ }
+ _setWantWill(option);
+ ++_doResponse[option];
+ _sendWill(option);
+ }
+
+ /**
+ * Sends a WONT.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendWont(int option)
+ throws IOException
+ {
+ if (debug || debugoptions)
+ {
+ System.err.println("WONT: " + TelnetOption.getOption(option));
+ }
+ _output_.write(_COMMAND_WONT);
+ _output_.write(option);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+
+ /**
+ * Requests a WONT.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _requestWont(int option)
+ throws IOException
+ {
+ if ((_willResponse[option] == 0 && _stateIsWont(option))
+ || _requestedWont(option))
+ {
+ return ;
+ }
+ _setWantWont(option);
+ ++_doResponse[option];
+ _sendWont(option);
+ }
+
+ /**
+ * Sends a byte.
+ *
+ * @param b - byte to send
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendByte(int b)
+ throws IOException
+ {
+ _output_.write(b);
+
+ /* Code Section added for supporting spystreams (start)*/
+ _spyWrite(b);
+ /* Code Section added for supporting spystreams (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.)
+ * @throws IOException - Exception in I/O.
+ * @throws IllegalArgumentException - Illegal argument
+ * @throws InterruptedException - Interrupted during wait.
+ * @return true if AYT received a response, false otherwise
+ **/
+ final boolean _sendAYT(long timeout)
+ throws IOException, IllegalArgumentException, InterruptedException
+ {
+ boolean retValue = false;
+ synchronized (aytMonitor)
+ {
+ synchronized (this)
+ {
+ aytFlag = false;
+ _output_.write(_COMMAND_AYT);
+ _output_.flush();
+ }
+
+ try
+ {
+ aytMonitor.wait(timeout);
+ if (aytFlag == false)
+ {
+ retValue = false;
+ aytFlag = true;
+ }
+ else
+ {
+ retValue = true;
+ }
+ }
+ catch (IllegalMonitorStateException e)
+ {
+ System.err.println("Exception processing AYT:"
+ + e.getMessage());
+ }
+ }
+
+ return (retValue);
+ }
+ /* Code Section added for supporting AYT (end)*/
+
+ /* open TelnetOptionHandler functionality (start)*/
+
+ /**
+ * Registers a new TelnetOptionHandler for this telnet to use.
+ *
+ * @param opthand - option handler to be registered.
+ * @throws InvalidTelnetOptionException - The option code is invalid.
+ **/
+ void addOptionHandler(TelnetOptionHandler opthand)
+ throws InvalidTelnetOptionException
+ {
+ int optcode = opthand.getOptionCode();
+ if (TelnetOption.isValidOption(optcode))
+ {
+ if (optionHandlers[optcode] == null)
+ {
+ optionHandlers[optcode] = opthand;
+ if (isConnected())
+ {
+ if (opthand.getInitLocal())
+ {
+ try
+ {
+ _requestWill(optcode);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while initializing option: "
+ + e.getMessage());
+ }
+ }
+
+ if (opthand.getInitRemote())
+ {
+ try
+ {
+ _requestDo(optcode);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while initializing option: "
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ else
+ {
+ throw (new InvalidTelnetOptionException(
+ "Already registered option", optcode));
+ }
+ }
+ else
+ {
+ throw (new InvalidTelnetOptionException(
+ "Invalid Option Code", optcode));
+ }
+ }
+
+ /**
+ * Unregisters a TelnetOptionHandler.
+ *
+ * @param optcode - Code of the option to be unregistered.
+ * @throws InvalidTelnetOptionException - The option code is invalid.
+ **/
+ void deleteOptionHandler(int optcode)
+ throws InvalidTelnetOptionException
+ {
+ if (TelnetOption.isValidOption(optcode))
+ {
+ if (optionHandlers[optcode] == null)
+ {
+ throw (new InvalidTelnetOptionException(
+ "Unregistered option", optcode));
+ }
+ else
+ {
+ TelnetOptionHandler opthand = optionHandlers[optcode];
+ optionHandlers[optcode] = null;
+
+ if (opthand.getWill())
+ {
+ try
+ {
+ _requestWont(optcode);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while turning off option: "
+ + e.getMessage());
+ }
+ }
+
+ if (opthand.getDo())
+ {
+ try
+ {
+ _requestDont(optcode);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while turning off option: "
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ else
+ {
+ throw (new InvalidTelnetOptionException(
+ "Invalid Option Code", optcode));
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /* Code Section added for supporting spystreams (start)*/
+ /***
+ * Registers an OutputStream for spying what's going on in
+ * the Telnet session.
+ * <p>
+ * @param spystream - OutputStream on which session activity
+ * will be echoed.
+ ***/
+ void _registerSpyStream(OutputStream spystream)
+ {
+ spyStream = spystream;
+ }
+
+ /***
+ * Stops spying this Telnet.
+ * <p>
+ ***/
+ void _stopSpyStream()
+ {
+ spyStream = null;
+ }
+
+ /***
+ * Sends a read char on the spy stream.
+ * <p>
+ * @param ch - character read from the session
+ ***/
+ void _spyRead(int ch)
+ {
+ if (spyStream != null)
+ {
+ try
+ {
+ if (ch != '\r')
+ {
+ spyStream.write(ch);
+ if (ch == '\n')
+ {
+ spyStream.write('\r');
+ }
+ spyStream.flush();
+ }
+ }
+ catch (IOException e)
+ {
+ spyStream = null;
+ }
+ }
+ }
+
+ /***
+ * Sends a written char on the spy stream.
+ * <p>
+ * @param ch - character written to the session
+ ***/
+ void _spyWrite(int ch)
+ {
+ if (!(_stateIsDo(TelnetOption.ECHO)
+ && _requestedDo(TelnetOption.ECHO)))
+ {
+ if (spyStream != null)
+ {
+ try
+ {
+ spyStream.write(ch);
+ spyStream.flush();
+ }
+ catch (IOException e)
+ {
+ spyStream = null;
+ }
+ }
+ }
+ }
+ /* Code Section added for supporting spystreams (end)*/
+
+ /***
+ * Registers a notification handler to which will be sent
+ * notifications of received telnet option negotiation commands.
+ * <p>
+ * @param notifhand - TelnetNotificationHandler to be registered
+ ***/
+ public void registerNotifHandler(TelnetNotificationHandler notifhand)
+ {
+ __notifhand = notifhand;
+ }
+
+ /***
+ * Unregisters the current notification handler.
+ * <p>
+ ***/
+ public void unregisterNotifHandler()
+ {
+ __notifhand = null;
+ }
+}