telnet: speed up processing of network input

function                                             old     new   delta
telnet_main                                         1482    1492     +10

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2019-01-06 18:41:11 +01:00
parent 1c952ba206
commit 5bfc4a32fd

View File

@ -94,19 +94,19 @@ enum {
IACBUFSIZE = 128, IACBUFSIZE = 128,
CHM_TRY = 0, CHM_TRY = 0,
CHM_ON = 1, CHM_ON = 1,
CHM_OFF = 2, CHM_OFF = 2,
UF_ECHO = 0x01, UF_ECHO = 0x01,
UF_SGA = 0x02, UF_SGA = 0x02,
TS_NORMAL = 0, TS_NORMAL = 0,
TS_COPY = 1, TS_COPY = 1,
TS_IAC = 2, TS_IAC = 2,
TS_OPT = 3, TS_OPT = 3,
TS_SUB1 = 4, TS_SUB1 = 4,
TS_SUB2 = 5, TS_SUB2 = 5,
TS_CR = 6, TS_CR = 6,
}; };
typedef unsigned char byte; typedef unsigned char byte;
@ -244,25 +244,34 @@ static void handle_net_output(int len)
static void handle_net_input(int len) static void handle_net_input(int len)
{ {
byte c;
int i; int i;
int cstart = 0; int cstart;
for (i = 0; i < len; i++) { i = 0;
byte c = G.buf[i]; //bb_error_msg("[%u,'%.*s']", G.telstate, len, G.buf);
if (G.telstate == TS_NORMAL) { /* most typical state */
if (G.telstate == TS_NORMAL) { /* most typical state */ while (i < len) {
if (c == IAC) { c = G.buf[i];
cstart = i; i++;
G.telstate = TS_IAC; if (c == IAC) /* unlikely */
} goto got_IAC;
else if (c == '\r') { if (c != '\r') /* likely */
cstart = i + 1; continue;
G.telstate = TS_CR; G.telstate = TS_CR;
} cstart = i;
/* No IACs were seen so far, no need to copy goto got_special;
* bytes within G.buf: */
continue;
} }
full_write(STDOUT_FILENO, G.buf, len);
return;
got_IAC:
G.telstate = TS_IAC;
cstart = i - 1;
got_special: ;
}
for (; i < len; i++) {
c = G.buf[i];
switch (G.telstate) { switch (G.telstate) {
case TS_CR: case TS_CR:
@ -278,20 +287,19 @@ static void handle_net_input(int len)
/* Similar to NORMAL, but in TS_COPY we need to copy bytes */ /* Similar to NORMAL, but in TS_COPY we need to copy bytes */
if (c == IAC) if (c == IAC)
G.telstate = TS_IAC; G.telstate = TS_IAC;
else else {
G.buf[cstart++] = c; G.buf[cstart++] = c;
if (c == '\r') if (c == '\r')
G.telstate = TS_CR; G.telstate = TS_CR;
}
break; break;
case TS_IAC: /* Prev char was IAC */ case TS_IAC: /* Prev char was IAC */
if (c == IAC) { /* IAC IAC -> one IAC */ switch (c) {
case IAC: /* IAC IAC -> one IAC */
G.buf[cstart++] = c; G.buf[cstart++] = c;
G.telstate = TS_COPY; G.telstate = TS_COPY;
break; break;
}
/* else */
switch (c) {
case SB: case SB:
G.telstate = TS_SUB1; G.telstate = TS_SUB1;
break; break;
@ -320,17 +328,12 @@ static void handle_net_input(int len)
} }
} }
if (G.telstate != TS_NORMAL) { /* We had some IACs, or CR */
/* We had some IACs, or CR */ iac_flush();
if (G.iaclen) if (G.telstate == TS_COPY) /* we aren't in the middle of IAC */
iac_flush(); G.telstate = TS_NORMAL;
if (G.telstate == TS_COPY) /* we aren't in the middle of IAC */ if (cstart != 0)
G.telstate = TS_NORMAL; full_write(STDOUT_FILENO, G.buf, cstart);
len = cstart;
}
if (len)
full_write(STDOUT_FILENO, G.buf, len);
} }
static void put_iac(int c) static void put_iac(int c)