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 + -
显示快捷键?