mirror of
https://github.com/curl/curl.git
synced 2025-04-24 16:40:32 +08:00
telnet: use dynbuf instad of malloc for escape buffer
Previously, send_telnet_data() would malloc + free a buffer every time for escaping IAC codes. Now, it reuses a dynbuf for this purpose. Closes #12652
This commit is contained in:
parent
d18811b52b
commit
2959f45b7d
57
lib/telnet.c
57
lib/telnet.c
@ -160,6 +160,7 @@ struct TELNET {
|
||||
unsigned short subopt_wsy; /* Set with suboption NAWS */
|
||||
TelnetReceive telrcv_state;
|
||||
struct curl_slist *telnet_vars; /* Environment variables */
|
||||
struct dynbuf out; /* output buffer */
|
||||
|
||||
/* suboptions */
|
||||
unsigned char subbuffer[SUBBUFSIZE];
|
||||
@ -204,6 +205,7 @@ CURLcode init_telnet(struct Curl_easy *data)
|
||||
if(!tn)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
Curl_dyn_init(&tn->out, 0xffff);
|
||||
data->req.p.telnet = tn; /* make us known */
|
||||
|
||||
tn->telrcv_state = CURL_TS_DATA;
|
||||
@ -1229,37 +1231,33 @@ process_iac:
|
||||
static CURLcode send_telnet_data(struct Curl_easy *data,
|
||||
char *buffer, ssize_t nread)
|
||||
{
|
||||
ssize_t escapes, i, outlen;
|
||||
unsigned char *outbuf = NULL;
|
||||
ssize_t i, outlen;
|
||||
unsigned char *outbuf;
|
||||
CURLcode result = CURLE_OK;
|
||||
ssize_t bytes_written, total_written;
|
||||
ssize_t bytes_written, total_written = 0;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct TELNET *tn = data->req.p.telnet;
|
||||
|
||||
/* Determine size of new buffer after escaping */
|
||||
escapes = 0;
|
||||
for(i = 0; i < nread; i++)
|
||||
if((unsigned char)buffer[i] == CURL_IAC)
|
||||
escapes++;
|
||||
outlen = nread + escapes;
|
||||
DEBUGASSERT(tn);
|
||||
|
||||
if(outlen == nread)
|
||||
outbuf = (unsigned char *)buffer;
|
||||
else {
|
||||
ssize_t j;
|
||||
outbuf = malloc(nread + escapes + 1);
|
||||
if(!outbuf)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(memchr(buffer, CURL_IAC, nread)) {
|
||||
/* only use the escape buffer when necessary */
|
||||
Curl_dyn_reset(&tn->out);
|
||||
|
||||
j = 0;
|
||||
for(i = 0; i < nread; i++) {
|
||||
outbuf[j++] = (unsigned char)buffer[i];
|
||||
if((unsigned char)buffer[i] == CURL_IAC)
|
||||
outbuf[j++] = CURL_IAC;
|
||||
for(i = 0; i < nread && !result; i++) {
|
||||
result = Curl_dyn_addn(&tn->out, &buffer[i], 1);
|
||||
if(!result && ((unsigned char)buffer[i] == CURL_IAC))
|
||||
/* IAC is FF in hex */
|
||||
result = Curl_dyn_addn(&tn->out, "\xff", 1);
|
||||
}
|
||||
outbuf[j] = '\0';
|
||||
}
|
||||
|
||||
total_written = 0;
|
||||
outlen = Curl_dyn_len(&tn->out);
|
||||
outbuf = Curl_dyn_uptr(&tn->out);
|
||||
}
|
||||
else {
|
||||
outlen = nread;
|
||||
outbuf = (unsigned char *)buffer;
|
||||
}
|
||||
while(!result && total_written < outlen) {
|
||||
/* Make sure socket is writable to avoid EWOULDBLOCK condition */
|
||||
struct pollfd pfd[1];
|
||||
@ -1272,19 +1270,13 @@ static CURLcode send_telnet_data(struct Curl_easy *data,
|
||||
break;
|
||||
default: /* write! */
|
||||
bytes_written = 0;
|
||||
result = Curl_nwrite(data, FIRSTSOCKET,
|
||||
outbuf + total_written,
|
||||
outlen - total_written,
|
||||
&bytes_written);
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, outbuf + total_written,
|
||||
outlen - total_written, &bytes_written);
|
||||
total_written += bytes_written;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free malloc copy if escaped */
|
||||
if(outbuf != (unsigned char *)buffer)
|
||||
free(outbuf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1300,6 +1292,7 @@ static CURLcode telnet_done(struct Curl_easy *data,
|
||||
|
||||
curl_slist_free_all(tn->telnet_vars);
|
||||
tn->telnet_vars = NULL;
|
||||
Curl_dyn_free(&tn->out);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user