telnetinputstream.java
来自「apache推出的net包」· Java 代码 · 共 602 行 · 第 1/2 页
JAVA
602 行
/* * Copyright 2003-2004 The Apache Software Foundation * * Licensed 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.IOException;import java.io.InputStream;import java.io.InterruptedIOException;/*** * * <p> * * <p> * <p> * @author Daniel F. Savarese * @author Bruno D'Avanzo ***/final class TelnetInputStream extends BufferedInputStream implements Runnable{ static final int _STATE_DATA = 0, _STATE_IAC = 1, _STATE_WILL = 2, _STATE_WONT = 3, _STATE_DO = 4, _STATE_DONT = 5, _STATE_SB = 6, _STATE_SE = 7, _STATE_CR = 8, _STATE_IAC_SB = 9; private boolean __hasReachedEOF, __isClosed; private boolean __readIsWaiting; private int __receiveState, __queueHead, __queueTail, __bytesAvailable; private int[] __queue; private TelnetClient __client; private Thread __thread; private IOException __ioException; /* TERMINAL-TYPE option (start)*/ private int __suboption[] = new int[256]; private int __suboption_count = 0; /* TERMINAL-TYPE option (end)*/ private boolean __threaded; TelnetInputStream(InputStream input, TelnetClient client, boolean readerThread) { super(input); __client = client; __receiveState = _STATE_DATA; __isClosed = true; __hasReachedEOF = false; // Make it 2049, because when full, one slot will go unused, and we // want a 2048 byte buffer just to have a round number (base 2 that is) __queue = new int[2049]; __queueHead = 0; __queueTail = 0; __bytesAvailable = 0; __ioException = null; __readIsWaiting = false; __threaded = false; if(readerThread) __thread = new Thread(this); else __thread = null; } TelnetInputStream(InputStream input, TelnetClient client) { this(input, client, true); } void _start() { if(__thread == null) return; int priority; __isClosed = false; // Need to set a higher priority in case JVM does not use pre-emptive // threads. This should prevent scheduler induced deadlock (rather than // deadlock caused by a bug in this code). priority = Thread.currentThread().getPriority() + 1; if (priority > Thread.MAX_PRIORITY) priority = Thread.MAX_PRIORITY; __thread.setPriority(priority); __thread.setDaemon(true); __thread.start(); __threaded = true; } // synchronized(__client) critical sections are to protect against // TelnetOutputStream writing through the telnet client at same time // as a processDo/Will/etc. command invoked from TelnetInputStream // tries to write. private int __read() throws IOException { int ch;_loop: while (true) { // Exit only when we reach end of stream. if ((ch = super.read()) < 0) return -1; ch = (ch & 0xff); /* Code Section added for supporting AYT (start)*/ synchronized (__client) { __client._processAYTResponse(); } /* Code Section added for supporting AYT (end)*/ /* Code Section added for supporting spystreams (start)*/ __client._spyRead(ch); /* Code Section added for supporting spystreams (end)*/_mainSwitch: switch (__receiveState) { case _STATE_CR: if (ch == '\0') { // Strip null continue; } // How do we handle newline after cr? // else if (ch == '\n' && _requestedDont(TelnetOption.ECHO) && // Handle as normal data by falling through to _STATE_DATA case case _STATE_DATA: if (ch == TelnetCommand.IAC) { __receiveState = _STATE_IAC; continue; } if (ch == '\r') { synchronized (__client) { if (__client._requestedDont(TelnetOption.BINARY)) __receiveState = _STATE_CR; else __receiveState = _STATE_DATA; } } else __receiveState = _STATE_DATA; break; case _STATE_IAC: switch (ch) { case TelnetCommand.WILL: __receiveState = _STATE_WILL; continue; case TelnetCommand.WONT: __receiveState = _STATE_WONT; continue; case TelnetCommand.DO: __receiveState = _STATE_DO; continue; case TelnetCommand.DONT: __receiveState = _STATE_DONT; continue; /* TERMINAL-TYPE option (start)*/ case TelnetCommand.SB: __suboption_count = 0; __receiveState = _STATE_SB; continue; /* TERMINAL-TYPE option (end)*/ case TelnetCommand.IAC: __receiveState = _STATE_DATA; break; default: break; } __receiveState = _STATE_DATA; continue; case _STATE_WILL: synchronized (__client) { __client._processWill(ch); __client._flushOutputStream(); } __receiveState = _STATE_DATA; continue; case _STATE_WONT: synchronized (__client) { __client._processWont(ch); __client._flushOutputStream(); } __receiveState = _STATE_DATA; continue; case _STATE_DO: synchronized (__client) { __client._processDo(ch); __client._flushOutputStream(); } __receiveState = _STATE_DATA; continue; case _STATE_DONT: synchronized (__client) { __client._processDont(ch); __client._flushOutputStream(); } __receiveState = _STATE_DATA; continue; /* TERMINAL-TYPE option (start)*/ case _STATE_SB: switch (ch) { case TelnetCommand.IAC: __receiveState = _STATE_IAC_SB; continue; default: // store suboption char __suboption[__suboption_count++] = ch; break; } __receiveState = _STATE_SB; continue; case _STATE_IAC_SB: switch (ch) { case TelnetCommand.SE: synchronized (__client) { __client._processSuboption(__suboption, __suboption_count); __client._flushOutputStream(); } __receiveState = _STATE_DATA; continue; default: __receiveState = _STATE_SB; break; } __receiveState = _STATE_DATA; continue; /* TERMINAL-TYPE option (end)*/ } break; } return ch; } // synchronized(__client) critical sections are to protect against // TelnetOutputStream writing through the telnet client at same time // as a processDo/Will/etc. command invoked from TelnetInputStream // tries to write. private void __processChar(int ch) throws InterruptedException { // Critical section because we're altering __bytesAvailable, // __queueTail, and the contents of _queue. synchronized (__queue) { while (__bytesAvailable >= __queue.length - 1) { if(__threaded) { __queue.notify(); try { __queue.wait(); } catch (InterruptedException e) { throw e; } } } // Need to do this in case we're not full, but block on a read if (__readIsWaiting && __threaded) { __queue.notify(); } __queue[__queueTail] = ch; ++__bytesAvailable;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?