0001: /*
0002: * Copyright 2003-2004 The Apache Software Foundation
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.apache.org/licenses/LICENSE-2.0
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */
0016: package org.apache.commons.net.telnet;
0017:
0018: import java.io.BufferedInputStream;
0019: import java.io.BufferedOutputStream;
0020: import java.io.OutputStream;
0021: import java.io.IOException;
0022: import org.apache.commons.net.SocketClient;
0023:
0024: /**
0025: * @author Daniel F. Savarese
0026: * @author Bruno D'Avanzo
0027: */
0028:
0029: class Telnet extends SocketClient {
0030: static final boolean debug = /*true;*/false;
0031:
0032: static final boolean debugoptions = /*true;*/false;
0033:
0034: static final byte[] _COMMAND_DO = { (byte) TelnetCommand.IAC,
0035: (byte) TelnetCommand.DO };
0036:
0037: static final byte[] _COMMAND_DONT = { (byte) TelnetCommand.IAC,
0038: (byte) TelnetCommand.DONT };
0039:
0040: static final byte[] _COMMAND_WILL = { (byte) TelnetCommand.IAC,
0041: (byte) TelnetCommand.WILL };
0042:
0043: static final byte[] _COMMAND_WONT = { (byte) TelnetCommand.IAC,
0044: (byte) TelnetCommand.WONT };
0045:
0046: static final byte[] _COMMAND_SB = { (byte) TelnetCommand.IAC,
0047: (byte) TelnetCommand.SB };
0048:
0049: static final byte[] _COMMAND_SE = { (byte) TelnetCommand.IAC,
0050: (byte) TelnetCommand.SE };
0051:
0052: static final int _WILL_MASK = 0x01, _DO_MASK = 0x02,
0053: _REQUESTED_WILL_MASK = 0x04, _REQUESTED_DO_MASK = 0x08;
0054:
0055: /* public */
0056: static final int DEFAULT_PORT = 23;
0057:
0058: int[] _doResponse, _willResponse, _options;
0059:
0060: /* TERMINAL-TYPE option (start)*/
0061: /***
0062: * Terminal type option
0063: ***/
0064: protected static final int TERMINAL_TYPE = 24;
0065:
0066: /***
0067: * Send (for subnegotiation)
0068: ***/
0069: protected static final int TERMINAL_TYPE_SEND = 1;
0070:
0071: /***
0072: * Is (for subnegotiation)
0073: ***/
0074: protected static final int TERMINAL_TYPE_IS = 0;
0075:
0076: /***
0077: * Is sequence (for subnegotiation)
0078: ***/
0079: static final byte[] _COMMAND_IS = { (byte) TERMINAL_TYPE,
0080: (byte) TERMINAL_TYPE_IS };
0081:
0082: /***
0083: * Terminal type
0084: ***/
0085: private String terminalType = null;
0086: /* TERMINAL-TYPE option (end)*/
0087:
0088: /* open TelnetOptionHandler functionality (start)*/
0089: /***
0090: * Array of option handlers
0091: ***/
0092: private TelnetOptionHandler optionHandlers[];
0093:
0094: /* open TelnetOptionHandler functionality (end)*/
0095:
0096: /* Code Section added for supporting AYT (start)*/
0097: /***
0098: * AYT sequence
0099: ***/
0100: static final byte[] _COMMAND_AYT = { (byte) TelnetCommand.IAC,
0101: (byte) TelnetCommand.AYT };
0102:
0103: /***
0104: * monitor to wait for AYT
0105: ***/
0106: private Object aytMonitor = new Object();
0107:
0108: /***
0109: * flag for AYT
0110: ***/
0111: private boolean aytFlag = true;
0112: /* Code Section added for supporting AYT (end)*/
0113:
0114: /***
0115: * The stream on which to spy
0116: ***/
0117: private OutputStream spyStream = null;
0118:
0119: /***
0120: * The notification handler
0121: ***/
0122: private TelnetNotificationHandler __notifhand = null;
0123:
0124: /***
0125: * Empty Constructor
0126: ***/
0127: Telnet() {
0128: setDefaultPort(DEFAULT_PORT);
0129: _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
0130: _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
0131: _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
0132: optionHandlers = new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
0133: }
0134:
0135: /* TERMINAL-TYPE option (start)*/
0136: /***
0137: * This constructor lets you specify the terminal type.
0138: * <p>
0139: * @param termtype - terminal type to be negotiated (ej. VT100)
0140: ***/
0141: Telnet(String termtype) {
0142: setDefaultPort(DEFAULT_PORT);
0143: _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
0144: _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
0145: _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
0146: terminalType = termtype;
0147: optionHandlers = new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
0148: }
0149:
0150: /* TERMINAL-TYPE option (end)*/
0151:
0152: /***
0153: * Looks for the state of the option.
0154: * <p>
0155: * @return returns true if a will has been acknowledged
0156: * <p>
0157: * @param option - option code to be looked up.
0158: ***/
0159: boolean _stateIsWill(int option) {
0160: return ((_options[option] & _WILL_MASK) != 0);
0161: }
0162:
0163: /***
0164: * Looks for the state of the option.
0165: * <p>
0166: * @return returns true if a wont has been acknowledged
0167: * <p>
0168: * @param option - option code to be looked up.
0169: ***/
0170: boolean _stateIsWont(int option) {
0171: return !_stateIsWill(option);
0172: }
0173:
0174: /***
0175: * Looks for the state of the option.
0176: * <p>
0177: * @return returns true if a do has been acknowledged
0178: * <p>
0179: * @param option - option code to be looked up.
0180: ***/
0181: boolean _stateIsDo(int option) {
0182: return ((_options[option] & _DO_MASK) != 0);
0183: }
0184:
0185: /***
0186: * Looks for the state of the option.
0187: * <p>
0188: * @return returns true if a dont has been acknowledged
0189: * <p>
0190: * @param option - option code to be looked up.
0191: ***/
0192: boolean _stateIsDont(int option) {
0193: return !_stateIsDo(option);
0194: }
0195:
0196: /***
0197: * Looks for the state of the option.
0198: * <p>
0199: * @return returns true if a will has been reuqested
0200: * <p>
0201: * @param option - option code to be looked up.
0202: ***/
0203: boolean _requestedWill(int option) {
0204: return ((_options[option] & _REQUESTED_WILL_MASK) != 0);
0205: }
0206:
0207: /***
0208: * Looks for the state of the option.
0209: * <p>
0210: * @return returns true if a wont has been reuqested
0211: * <p>
0212: * @param option - option code to be looked up.
0213: ***/
0214: boolean _requestedWont(int option) {
0215: return !_requestedWill(option);
0216: }
0217:
0218: /***
0219: * Looks for the state of the option.
0220: * <p>
0221: * @return returns true if a do has been reuqested
0222: * <p>
0223: * @param option - option code to be looked up.
0224: ***/
0225: boolean _requestedDo(int option) {
0226: return ((_options[option] & _REQUESTED_DO_MASK) != 0);
0227: }
0228:
0229: /***
0230: * Looks for the state of the option.
0231: * <p>
0232: * @return returns true if a dont has been reuqested
0233: * <p>
0234: * @param option - option code to be looked up.
0235: ***/
0236: boolean _requestedDont(int option) {
0237: return !_requestedDo(option);
0238: }
0239:
0240: /***
0241: * Sets the state of the option.
0242: * <p>
0243: * @param option - option code to be set.
0244: ***/
0245: void _setWill(int option) {
0246: _options[option] |= _WILL_MASK;
0247:
0248: /* open TelnetOptionHandler functionality (start)*/
0249: if (_requestedWill(option)) {
0250: if (optionHandlers[option] != null) {
0251: optionHandlers[option].setWill(true);
0252:
0253: int subneg[] = optionHandlers[option]
0254: .startSubnegotiationLocal();
0255:
0256: if (subneg != null) {
0257: try {
0258: _sendSubnegotiation(subneg);
0259: } catch (Exception e) {
0260: System.err
0261: .println("Exception in option subnegotiation"
0262: + e.getMessage());
0263: }
0264: }
0265: }
0266: }
0267: /* open TelnetOptionHandler functionality (end)*/
0268: }
0269:
0270: /***
0271: * Sets the state of the option.
0272: * <p>
0273: * @param option - option code to be set.
0274: ***/
0275: void _setDo(int option) {
0276: _options[option] |= _DO_MASK;
0277:
0278: /* open TelnetOptionHandler functionality (start)*/
0279: if (_requestedDo(option)) {
0280: if (optionHandlers[option] != null) {
0281: optionHandlers[option].setDo(true);
0282:
0283: int subneg[] = optionHandlers[option]
0284: .startSubnegotiationRemote();
0285:
0286: if (subneg != null) {
0287: try {
0288: _sendSubnegotiation(subneg);
0289: } catch (Exception e) {
0290: System.err
0291: .println("Exception in option subnegotiation"
0292: + e.getMessage());
0293: }
0294: }
0295: }
0296: }
0297: /* open TelnetOptionHandler functionality (end)*/
0298: }
0299:
0300: /***
0301: * Sets the state of the option.
0302: * <p>
0303: * @param option - option code to be set.
0304: ***/
0305: void _setWantWill(int option) {
0306: _options[option] |= _REQUESTED_WILL_MASK;
0307: }
0308:
0309: /***
0310: * Sets the state of the option.
0311: * <p>
0312: * @param option - option code to be set.
0313: ***/
0314: void _setWantDo(int option) {
0315: _options[option] |= _REQUESTED_DO_MASK;
0316: }
0317:
0318: /***
0319: * Sets the state of the option.
0320: * <p>
0321: * @param option - option code to be set.
0322: ***/
0323: void _setWont(int option) {
0324: _options[option] &= ~_WILL_MASK;
0325:
0326: /* open TelnetOptionHandler functionality (start)*/
0327: if (optionHandlers[option] != null) {
0328: optionHandlers[option].setWill(false);
0329: }
0330: /* open TelnetOptionHandler functionality (end)*/
0331: }
0332:
0333: /***
0334: * Sets the state of the option.
0335: * <p>
0336: * @param option - option code to be set.
0337: ***/
0338: void _setDont(int option) {
0339: _options[option] &= ~_DO_MASK;
0340:
0341: /* open TelnetOptionHandler functionality (start)*/
0342: if (optionHandlers[option] != null) {
0343: optionHandlers[option].setDo(false);
0344: }
0345: /* open TelnetOptionHandler functionality (end)*/
0346: }
0347:
0348: /***
0349: * Sets the state of the option.
0350: * <p>
0351: * @param option - option code to be set.
0352: ***/
0353: void _setWantWont(int option) {
0354: _options[option] &= ~_REQUESTED_WILL_MASK;
0355: }
0356:
0357: /***
0358: * Sets the state of the option.
0359: * <p>
0360: * @param option - option code to be set.
0361: ***/
0362: void _setWantDont(int option) {
0363: _options[option] &= ~_REQUESTED_DO_MASK;
0364: }
0365:
0366: /***
0367: * Processes a DO request.
0368: * <p>
0369: * @throws IOException - Exception in I/O.
0370: * <p>
0371: * @param option - option code to be set.
0372: ***/
0373: void _processDo(int option) throws IOException {
0374: if (debugoptions) {
0375: System.err.println("RECEIVED DO: "
0376: + TelnetOption.getOption(option));
0377: }
0378:
0379: if (__notifhand != null) {
0380: __notifhand.receivedNegotiation(
0381: TelnetNotificationHandler.RECEIVED_DO, option);
0382: }
0383:
0384: boolean acceptNewState = false;
0385:
0386: /* open TelnetOptionHandler functionality (start)*/
0387: if (optionHandlers[option] != null) {
0388: acceptNewState = optionHandlers[option].getAcceptLocal();
0389: } else {
0390: /* open TelnetOptionHandler functionality (end)*/
0391: /* TERMINAL-TYPE option (start)*/
0392: if (option == TERMINAL_TYPE) {
0393: if ((terminalType != null)
0394: && (terminalType.length() > 0)) {
0395: acceptNewState = true;
0396: }
0397: }
0398: /* TERMINAL-TYPE option (end)*/
0399: /* open TelnetOptionHandler functionality (start)*/
0400: }
0401: /* open TelnetOptionHandler functionality (end)*/
0402:
0403: if (_willResponse[option] > 0) {
0404: --_willResponse[option];
0405: if (_willResponse[option] > 0 && _stateIsWill(option)) {
0406: --_willResponse[option];
0407: }
0408: }
0409:
0410: if (_willResponse[option] == 0) {
0411: if (_requestedWont(option)) {
0412:
0413: switch (option) {
0414:
0415: default:
0416: break;
0417:
0418: }
0419:
0420: if (acceptNewState) {
0421: _setWantWill(option);
0422: _sendWill(option);
0423: } else {
0424: ++_willResponse[option];
0425: _sendWont(option);
0426: }
0427: } else {
0428: // Other end has acknowledged option.
0429:
0430: switch (option) {
0431:
0432: default:
0433: break;
0434:
0435: }
0436:
0437: }
0438: }
0439:
0440: _setWill(option);
0441: }
0442:
0443: /***
0444: * Processes a DONT request.
0445: * <p>
0446: * @throws IOException - Exception in I/O.
0447: * <p>
0448: * @param option - option code to be set.
0449: ***/
0450: void _processDont(int option) throws IOException {
0451: if (debugoptions) {
0452: System.err.println("RECEIVED DONT: "
0453: + TelnetOption.getOption(option));
0454: }
0455: if (__notifhand != null) {
0456: __notifhand.receivedNegotiation(
0457: TelnetNotificationHandler.RECEIVED_DONT, option);
0458: }
0459: if (_willResponse[option] > 0) {
0460: --_willResponse[option];
0461: if (_willResponse[option] > 0 && _stateIsWont(option)) {
0462: --_willResponse[option];
0463: }
0464: }
0465:
0466: if (_willResponse[option] == 0 && _requestedWill(option)) {
0467:
0468: switch (option) {
0469:
0470: default:
0471: break;
0472:
0473: }
0474:
0475: /* FIX for a BUG in the negotiation (start)*/
0476: if ((_stateIsWill(option)) || (_requestedWill(option))) {
0477: _sendWont(option);
0478: }
0479:
0480: _setWantWont(option);
0481: /* FIX for a BUG in the negotiation (end)*/
0482: }
0483:
0484: _setWont(option);
0485: }
0486:
0487: /***
0488: * Processes a WILL request.
0489: * <p>
0490: * @throws IOException - Exception in I/O.
0491: * <p>
0492: * @param option - option code to be set.
0493: ***/
0494: void _processWill(int option) throws IOException {
0495: if (debugoptions) {
0496: System.err.println("RECEIVED WILL: "
0497: + TelnetOption.getOption(option));
0498: }
0499:
0500: if (__notifhand != null) {
0501: __notifhand.receivedNegotiation(
0502: TelnetNotificationHandler.RECEIVED_WILL, option);
0503: }
0504:
0505: boolean acceptNewState = false;
0506:
0507: /* open TelnetOptionHandler functionality (start)*/
0508: if (optionHandlers[option] != null) {
0509: acceptNewState = optionHandlers[option].getAcceptRemote();
0510: }
0511: /* open TelnetOptionHandler functionality (end)*/
0512:
0513: if (_doResponse[option] > 0) {
0514: --_doResponse[option];
0515: if (_doResponse[option] > 0 && _stateIsDo(option)) {
0516: --_doResponse[option];
0517: }
0518: }
0519:
0520: if (_doResponse[option] == 0 && _requestedDont(option)) {
0521:
0522: switch (option) {
0523:
0524: default:
0525: break;
0526:
0527: }
0528:
0529: if (acceptNewState) {
0530: _setWantDo(option);
0531: _sendDo(option);
0532: } else {
0533: ++_doResponse[option];
0534: _sendDont(option);
0535: }
0536: }
0537:
0538: _setDo(option);
0539: }
0540:
0541: /***
0542: * Processes a WONT request.
0543: * <p>
0544: * @throws IOException - Exception in I/O.
0545: * <p>
0546: * @param option - option code to be set.
0547: ***/
0548: void _processWont(int option) throws IOException {
0549: if (debugoptions) {
0550: System.err.println("RECEIVED WONT: "
0551: + TelnetOption.getOption(option));
0552: }
0553:
0554: if (__notifhand != null) {
0555: __notifhand.receivedNegotiation(
0556: TelnetNotificationHandler.RECEIVED_WONT, option);
0557: }
0558:
0559: if (_doResponse[option] > 0) {
0560: --_doResponse[option];
0561: if (_doResponse[option] > 0 && _stateIsDont(option)) {
0562: --_doResponse[option];
0563: }
0564: }
0565:
0566: if (_doResponse[option] == 0 && _requestedDo(option)) {
0567:
0568: switch (option) {
0569:
0570: default:
0571: break;
0572:
0573: }
0574:
0575: /* FIX for a BUG in the negotiation (start)*/
0576: if ((_stateIsDo(option)) || (_requestedDo(option))) {
0577: _sendDont(option);
0578: }
0579:
0580: _setWantDont(option);
0581: /* FIX for a BUG in the negotiation (end)*/
0582: }
0583:
0584: _setDont(option);
0585: }
0586:
0587: /* TERMINAL-TYPE option (start)*/
0588: /***
0589: * Processes a suboption negotiation.
0590: * <p>
0591: * @throws IOException - Exception in I/O.
0592: * <p>
0593: * @param suboption - subnegotiation data received
0594: * @param suboptionLength - length of data received
0595: ***/
0596: void _processSuboption(int suboption[], int suboptionLength)
0597: throws IOException {
0598: if (debug) {
0599: System.err.println("PROCESS SUBOPTION.");
0600: }
0601:
0602: /* open TelnetOptionHandler functionality (start)*/
0603: if (suboptionLength > 0) {
0604: if (optionHandlers[suboption[0]] != null) {
0605: int responseSuboption[] = optionHandlers[suboption[0]]
0606: .answerSubnegotiation(suboption,
0607: suboptionLength);
0608: _sendSubnegotiation(responseSuboption);
0609: } else {
0610: if (suboptionLength > 1) {
0611: if (debug) {
0612: for (int ii = 0; ii < suboptionLength; ii++) {
0613: System.err.println("SUB[" + ii + "]: "
0614: + suboption[ii]);
0615: }
0616: }
0617: if ((suboption[0] == TERMINAL_TYPE)
0618: && (suboption[1] == TERMINAL_TYPE_SEND)) {
0619: _sendTerminalType();
0620: }
0621: }
0622: }
0623: }
0624: /* open TelnetOptionHandler functionality (end)*/
0625: }
0626:
0627: /***
0628: * Sends terminal type information.
0629: * <p>
0630: * @throws IOException - Exception in I/O.
0631: ***/
0632: final synchronized void _sendTerminalType() throws IOException {
0633: if (debug) {
0634: System.err.println("SEND TERMINAL-TYPE: " + terminalType);
0635: }
0636: if (terminalType != null) {
0637: _output_.write(_COMMAND_SB);
0638: _output_.write(_COMMAND_IS);
0639: _output_.write(terminalType.getBytes());
0640: _output_.write(_COMMAND_SE);
0641: _output_.flush();
0642: }
0643: }
0644:
0645: /* TERMINAL-TYPE option (end)*/
0646:
0647: /* open TelnetOptionHandler functionality (start)*/
0648: /***
0649: * Manages subnegotiation for Terminal Type.
0650: * <p>
0651: * @throws IOException - Exception in I/O.
0652: * <p>
0653: * @param subn - subnegotiation data to be sent
0654: ***/
0655: final synchronized void _sendSubnegotiation(int subn[])
0656: throws IOException {
0657: if (debug) {
0658: System.err.println("SEND SUBNEGOTIATION: ");
0659: if (subn != null) {
0660: for (int ii = 0; ii < subn.length; ii++) {
0661: System.err.println("subn[" + ii + "]=" + subn[ii]);
0662: }
0663: }
0664: }
0665: if (subn != null) {
0666: byte byteresp[] = new byte[subn.length];
0667: for (int ii = 0; ii < subn.length; ii++) {
0668: byteresp[ii] = (byte) subn[ii];
0669: }
0670:
0671: _output_.write(_COMMAND_SB);
0672: _output_.write(byteresp);
0673: _output_.write(_COMMAND_SE);
0674:
0675: /* Code Section added for sending the negotiation ASAP (start)*/
0676: _output_.flush();
0677: /* Code Section added for sending the negotiation ASAP (end)*/
0678: }
0679: }
0680:
0681: /* open TelnetOptionHandler functionality (end)*/
0682:
0683: /* Code Section added for supporting AYT (start)*/
0684: /***
0685: * Processes the response of an AYT
0686: ***/
0687: final synchronized void _processAYTResponse() {
0688: if (!aytFlag) {
0689: synchronized (aytMonitor) {
0690: aytFlag = true;
0691: try {
0692: aytMonitor.notifyAll();
0693: } catch (Exception e) {
0694: System.err.println("Exception notifying:"
0695: + e.getMessage());
0696: }
0697: }
0698: }
0699: }
0700:
0701: /* Code Section added for supporting AYT (end)*/
0702:
0703: /***
0704: * Called upon connection.
0705: * <p>
0706: * @throws IOException - Exception in I/O.
0707: ***/
0708: protected void _connectAction_() throws IOException {
0709: /* (start). BUGFIX: clean the option info for each connection*/
0710: for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++) {
0711: _doResponse[ii] = 0;
0712: _willResponse[ii] = 0;
0713: _options[ii] = 0;
0714: if (optionHandlers[ii] != null) {
0715: optionHandlers[ii].setDo(false);
0716: optionHandlers[ii].setWill(false);
0717: }
0718: }
0719: /* (end). BUGFIX: clean the option info for each connection*/
0720:
0721: super ._connectAction_();
0722: _input_ = new BufferedInputStream(_input_);
0723: _output_ = new BufferedOutputStream(_output_);
0724:
0725: /* open TelnetOptionHandler functionality (start)*/
0726: for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++) {
0727: if (optionHandlers[ii] != null) {
0728: if (optionHandlers[ii].getInitLocal()) {
0729: try {
0730: _requestWill(optionHandlers[ii].getOptionCode());
0731: } catch (IOException e) {
0732: System.err
0733: .println("Exception while initializing option: "
0734: + e.getMessage());
0735: }
0736: }
0737:
0738: if (optionHandlers[ii].getInitRemote()) {
0739: try {
0740: _requestDo(optionHandlers[ii].getOptionCode());
0741: } catch (IOException e) {
0742: System.err
0743: .println("Exception while initializing option: "
0744: + e.getMessage());
0745: }
0746: }
0747: }
0748: }
0749: /* open TelnetOptionHandler functionality (end)*/
0750: }
0751:
0752: /***
0753: * Sends a DO.
0754: * <p>
0755: * @throws IOException - Exception in I/O.
0756: * <p>
0757: * @param option - Option code.
0758: ***/
0759: final synchronized void _sendDo(int option) throws IOException {
0760: if (debug || debugoptions) {
0761: System.err.println("DO: " + TelnetOption.getOption(option));
0762: }
0763: _output_.write(_COMMAND_DO);
0764: _output_.write(option);
0765:
0766: /* Code Section added for sending the negotiation ASAP (start)*/
0767: _output_.flush();
0768: /* Code Section added for sending the negotiation ASAP (end)*/
0769: }
0770:
0771: /***
0772: * Requests a DO.
0773: * <p>
0774: * @throws IOException - Exception in I/O.
0775: * <p>
0776: * @param option - Option code.
0777: ***/
0778: final synchronized void _requestDo(int option) throws IOException {
0779: if ((_doResponse[option] == 0 && _stateIsDo(option))
0780: || _requestedDo(option)) {
0781: return;
0782: }
0783: _setWantDo(option);
0784: ++_doResponse[option];
0785: _sendDo(option);
0786: }
0787:
0788: /***
0789: * Sends a DONT.
0790: * <p>
0791: * @throws IOException - Exception in I/O.
0792: * <p>
0793: * @param option - Option code.
0794: ***/
0795: final synchronized void _sendDont(int option) throws IOException {
0796: if (debug || debugoptions) {
0797: System.err.println("DONT: "
0798: + TelnetOption.getOption(option));
0799: }
0800: _output_.write(_COMMAND_DONT);
0801: _output_.write(option);
0802:
0803: /* Code Section added for sending the negotiation ASAP (start)*/
0804: _output_.flush();
0805: /* Code Section added for sending the negotiation ASAP (end)*/
0806: }
0807:
0808: /***
0809: * Requests a DONT.
0810: * <p>
0811: * @throws IOException - Exception in I/O.
0812: * <p>
0813: * @param option - Option code.
0814: ***/
0815: final synchronized void _requestDont(int option) throws IOException {
0816: if ((_doResponse[option] == 0 && _stateIsDont(option))
0817: || _requestedDont(option)) {
0818: return;
0819: }
0820: _setWantDont(option);
0821: ++_doResponse[option];
0822: _sendDont(option);
0823: }
0824:
0825: /***
0826: * Sends a WILL.
0827: * <p>
0828: * @throws IOException - Exception in I/O.
0829: * <p>
0830: * @param option - Option code.
0831: ***/
0832: final synchronized void _sendWill(int option) throws IOException {
0833: if (debug || debugoptions) {
0834: System.err.println("WILL: "
0835: + TelnetOption.getOption(option));
0836: }
0837: _output_.write(_COMMAND_WILL);
0838: _output_.write(option);
0839:
0840: /* Code Section added for sending the negotiation ASAP (start)*/
0841: _output_.flush();
0842: /* Code Section added for sending the negotiation ASAP (end)*/
0843: }
0844:
0845: /***
0846: * Requests a WILL.
0847: * <p>
0848: * @throws IOException - Exception in I/O.
0849: * <p>
0850: * @param option - Option code.
0851: ***/
0852: final synchronized void _requestWill(int option) throws IOException {
0853: if ((_willResponse[option] == 0 && _stateIsWill(option))
0854: || _requestedWill(option)) {
0855: return;
0856: }
0857: _setWantWill(option);
0858: ++_doResponse[option];
0859: _sendWill(option);
0860: }
0861:
0862: /***
0863: * Sends a WONT.
0864: * <p>
0865: * @throws IOException - Exception in I/O.
0866: * <p>
0867: * @param option - Option code.
0868: ***/
0869: final synchronized void _sendWont(int option) throws IOException {
0870: if (debug || debugoptions) {
0871: System.err.println("WONT: "
0872: + TelnetOption.getOption(option));
0873: }
0874: _output_.write(_COMMAND_WONT);
0875: _output_.write(option);
0876:
0877: /* Code Section added for sending the negotiation ASAP (start)*/
0878: _output_.flush();
0879: /* Code Section added for sending the negotiation ASAP (end)*/
0880: }
0881:
0882: /***
0883: * Requests a WONT.
0884: * <p>
0885: * @throws IOException - Exception in I/O.
0886: * <p>
0887: * @param option - Option code.
0888: ***/
0889: final synchronized void _requestWont(int option) throws IOException {
0890: if ((_willResponse[option] == 0 && _stateIsWont(option))
0891: || _requestedWont(option)) {
0892: return;
0893: }
0894: _setWantWont(option);
0895: ++_doResponse[option];
0896: _sendWont(option);
0897: }
0898:
0899: /***
0900: * Sends a byte.
0901: * <p>
0902: * @throws IOException - Exception in I/O.
0903: * <p>
0904: * @param b - byte to send
0905: ***/
0906: final synchronized void _sendByte(int b) throws IOException {
0907: _output_.write(b);
0908:
0909: /* Code Section added for supporting spystreams (start)*/
0910: _spyWrite(b);
0911: /* Code Section added for supporting spystreams (end)*/
0912:
0913: }
0914:
0915: /* Code Section added for supporting AYT (start)*/
0916: /***
0917: * Sends an Are You There sequence and waits for the result.
0918: * <p>
0919: * @throws IOException - Exception in I/O.
0920: * @throws IllegalArgumentException - Illegal argument
0921: * @throws InterruptedException - Interrupted during wait.
0922: * <p>
0923: * @param timeout - Time to wait for a response (millis.)
0924: * <p>
0925: * @return true if AYT received a response, false otherwise
0926: ***/
0927: final boolean _sendAYT(long timeout) throws IOException,
0928: IllegalArgumentException, InterruptedException {
0929: boolean retValue = false;
0930: synchronized (aytMonitor) {
0931: synchronized (this ) {
0932: aytFlag = false;
0933: _output_.write(_COMMAND_AYT);
0934: _output_.flush();
0935: }
0936:
0937: try {
0938: aytMonitor.wait(timeout);
0939: if (aytFlag == false) {
0940: retValue = false;
0941: aytFlag = true;
0942: } else {
0943: retValue = true;
0944: }
0945: } catch (IllegalMonitorStateException e) {
0946: System.err.println("Exception processing AYT:"
0947: + e.getMessage());
0948: }
0949: }
0950:
0951: return (retValue);
0952: }
0953:
0954: /* Code Section added for supporting AYT (end)*/
0955:
0956: /* open TelnetOptionHandler functionality (start)*/
0957:
0958: /***
0959: * Registers a new TelnetOptionHandler for this telnet to use.
0960: * <p>
0961: * @throws InvalidTelnetOptionException - The option code is invalid.
0962: * <p>
0963: * @param opthand - option handler to be registered.
0964: ***/
0965: void addOptionHandler(TelnetOptionHandler opthand)
0966: throws InvalidTelnetOptionException {
0967: int optcode = opthand.getOptionCode();
0968: if (TelnetOption.isValidOption(optcode)) {
0969: if (optionHandlers[optcode] == null) {
0970: optionHandlers[optcode] = opthand;
0971: if (isConnected()) {
0972: if (opthand.getInitLocal()) {
0973: try {
0974: _requestWill(optcode);
0975: } catch (IOException e) {
0976: System.err
0977: .println("Exception while initializing option: "
0978: + e.getMessage());
0979: }
0980: }
0981:
0982: if (opthand.getInitRemote()) {
0983: try {
0984: _requestDo(optcode);
0985: } catch (IOException e) {
0986: System.err
0987: .println("Exception while initializing option: "
0988: + e.getMessage());
0989: }
0990: }
0991: }
0992: } else {
0993: throw (new InvalidTelnetOptionException(
0994: "Already registered option", optcode));
0995: }
0996: } else {
0997: throw (new InvalidTelnetOptionException(
0998: "Invalid Option Code", optcode));
0999: }
1000: }
1001:
1002: /***
1003: * Unregisters a TelnetOptionHandler.
1004: * <p>
1005: * @throws InvalidTelnetOptionException - The option code is invalid.
1006: * <p>
1007: * @param optcode - Code of the option to be unregistered.
1008: ***/
1009: void deleteOptionHandler(int optcode)
1010: throws InvalidTelnetOptionException {
1011: if (TelnetOption.isValidOption(optcode)) {
1012: if (optionHandlers[optcode] == null) {
1013: throw (new InvalidTelnetOptionException(
1014: "Unregistered option", optcode));
1015: } else {
1016: TelnetOptionHandler opthand = optionHandlers[optcode];
1017: optionHandlers[optcode] = null;
1018:
1019: if (opthand.getWill()) {
1020: try {
1021: _requestWont(optcode);
1022: } catch (IOException e) {
1023: System.err
1024: .println("Exception while turning off option: "
1025: + e.getMessage());
1026: }
1027: }
1028:
1029: if (opthand.getDo()) {
1030: try {
1031: _requestDont(optcode);
1032: } catch (IOException e) {
1033: System.err
1034: .println("Exception while turning off option: "
1035: + e.getMessage());
1036: }
1037: }
1038: }
1039: } else {
1040: throw (new InvalidTelnetOptionException(
1041: "Invalid Option Code", optcode));
1042: }
1043: }
1044:
1045: /* open TelnetOptionHandler functionality (end)*/
1046:
1047: /* Code Section added for supporting spystreams (start)*/
1048: /***
1049: * Registers an OutputStream for spying what's going on in
1050: * the Telnet session.
1051: * <p>
1052: * @param spystream - OutputStream on which session activity
1053: * will be echoed.
1054: ***/
1055: void _registerSpyStream(OutputStream spystream) {
1056: spyStream = spystream;
1057: }
1058:
1059: /***
1060: * Stops spying this Telnet.
1061: * <p>
1062: ***/
1063: void _stopSpyStream() {
1064: spyStream = null;
1065: }
1066:
1067: /***
1068: * Sends a read char on the spy stream.
1069: * <p>
1070: * @param ch - character read from the session
1071: ***/
1072: void _spyRead(int ch) {
1073: if (spyStream != null) {
1074: try {
1075: if (ch != (int) '\r') {
1076: spyStream.write(ch);
1077: if (ch == (int) '\n') {
1078: spyStream.write((int) '\r');
1079: }
1080: spyStream.flush();
1081: }
1082: } catch (Exception e) {
1083: spyStream = null;
1084: }
1085: }
1086: }
1087:
1088: /***
1089: * Sends a written char on the spy stream.
1090: * <p>
1091: * @param ch - character written to the session
1092: ***/
1093: void _spyWrite(int ch) {
1094: if (!(_stateIsDo(TelnetOption.ECHO) && _requestedDo(TelnetOption.ECHO))) {
1095: if (spyStream != null) {
1096: try {
1097: spyStream.write(ch);
1098: spyStream.flush();
1099: } catch (Exception e) {
1100: spyStream = null;
1101: }
1102: }
1103: }
1104: }
1105:
1106: /* Code Section added for supporting spystreams (end)*/
1107:
1108: /***
1109: * Registers a notification handler to which will be sent
1110: * notifications of received telnet option negotiation commands.
1111: * <p>
1112: * @param notifhand - TelnetNotificationHandler to be registered
1113: ***/
1114: public void registerNotifHandler(TelnetNotificationHandler notifhand) {
1115: __notifhand = notifhand;
1116: }
1117:
1118: /***
1119: * Unregisters the current notification handler.
1120: * <p>
1121: ***/
1122: public void unregisterNotifHandler() {
1123: __notifhand = null;
1124: }
1125: }
|