telnetinputstream.java

来自「j2me学习 简单例子」· Java 代码 · 共 254 行

JAVA
254
字号
/* License
 * 
 * Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  
 *  * Redistribution of source code must retain the above copyright notice,
 *	this list of conditions and the following disclaimer.
 * 
 *  * Redistribution in binary form must reproduce the above copyright notice,
 *	this list of conditions and the following disclaimer in the
 *	documentation and/or other materials provided with the distribution.
 * 
 * Neither the name of Sun Microsystems, Inc. or the names of contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *  
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *  
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility. 
 */

 //package net.mpowers.telnet;
package example.term.telnetui;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

/**
* A minimal telnet protocol filter that handles only
* TERMINAL_TYPE and NAWS (window size) options.
*/
public class TelnetInputStream extends InputStream
{
    private InputStream input;
    private OutputStream output;
    private int width, height;
    private String terminal;
    
    // used for replies
    private final byte[] reply = { IAC, (byte) 0, (byte) 0 };
    
    /**
    * Constructor specifying the input stream to filter,
    * and the output stream with which the telnet protocol
    * is negotiated.
    */
    public TelnetInputStream( 
        InputStream inInput, OutputStream inOutput )
    {
        this( inInput, inOutput, 0, 0, null );
    }
    
    /**
    * Constructor specifying the input stream to filter,
    * the output stream with which the telnet protocol
    * is negotiated, and terminal emulation settings.
    */
    public TelnetInputStream( 
        InputStream inInput, OutputStream inOutput,
        int inWidth, int inHeight, String inTermType )
    {
        input = inInput;
        output = inOutput;
        width = inWidth;
        height = inHeight;
        terminal = inTermType;
        if ( terminal == null ) terminal = "dumb";
    }
    
    public int read() throws IOException
    {
        byte b;
        
        b = (byte) input.read();
        if ( b != IAC ) return b; // not an IAC, skip.
        
        b = (byte) input.read();
        if ( b == IAC ) return b; // two IACs isn't.
        
        if ( b != SB ) // handle command
        {
            switch ( b )
            {
                // basic commands
                case   GA:
                case  NOP:
                case  DAT:
                case  BRK:
                case   IP:
                case   AO:
                case  AYT:
                case   EC:
                case   EL:
                    // not implemented: ignore for now
                    System.err.println( 
                        "Ignored command: " + b + " : " + reply[2] );
                    return read();
                    
                // option prefixes
                case   DO:
                case DONT:
                case WILL:
                case WONT:
                    // read next byte to determine option
                    reply[2] = (byte) input.read();
                    switch ( reply[2] )
                    {
                        case TERMINAL_TYPE:
                            // do allow terminal type subnegotiation
                            if ( b == DO )
                            {
                                reply[1] = WILL;
                                write( reply );
                                break;
                            }
                        
                        case WINDOW_SIZE:
                            // do allow and reply with window size
                            if ( b == DO && width > 0 && height > 0 )
                            {
                                reply[1] = WILL;
                                write( reply );
                                reply[1] = SB;
                                write( reply );
                                byte[] bytes = new byte[6];
                                bytes[0] = (byte) (width >> 8);
                                bytes[1] = (byte) (width & 0xff);
                                bytes[2] = (byte) (height >> 8);
                                bytes[3] = (byte) (height & 0xff);
                                bytes[4] = IAC;
                                bytes[5] = SE;
                                write( bytes );
                                break;
                            }
                        
                        default:
                            // unsupported option: refuse and break
                            System.err.println( 
                                "Unsupported option: " + b + " : " + reply[2] );
                            reply[1] = WONT;
                            if ( b == WILL )
                            {
                                reply[1] = DONT;
                            }
                            write( reply );
                            break;
                    }
                    break;
                    
                default:
                    // unsupported option: suppress and exit
                    System.err.println( "Unsupported command: " + b );
            }
        }
        else // handle begin-sub
        {
            b = (byte) input.read();
            reply[2] = b;

            switch ( b )
            {
                case TERMINAL_TYPE:
                    if ( (b = (byte) input.read()) != TERMINAL_SEND ) return b;
                    if ( (b = (byte) input.read()) != IAC ) return b;
                    if ( (b = (byte) input.read()) != SE ) return b;
                    reply[1] = SB;
                    write( reply );
                    char[] c = terminal.toCharArray();
                    byte[] bytes = new byte[c.length+3];
                    int i = 0;
                    bytes[i++] = TERMINAL_IS;
                    for ( ; i < c.length+1; i++ ) bytes[i] = (byte) c[i-1];
                    bytes[i++] = IAC;
                    bytes[i++] = SE;
                    write( bytes );
                    break;
                default:
                    reply[1] = WONT;
                    write( reply );
            }
        }
        
        return read();
    }
    
    public void close() throws IOException
    {
        input.close();
    }
    
    private void write( byte inByte ) throws IOException
    {
        output.write( inByte );
        output.flush();
    }
    
    private void write( byte[] inBytes ) throws IOException
    {
        output.write( inBytes );
        output.flush();
    }
    
    // iac commands
    private final static byte SE   = (byte) 240; // -16
    private final static byte NOP  = (byte) 241;
    private final static byte DAT  = (byte) 242;
    private final static byte BRK  = (byte) 243;
    private final static byte IP   = (byte) 244;
    private final static byte AO   = (byte) 245;
    private final static byte AYT  = (byte) 246;
    private final static byte EC   = (byte) 247;
    private final static byte EL   = (byte) 248;
    private final static byte GA   = (byte) 249;
    private final static byte SB   = (byte) 250; // -6
    private final static byte WILL = (byte) 251; // -5
    private final static byte WONT = (byte) 252; // -4
    private final static byte DO   = (byte) 253; // -3
    private final static byte DONT = (byte) 254; // -2
    private final static byte IAC  = (byte) 255; // -1

    // options
    private final static byte TRANSMIT_BINARY = (byte) 0;
    private final static byte ECHO = (byte) 1;
    private final static byte SUPPRESS_GO_AHEAD = (byte) 3;
    private final static byte STATUS = (byte) 5;
    private final static byte TIMING_MARK = (byte) 6;
    private final static byte TERMINAL_TYPE = (byte) 24; 
    private final static byte END_OF_RECORD = (byte) 25; 
    private final static byte WINDOW_SIZE = (byte) 31; 

    // used with END_OF_RECORD
    private final static byte EOR  = (byte) 239;
    
    // used with TERMINAL_TYPE
    private final static byte TERMINAL_IS = (byte) 0; 
    private final static byte TERMINAL_SEND = (byte) 1; 

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?