| /* |
| * 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; |
| } |
| } |