in src/main/java/org/apache/commons/net/telnet/TelnetInputStream.java [269:430]
private int read(final boolean mayBlock) throws IOException {
int ch;
while (true) {
// If there is no more data AND we were told not to block,
// just return WOULD_BLOCK (-2). (More efficient than exception.)
if (!mayBlock && super.available() == 0) {
return WOULD_BLOCK;
}
// Otherwise, exit only when we reach end of stream.
if ((ch = super.read()) < 0) {
return EOF;
}
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) */
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
//$FALL-THROUGH$
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:
suboptionCount = 0;
receiveState = STATE_SB;
continue;
/* TERMINAL-TYPE option (end) */
case TelnetCommand.IAC:
receiveState = STATE_DATA;
break; // exit to enclosing switch to return IAC from read
case TelnetCommand.SE: // unexpected byte! ignore it (don't send it as a command)
receiveState = STATE_DATA;
continue;
default:
receiveState = STATE_DATA;
client.processCommand(ch); // Notify the user
continue; // move on the next char
}
break; // exit and return from read
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
if (suboptionCount < suboption.length) {
suboption[suboptionCount++] = ch;
}
break;
}
receiveState = STATE_SB;
continue;
case STATE_IAC_SB: // IAC received during SB phase
switch (ch) {
case TelnetCommand.SE:
synchronized (client) {
client.processSuboption(suboption, suboptionCount);
client.flushOutputStream();
}
receiveState = STATE_DATA;
continue;
case TelnetCommand.IAC: // De-dup the duplicated IAC
if (suboptionCount < suboption.length) {
suboption[suboptionCount++] = ch;
}
break;
default: // unexpected byte! ignore it
break;
}
receiveState = STATE_SB;
continue;
/* TERMINAL-TYPE option (end) */
}
break;
}
return ch;
}