Improved telnet support by drastically reducing the number of write

callbacks needed to pass a buffer to the user.  Instead one per byte it
is now as little as one per segment.
This commit is contained in:
Dan Fandrich 2007-11-07 05:52:03 +00:00
parent 70f10f1ac9
commit 33f7ac06c3
2 changed files with 45 additions and 23 deletions

View File

@ -6,6 +6,11 @@
Changelog
Dan F (6 Nov 2007)
- Improved telnet support by drastically reducing the number of write
callbacks needed to pass a buffer to the user. Instead one per byte it
is now as little as one per segment.
Yang Tse (6 Nov 2007)
- Bug report #1824894 (http://curl.haxx.se/bug/view.cgi?id=1824894) pointed
out a problem in curl.h when building C++ apps with MSVC. To fix it, the

View File

@ -106,7 +106,7 @@ static CURLcode check_wsock2 ( struct SessionHandle *data );
static
void telrcv(struct connectdata *,
unsigned char *inbuf, /* Data received from socket */
const unsigned char *inbuf, /* Data received from socket */
ssize_t count); /* Number of bytes received */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
@ -949,104 +949,119 @@ static void suboption(struct connectdata *conn)
static
void telrcv(struct connectdata *conn,
unsigned char *inbuf, /* Data received from socket */
const unsigned char *inbuf, /* Data received from socket */
ssize_t count) /* Number of bytes received */
{
unsigned char c;
int in = 0;
int startwrite=-1;
struct SessionHandle *data = conn->data;
struct TELNET *tn = (struct TELNET *)data->reqdata.proto.telnet;
#define startskipping() \
if (startwrite >= 0) \
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&inbuf[startwrite], in-startwrite); \
startwrite = -1
#define writebyte() \
if (startwrite < 0) \
startwrite = in
#define bufferflush() startskipping()
while(count--)
{
c = inbuf[in++];
c = inbuf[in];
/*infof(data,"In rcv state %d char %d\n", tn->telrcv_state, c);*/
switch (tn->telrcv_state)
{
case CURL_TS_CR:
tn->telrcv_state = CURL_TS_DATA;
if(c == '\0')
{
startskipping();
break; /* Ignore \0 after CR */
}
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
continue;
writebyte();
break;
case CURL_TS_DATA:
if(c == CURL_IAC)
{
tn->telrcv_state = CURL_TS_IAC;
startskipping();
break;
}
else if(c == '\r')
{
tn->telrcv_state = CURL_TS_CR;
}
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
continue;
writebyte();
break;
case CURL_TS_IAC:
process_iac:
DEBUGASSERT(startwrite < 0);
switch (c)
{
case CURL_WILL:
tn->telrcv_state = CURL_TS_WILL;
continue;
break;
case CURL_WONT:
tn->telrcv_state = CURL_TS_WONT;
continue;
break;
case CURL_DO:
tn->telrcv_state = CURL_TS_DO;
continue;
break;
case CURL_DONT:
tn->telrcv_state = CURL_TS_DONT;
continue;
break;
case CURL_SB:
CURL_SB_CLEAR(tn);
tn->telrcv_state = CURL_TS_SB;
continue;
break;
case CURL_IAC:
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
tn->telrcv_state = CURL_TS_DATA;
writebyte();
break;
case CURL_DM:
case CURL_NOP:
case CURL_GA:
default:
tn->telrcv_state = CURL_TS_DATA;
printoption(data, "RCVD", CURL_IAC, c);
break;
}
tn->telrcv_state = CURL_TS_DATA;
continue;
break;
case CURL_TS_WILL:
printoption(data, "RCVD", CURL_WILL, c);
tn->please_negotiate = 1;
rec_will(conn, c);
tn->telrcv_state = CURL_TS_DATA;
continue;
break;
case CURL_TS_WONT:
printoption(data, "RCVD", CURL_WONT, c);
tn->please_negotiate = 1;
rec_wont(conn, c);
tn->telrcv_state = CURL_TS_DATA;
continue;
break;
case CURL_TS_DO:
printoption(data, "RCVD", CURL_DO, c);
tn->please_negotiate = 1;
rec_do(conn, c);
tn->telrcv_state = CURL_TS_DATA;
continue;
break;
case CURL_TS_DONT:
printoption(data, "RCVD", CURL_DONT, c);
tn->please_negotiate = 1;
rec_dont(conn, c);
tn->telrcv_state = CURL_TS_DATA;
continue;
break;
case CURL_TS_SB:
if(c == CURL_IAC)
@ -1057,7 +1072,7 @@ void telrcv(struct connectdata *conn,
{
CURL_SB_ACCUM(tn,c);
}
continue;
break;
case CURL_TS_SE:
if(c != CURL_SE)
@ -1097,7 +1112,9 @@ void telrcv(struct connectdata *conn,
}
break;
}
++in;
}
bufferflush();
}
static CURLcode Curl_telnet_done(struct connectdata *conn,
@ -1143,7 +1160,7 @@ static CURLcode Curl_telnet(struct connectdata *conn, bool *done)
char *buf = data->state.buffer;
struct TELNET *tn;
*done = TRUE; /* uncontionally */
*done = TRUE; /* unconditionally */
code = init_telnet(conn);
if(code)