dont require a buffer for subnegotiations with no data; more efficient for apps that dont use more advanced subnegotiation features
diff --git a/README b/README
index ce695bd..f3d7e1a 100644
--- a/README
+++ b/README
@@ -20,13 +20,11 @@
- RFC 1143 option negotiation algorithm
- automatic MCCP2 handling (controllable by host app)
- - efficient one-byte sub-requests
? MCCP1
? ZMP parsing
? MSSP parsing
? ENVIRON/NEW-ENVIRON parsing
? telnet-status testing tool
- ? few options to make telnet-proxy even more useful
I. INTRODUCTION
=====================================================================
diff --git a/libtelnet.c b/libtelnet.c
index 4a521e6..27513ef 100644
--- a/libtelnet.c
+++ b/libtelnet.c
@@ -263,11 +263,18 @@
telnet->state = LIBTELNET_STATE_DATA;
break;
- /* subnegotiation -- buffer bytes until end request */
+ /* subnegotiation -- determine subnegotiation telopt */
case LIBTELNET_STATE_SB:
+ telnet->sb_telopt = byte;
+ telnet->length = 0;
+ telnet->state = LIBTELNET_STATE_SB_DATA;
+ break;
+
+ /* subnegotiation -- buffer bytes until end request */
+ case LIBTELNET_STATE_SB_DATA:
/* IAC command in subnegotiation -- either IAC SE or IAC IAC */
if (byte == LIBTELNET_IAC) {
- telnet->state = LIBTELNET_STATE_SB_IAC;
+ telnet->state = LIBTELNET_STATE_SB_DATA_IAC;
/* buffer the byte, or bail if we can't */
} else if (_buffer_byte(telnet, byte, user_data) !=
LIBTELNET_EOK) {
@@ -277,7 +284,7 @@
break;
/* IAC escaping inside a subnegotiation */
- case LIBTELNET_STATE_SB_IAC:
+ case LIBTELNET_STATE_SB_DATA_IAC:
switch (byte) {
/* end subnegotiation */
case LIBTELNET_SE:
@@ -285,25 +292,17 @@
start = i + 1;
telnet->state = LIBTELNET_STATE_DATA;
- /* zero-size buffer is a protocol error */
- if (telnet->length == 0) {
- ERROR(telnet, LIBTELNET_EPROTOCOL, user_data,
- "subnegotiation has zero data");
- break;
- }
-
/* invoke callback */
_event(telnet, LIBTELNET_EV_SUBNEGOTIATION, 0,
- telnet->buffer[0], telnet->buffer + 1,
- telnet->length - 1, user_data);
- telnet->length = 0;
+ telnet->sb_telopt, telnet->buffer, telnet->length,
+ user_data);
#ifdef HAVE_ZLIB
/* if we are a client or a proxy and just received the
* COMPRESS2 begin marker, setup our zlib box and start
* handling the compressed stream if it's not already.
*/
- if (telnet->buffer[0] == LIBTELNET_TELOPT_COMPRESS2 &&
+ if (telnet->sb_telopt == LIBTELNET_TELOPT_COMPRESS2 &&
telnet->z_inflate == 0 &&
(telnet->mode == LIBTELNET_MODE_CLIENT ||
telnet->mode == LIBTELNET_MODE_PROXY)) {
@@ -337,7 +336,7 @@
start = i + 1;
telnet->state = LIBTELNET_STATE_DATA;
} else {
- telnet->state = LIBTELNET_STATE_SB;
+ telnet->state = LIBTELNET_STATE_SB_DATA;
}
break;
/* something else -- protocol error */
diff --git a/libtelnet.h b/libtelnet.h
index 87f0659..629dace 100644
--- a/libtelnet.h
+++ b/libtelnet.h
@@ -101,7 +101,8 @@
LIBTELNET_STATE_WILL,
LIBTELNET_STATE_WONT,
LIBTELNET_STATE_SB,
- LIBTELNET_STATE_SB_IAC
+ LIBTELNET_STATE_SB_DATA,
+ LIBTELNET_STATE_SB_DATA_IAC
};
/* error codes */
@@ -160,6 +161,8 @@
enum libtelnet_state_t state;
/* processing mode */
enum libtelnet_mode_t mode;
+ /* current subnegotiation telopt */
+ unsigned char sb_telopt;
};
/* initialize a telnet state tracker */