line source
+ − /*
+ − * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform".
+ − *
+ − * (c) Matthias L. Jugel, Marcus Meißner 1996-2005. All Rights Reserved.
+ − *
+ − * Please visit http://javatelnet.org/ for updates and contact.
+ − *
+ − * --LICENSE NOTICE--
+ − * This program is free software; you can redistribute it and/or
+ − * modify it under the terms of the GNU General Public License
+ − * as published by the Free Software Foundation; either version 2
+ − * of the License, or (at your option) any later version.
+ − *
+ − * This program is distributed in the hope that it will be useful,
+ − * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ − * GNU General Public License for more details.
+ − *
+ − * You should have received a copy of the GNU General Public License
+ − * along with this program; if not, write to the Free Software
+ − * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ − * --LICENSE NOTICE--
+ − *
+ − */
+ −
+ − package de.mud.telnet;
+ −
+ − import java.io.IOException;
+ − /**
+ − * This is a telnet protocol handler. The handler needs implementations
+ − * for several methods to handle the telnet options and to be able to
+ − * read and write the buffer.
+ − * <P>
+ − * <B>Maintainer:</B> Marcus Meissner
+ − *
+ − * @version $Id: TelnetProtocolHandler.java 503 2005-10-24 07:34:13Z marcus $
+ − * @author Matthias L. Jugel, Marcus Meissner
+ − */
+ − public abstract class TelnetProtocolHandler {
+ − /** contains the current revision id */
+ − public final static String ID = "$Id: TelnetProtocolHandler.java 503 2005-10-24 07:34:13Z marcus $";
+ −
+ − /** debug level */
+ − private final static int debug = 0;
+ −
+ − /** temporary buffer for data-telnetstuff-data transformation */
+ − private byte[] tempbuf = new byte[0];
+ −
+ − /** the data sent on pressing <RETURN> \n */
+ − private byte[] crlf = new byte[2];
+ − /** the data sent on pressing <LineFeed> \r */
+ − private byte[] cr = new byte[2];
+ −
+ − /**
+ − * Create a new telnet protocol handler.
+ − */
+ − public TelnetProtocolHandler() {
+ − reset();
+ − crlf[0] = 13; crlf[1] = 10;
+ − cr[0] = 13; cr[1] = 0;
+ − }
+ −
+ − /**
+ − * Get the current terminal type for TTYPE telnet option.
+ − * @return the string id of the terminal
+ − */
+ − protected abstract String getTerminalType();
+ −
+ − /**
+ − * Get the current window size of the terminal for the
+ − * NAWS telnet option.
+ − * @return the size of the terminal as Dimension
+ − */
+ − protected abstract int[] getWindowSize();
+ −
+ − /**
+ − * Set the local echo option of telnet.
+ − * @param echo true for local echo, false for no local echo
+ − */
+ − protected abstract void setLocalEcho(boolean echo);
+ −
+ − /**
+ − * Generate an EOR (end of record) request. For use by prompt displaying.
+ − */
+ − protected abstract void notifyEndOfRecord();
+ −
+ − /**
+ − * Send data to the remote host.
+ − * @param b array of bytes to send
+ − */
+ − protected abstract void write(byte[] b) throws IOException;
+ −
+ − /**
+ − * Read the charset name from terminal.
+ − */
+ − protected abstract String getCharsetName();
+ −
+ − /**
+ − * Send one byte to the remote host.
+ − * @param b the byte to be sent
+ − * @see #write(byte[] b)
+ − */
+ − private static byte[] one = new byte[1];
+ − private void write(byte b) throws IOException {
+ − one[0] = b;
+ − write(one);
+ − }
+ −
+ − /**
+ − * Reset the protocol handler. This may be necessary after the
+ − * connection was closed or some other problem occured.
+ − */
+ − public void reset() {
+ − neg_state = 0;
+ − receivedDX = new byte[256];
+ − sentDX = new byte[256];
+ − receivedWX = new byte[256];
+ − sentWX = new byte[256];
+ − }
+ −
+ − // ===================================================================
+ − // the actual negotiation handling for the telnet protocol follows:
+ − // ===================================================================
+ −
+ − /** state variable for telnet negotiation reader */
+ − private byte neg_state = 0;
+ −
+ − /** constants for the negotiation state */
+ − private final static byte STATE_DATA = 0;
+ − private final static byte STATE_IAC = 1;
+ − private final static byte STATE_IACSB = 2;
+ − private final static byte STATE_IACWILL = 3;
+ − private final static byte STATE_IACDO = 4;
+ − private final static byte STATE_IACWONT = 5;
+ − private final static byte STATE_IACDONT = 6;
+ − private final static byte STATE_IACSBIAC = 7;
+ − private final static byte STATE_IACSBDATA = 8;
+ − private final static byte STATE_IACSBDATAIAC = 9;
+ −
+ − /** What IAC SB <xx> we are handling right now */
+ − private byte current_sb;
+ −
+ − /** current SB negotiation buffer */
+ − private byte[] sbbuf;
+ −
+ − /** IAC - init sequence for telnet negotiation. */
+ − private final static byte IAC = (byte)255;
+ − /** [IAC] End Of Record */
+ − private final static byte EOR = (byte)239;
+ − /** [IAC] WILL */
+ − private final static byte WILL = (byte)251;
+ − /** [IAC] WONT */
+ − private final static byte WONT = (byte)252;
+ − /** [IAC] DO */
+ − private final static byte DO = (byte)253;
+ − /** [IAC] DONT */
+ − private final static byte DONT = (byte)254;
+ − /** [IAC] Sub Begin */
+ − private final static byte SB = (byte)250;
+ − /** [IAC] Sub End */
+ − private final static byte SE = (byte)240;
+ − /** Telnet option: binary mode */
+ − private final static byte TELOPT_BINARY = (byte)0; /* binary mode */
+ − /** Telnet option: echo text */
+ − private final static byte TELOPT_ECHO = (byte)1; /* echo on/off */
+ − /** Telnet option: sga */
+ − private final static byte TELOPT_SGA = (byte)3; /* supress go ahead */
+ − /** Telnet option: End Of Record */
+ − private final static byte TELOPT_EOR = (byte)25; /* end of record */
+ − /** Telnet option: Negotiate About Window Size */
+ − private final static byte TELOPT_NAWS = (byte)31; /* NA-WindowSize*/
+ − /** Telnet option: Terminal Type */
+ − private final static byte TELOPT_TTYPE = (byte)24; /* terminal type */
+ − /** Telnet option: CHARSET */
+ − private final static byte TELOPT_CHARSET = (byte)42; /* charset */
+ −
+ − private final static byte[] IACWILL = { IAC, WILL };
+ − private final static byte[] IACWONT = { IAC, WONT };
+ − private final static byte[] IACDO = { IAC, DO };
+ − private final static byte[] IACDONT = { IAC, DONT };
+ − private final static byte[] IACSB = { IAC, SB };
+ − private final static byte[] IACSE = { IAC, SE };
+ −
+ − private final static byte CHARSET_ACCEPTED = (byte)2;
+ − private final static byte CHARSET_REJECTED = (byte)3;
+ −
+ − /** Telnet option qualifier 'IS' */
+ − private final static byte TELQUAL_IS = (byte)0;
+ − /** Telnet option qualifier 'SEND' */
+ − private final static byte TELQUAL_SEND = (byte)1;
+ −
+ − /** What IAC DO(NT) request do we have received already ? */
+ − private byte[] receivedDX;
+ − /** What IAC WILL/WONT request do we have received already ? */
+ − private byte[] receivedWX;
+ − /** What IAC DO/DONT request do we have sent already ? */
+ − private byte[] sentDX;
+ − /** What IAC WILL/WONT request do we have sent already ? */
+ − private byte[] sentWX;
+ −
+ − /**
+ − * Send a Telnet Escape character (IAC <code>)
+ − */
+ − public void sendTelnetControl(byte code)
+ − throws IOException {
+ − byte[] b = new byte[2];
+ − b[0] = IAC;
+ − b[1] = code;
+ − write(b);
+ − }
+ −
+ − /**
+ − * Send the new Window Size (via NAWS)
+ − */
+ − public void setWindowSize(int columns, int rows)
+ − throws IOException {
+ − if (debug > 2) System.err.println("sending NAWS");
+ −
+ − if (receivedDX[TELOPT_NAWS] != DO) {
+ − System.err.println("not allowed to send NAWS? (DONT NAWS)");
+ − return;
+ − }
+ −
+ − write(IAC); write(SB); write(TELOPT_NAWS);
+ − write((byte)(columns >> 8));
+ − write((byte)(columns & 0xff));
+ − write((byte)(rows >> 8));
+ − write((byte)(rows & 0xff));
+ − write(IAC); write(SE);
+ − }
+ −
+ −
+ − /**
+ − * Handle an incoming IAC SB <type> <bytes> IAC SE
+ − * @param type type of SB
+ − * @param sbata byte array as <bytes>
+ − */
+ − private void handle_sb(byte type, byte[] sbdata)
+ − throws IOException {
+ − if (debug > 1)
+ − System.err.println("TelnetIO.handle_sb(" + type + ")");
+ −
+ − switch (type) {
+ − case TELOPT_TTYPE:
+ − if (sbdata.length > 0 && sbdata[0] == TELQUAL_SEND) {
+ − write(IACSB); write(TELOPT_TTYPE); write(TELQUAL_IS);
+ − /* FIXME: need more logic here if we use
+ − * more than one terminal type
+ − */
+ − String ttype = getTerminalType();
+ −
+ − if (ttype == null) ttype = "dumb";
+ −
+ − write(ttype.getBytes());
+ − write(IACSE);
+ − }
+ −
+ − break;
+ −
+ − case TELOPT_CHARSET:
+ − System.out.println("Got SB CHARSET");
+ − String charsetStr = new String(sbdata, "US-ASCII");
+ −
+ − if (charsetStr.startsWith("TTABLE ")) {
+ − charsetStr = charsetStr.substring(7);
+ − }
+ −
+ − String[] charsets = charsetStr.split(charsetStr.substring(0, 0));
+ − String myCharset = getCharsetName();
+ −
+ − for (String charset : charsets) {
+ − if (charset.equals(myCharset)) {
+ − write(IACSB); write(TELOPT_CHARSET); write(CHARSET_ACCEPTED);
+ − write(charset.getBytes());
+ − write(IACSE);
+ − System.out.println("Sent our charset!");
+ − return;
+ − }
+ − }
+ −
+ − write(IACSB); write(TELOPT_CHARSET); write(CHARSET_REJECTED);
+ − write(IACSE);
+ − break;
+ − }
+ − }
+ −
+ − /**
+ − * Do not send any notifications at startup. We do not know,
+ − * whether the remote client understands telnet protocol handling,
+ − * so we are silent.
+ − * (This used to send IAC WILL SGA, but this is false for a compliant
+ − * client.)
+ − */
+ − public void startup() throws IOException {
+ − }
+ − /**
+ − * Transpose special telnet codes like 0xff or newlines to values
+ − * that are compliant to the protocol. This method will also send
+ − * the buffer immediately after transposing the data.
+ − * @param buf the data buffer to be sent
+ − */
+ − public void transpose(byte[] buf) throws IOException {
+ − int i;
+ − byte[] nbuf, xbuf;
+ − int nbufptr = 0;
+ − nbuf = new byte[buf.length * 2]; // FIXME: buffer overflows possible
+ −
+ − for (i = 0; i < buf.length ; i++) {
+ − switch (buf[i]) {
+ − // Escape IAC twice in stream ... to be telnet protocol compliant
+ − // this is there in binary and non-binary mode.
+ − case IAC:
+ − nbuf[nbufptr++] = IAC;
+ − nbuf[nbufptr++] = IAC;
+ − break;
+ −
+ − // We need to heed RFC 854. LF (\n) is 10, CR (\r) is 13
+ − // we assume that the Terminal sends \n for lf+cr and \r for just cr
+ − // linefeed+carriage return is CR LF */
+ − case 10: // \n
+ − if (receivedDX[TELOPT_BINARY + 128 ] != DO) {
+ − while (nbuf.length - nbufptr < crlf.length) {
+ − xbuf = new byte[nbuf.length * 2];
+ − System.arraycopy(nbuf, 0, xbuf, 0, nbufptr);
+ − nbuf = xbuf;
+ − }
+ −
+ − for (int j = 0; j < crlf.length; j++)
+ − nbuf[nbufptr++] = crlf[j];
+ −
+ − break;
+ − }
+ − else {
+ − // copy verbatim in binary mode.
+ − nbuf[nbufptr++] = buf[i];
+ − }
+ −
+ − break;
+ −
+ − // carriage return is CR NUL */
+ − case 13: // \r
+ − if (receivedDX[TELOPT_BINARY + 128 ] != DO) {
+ − while (nbuf.length - nbufptr < cr.length) {
+ − xbuf = new byte[nbuf.length * 2];
+ − System.arraycopy(nbuf, 0, xbuf, 0, nbufptr);
+ − nbuf = xbuf;
+ − }
+ −
+ − for (int j = 0; j < cr.length; j++)
+ − nbuf[nbufptr++] = cr[j];
+ − }
+ − else {
+ − // copy verbatim in binary mode.
+ − nbuf[nbufptr++] = buf[i];
+ − }
+ −
+ − break;
+ −
+ − // all other characters are just copied
+ − default:
+ − nbuf[nbufptr++] = buf[i];
+ − break;
+ − }
+ − }
+ −
+ − xbuf = new byte[nbufptr];
+ − System.arraycopy(nbuf, 0, xbuf, 0, nbufptr);
+ − write(xbuf);
+ − }
+ −
+ − public void setCRLF(String xcrlf) { crlf = xcrlf.getBytes(); }
+ − public void setCR(String xcr) { cr = xcr.getBytes(); }
+ −
+ − /**
+ − * Handle telnet protocol negotiation. The buffer will be parsed
+ − * and necessary actions are taken according to the telnet protocol.
+ − * See <A HREF="RFC-Telnet-URL">RFC-Telnet</A>
+ − * @param nbuf the byte buffer put out after negotiation
+ − * @return number of bytes processed, 0 for none, and -1 for end of buffer.
+ − */
+ − public int negotiate(byte nbuf[], int offset)
+ − throws IOException {
+ − int count = tempbuf.length;
+ − byte[] buf = tempbuf;
+ − byte sendbuf[] = new byte[3];
+ − byte b, reply;
+ − int boffset = 0, noffset = offset;
+ − boolean dobreak = false;
+ −
+ − if (count == 0) // buffer is empty.
+ − return -1;
+ −
+ − while (!dobreak && (boffset < count) && (noffset < nbuf.length)) {
+ − b = buf[boffset++];
+ −
+ − // of course, byte is a signed entity (-128 -> 127)
+ − // but apparently the SGI Netscape 3.0 doesn't seem
+ − // to care and provides happily values up to 255
+ − if (b >= 128)
+ − b = (byte)(b - 256);
+ −
+ − if (debug > 2) {
+ − Byte B = new Byte(b);
+ − System.err.print("byte: " + B.intValue() + " ");
+ − }
+ −
+ − switch (neg_state) {
+ − case STATE_DATA:
+ − if (b == IAC) {
+ − neg_state = STATE_IAC;
+ − dobreak = true; // leave the loop so we can sync.
+ − }
+ − else
+ − nbuf[noffset++] = b;
+ −
+ − break;
+ −
+ − case STATE_IAC:
+ − switch (b) {
+ − case IAC:
+ − if (debug > 2) System.err.print("IAC ");
+ −
+ − neg_state = STATE_DATA;
+ − nbuf[noffset++] = IAC;
+ − break;
+ −
+ − case WILL:
+ − if (debug > 2) System.err.print("WILL ");
+ −
+ − neg_state = STATE_IACWILL;
+ − break;
+ −
+ − case WONT:
+ − if (debug > 2) System.err.print("WONT ");
+ −
+ − neg_state = STATE_IACWONT;
+ − break;
+ −
+ − case DONT:
+ − if (debug > 2) System.err.print("DONT ");
+ −
+ − neg_state = STATE_IACDONT;
+ − break;
+ −
+ − case DO:
+ − if (debug > 2) System.err.print("DO ");
+ −
+ − neg_state = STATE_IACDO;
+ − break;
+ −
+ − case EOR:
+ − if (debug > 1) System.err.print("EOR ");
+ −
+ − notifyEndOfRecord();
+ − dobreak = true; // leave the loop so we can sync.
+ − neg_state = STATE_DATA;
+ − break;
+ −
+ − case SB:
+ − if (debug > 2) System.err.print("SB ");
+ −
+ − neg_state = STATE_IACSB;
+ − break;
+ −
+ − default:
+ − if (debug > 2) System.err.print("<UNKNOWN " + b + " > ");
+ −
+ − neg_state = STATE_DATA;
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case STATE_IACWILL:
+ − switch (b) {
+ − case TELOPT_ECHO:
+ − if (debug > 2) System.err.println("ECHO");
+ −
+ − reply = DO;
+ − setLocalEcho(false);
+ − break;
+ −
+ − case TELOPT_SGA:
+ − if (debug > 2) System.err.println("SGA");
+ −
+ − reply = DO;
+ − break;
+ −
+ − case TELOPT_EOR:
+ − if (debug > 2) System.err.println("EOR");
+ −
+ − reply = DO;
+ − break;
+ −
+ − case TELOPT_BINARY:
+ − if (debug > 2) System.err.println("BINARY");
+ −
+ − reply = DO;
+ − break;
+ −
+ − default:
+ − if (debug > 2) System.err.println("<UNKNOWN," + b + ">");
+ −
+ − reply = DONT;
+ − break;
+ − }
+ −
+ − if (debug > 1) System.err.println("<" + b + ", WILL =" + WILL + ">");
+ −
+ − if (reply != sentDX[b + 128] || WILL != receivedWX[b + 128]) {
+ − sendbuf[0] = IAC;
+ − sendbuf[1] = reply;
+ − sendbuf[2] = b;
+ − write(sendbuf);
+ − sentDX[b + 128] = reply;
+ − receivedWX[b + 128] = WILL;
+ − }
+ −
+ − neg_state = STATE_DATA;
+ − break;
+ −
+ − case STATE_IACWONT:
+ − switch (b) {
+ − case TELOPT_ECHO:
+ − if (debug > 2) System.err.println("ECHO");
+ −
+ − setLocalEcho(true);
+ − reply = DONT;
+ − break;
+ −
+ − case TELOPT_SGA:
+ − if (debug > 2) System.err.println("SGA");
+ −
+ − reply = DONT;
+ − break;
+ −
+ − case TELOPT_EOR:
+ − if (debug > 2) System.err.println("EOR");
+ −
+ − reply = DONT;
+ − break;
+ −
+ − case TELOPT_BINARY:
+ − if (debug > 2) System.err.println("BINARY");
+ −
+ − reply = DONT;
+ − break;
+ −
+ − default:
+ − if (debug > 2) System.err.println("<UNKNOWN," + b + ">");
+ −
+ − reply = DONT;
+ − break;
+ − }
+ −
+ − if (reply != sentDX[b + 128] || WONT != receivedWX[b + 128]) {
+ − sendbuf[0] = IAC;
+ − sendbuf[1] = reply;
+ − sendbuf[2] = b;
+ − write(sendbuf);
+ − sentDX[b + 128] = reply;
+ − receivedWX[b + 128] = WILL;
+ − }
+ −
+ − neg_state = STATE_DATA;
+ − break;
+ −
+ − case STATE_IACDO:
+ − switch (b) {
+ − case TELOPT_ECHO:
+ − if (debug > 2) System.err.println("ECHO");
+ −
+ − reply = WILL;
+ − setLocalEcho(true);
+ − break;
+ −
+ − case TELOPT_SGA:
+ − if (debug > 2) System.err.println("SGA");
+ −
+ − reply = WILL;
+ − break;
+ −
+ − case TELOPT_TTYPE:
+ − if (debug > 2) System.err.println("TTYPE");
+ −
+ − reply = WILL;
+ − break;
+ −
+ − case TELOPT_BINARY:
+ − if (debug > 2) System.err.println("BINARY");
+ −
+ − reply = WILL;
+ − break;
+ −
+ − case TELOPT_NAWS:
+ − if (debug > 2) System.err.println("NAWS");
+ −
+ − int[] size = getWindowSize();
+ − receivedDX[b] = DO;
+ −
+ − if (size == null) {
+ − // this shouldn't happen
+ − write(IAC);
+ − write(WONT);
+ − write(TELOPT_NAWS);
+ − reply = WONT;
+ − sentWX[b] = WONT;
+ − break;
+ − }
+ −
+ − reply = WILL;
+ − sentWX[b] = WILL;
+ − sendbuf[0] = IAC;
+ − sendbuf[1] = WILL;
+ − sendbuf[2] = TELOPT_NAWS;
+ − write(sendbuf);
+ − write(IAC); write(SB); write(TELOPT_NAWS);
+ − write((byte)(size[0] >> 8));
+ − write((byte)(size[0] & 0xff));
+ − write((byte)(size[1] >> 8));
+ − write((byte)(size[1] & 0xff));
+ − write(IAC); write(SE);
+ − break;
+ −
+ − default:
+ − if (debug > 2) System.err.println("<UNKNOWN," + b + ">");
+ −
+ − reply = WONT;
+ − break;
+ − }
+ −
+ − if (reply != sentWX[128 + b] || DO != receivedDX[128 + b]) {
+ − sendbuf[0] = IAC;
+ − sendbuf[1] = reply;
+ − sendbuf[2] = b;
+ − write(sendbuf);
+ − sentWX[b + 128] = reply;
+ − receivedDX[b + 128] = DO;
+ − }
+ −
+ − neg_state = STATE_DATA;
+ − break;
+ −
+ − case STATE_IACDONT:
+ − switch (b) {
+ − case TELOPT_ECHO:
+ − if (debug > 2) System.err.println("ECHO");
+ −
+ − reply = WONT;
+ − setLocalEcho(false);
+ − break;
+ −
+ − case TELOPT_SGA:
+ − if (debug > 2) System.err.println("SGA");
+ −
+ − reply = WONT;
+ − break;
+ −
+ − case TELOPT_NAWS:
+ − if (debug > 2) System.err.println("NAWS");
+ −
+ − reply = WONT;
+ − break;
+ −
+ − case TELOPT_BINARY:
+ − if (debug > 2) System.err.println("BINARY");
+ −
+ − reply = WONT;
+ − break;
+ −
+ − default:
+ − if (debug > 2) System.err.println("<UNKNOWN," + b + ">");
+ −
+ − reply = WONT;
+ − break;
+ − }
+ −
+ − if (reply != sentWX[b + 128] || DONT != receivedDX[b + 128]) {
+ − write(IAC); write(reply); write(b);
+ − sentWX[b + 128] = reply;
+ − receivedDX[b + 128] = DONT;
+ − }
+ −
+ − neg_state = STATE_DATA;
+ − break;
+ −
+ − case STATE_IACSBIAC:
+ − if (debug > 2) System.err.println("" + b + " ");
+ −
+ − if (b == IAC) {
+ − sbbuf = new byte[0];
+ − current_sb = b;
+ − neg_state = STATE_IACSBDATA;
+ − }
+ − else {
+ − System.err.println("(bad) " + b + " ");
+ − neg_state = STATE_DATA;
+ − }
+ −
+ − break;
+ −
+ − case STATE_IACSB:
+ − if (debug > 2) System.err.println("" + b + " ");
+ −
+ − switch (b) {
+ − case IAC:
+ − neg_state = STATE_IACSBIAC;
+ − break;
+ −
+ − default:
+ − current_sb = b;
+ − sbbuf = new byte[0];
+ − neg_state = STATE_IACSBDATA;
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case STATE_IACSBDATA:
+ − if (debug > 2) System.err.println("" + b + " ");
+ −
+ − switch (b) {
+ − case IAC:
+ − neg_state = STATE_IACSBDATAIAC;
+ − break;
+ −
+ − default:
+ − byte[] xsb = new byte[sbbuf.length + 1];
+ − System.arraycopy(sbbuf, 0, xsb, 0, sbbuf.length);
+ − sbbuf = xsb;
+ − sbbuf[sbbuf.length - 1] = b;
+ − break;
+ − }
+ −
+ − break;
+ −
+ − case STATE_IACSBDATAIAC:
+ − if (debug > 2) System.err.println("" + b + " ");
+ −
+ − switch (b) {
+ − case IAC:
+ − neg_state = STATE_IACSBDATA;
+ − byte[] xsb = new byte[sbbuf.length + 1];
+ − System.arraycopy(sbbuf, 0, xsb, 0, sbbuf.length);
+ − sbbuf = xsb;
+ − sbbuf[sbbuf.length - 1] = IAC;
+ − break;
+ −
+ − case SE:
+ − handle_sb(current_sb, sbbuf);
+ − current_sb = 0;
+ − neg_state = STATE_DATA;
+ − break;
+ −
+ − case SB:
+ − handle_sb(current_sb, sbbuf);
+ − neg_state = STATE_IACSB;
+ − break;
+ −
+ − default:
+ − neg_state = STATE_DATA;
+ − break;
+ − }
+ −
+ − break;
+ −
+ − default:
+ − if (debug > 1)
+ − System.err.println("This should not happen: " + neg_state + " ");
+ −
+ − neg_state = STATE_DATA;
+ − break;
+ − }
+ − }
+ −
+ − // shrink tempbuf to new processed size.
+ − byte[] xb = new byte[count - boffset];
+ − System.arraycopy(tempbuf, boffset, xb, 0, count - boffset);
+ − tempbuf = xb;
+ − return noffset - offset;
+ − }
+ −
+ − public void inputfeed(byte[] b, int offset, int len) {
+ − byte[] xb = new byte[tempbuf.length + len];
+ − System.arraycopy(tempbuf, 0, xb, 0, tempbuf.length);
+ − System.arraycopy(b, offset, xb, tempbuf.length, len);
+ − tempbuf = xb;
+ − }
+ − }