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 */
|
unsigned short subopt_wsy; /* Set with suboption NAWS */
|
||||||
TelnetReceive telrcv_state;
|
TelnetReceive telrcv_state;
|
||||||
struct curl_slist *telnet_vars; /* Environment variables */
|
struct curl_slist *telnet_vars; /* Environment variables */
|
||||||
|
struct dynbuf out; /* output buffer */
|
||||||
|
|
||||||
/* suboptions */
|
/* suboptions */
|
||||||
unsigned char subbuffer[SUBBUFSIZE];
|
unsigned char subbuffer[SUBBUFSIZE];
|
||||||
@ -204,6 +205,7 @@ CURLcode init_telnet(struct Curl_easy *data)
|
|||||||
if(!tn)
|
if(!tn)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
Curl_dyn_init(&tn->out, 0xffff);
|
||||||
data->req.p.telnet = tn; /* make us known */
|
data->req.p.telnet = tn; /* make us known */
|
||||||
|
|
||||||
tn->telrcv_state = CURL_TS_DATA;
|
tn->telrcv_state = CURL_TS_DATA;
|
||||||
@ -1229,37 +1231,33 @@ process_iac:
|
|||||||
static CURLcode send_telnet_data(struct Curl_easy *data,
|
static CURLcode send_telnet_data(struct Curl_easy *data,
|
||||||
char *buffer, ssize_t nread)
|
char *buffer, ssize_t nread)
|
||||||
{
|
{
|
||||||
ssize_t escapes, i, outlen;
|
ssize_t i, outlen;
|
||||||
unsigned char *outbuf = NULL;
|
unsigned char *outbuf;
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
ssize_t bytes_written, total_written;
|
ssize_t bytes_written, total_written = 0;
|
||||||
struct connectdata *conn = data->conn;
|
struct connectdata *conn = data->conn;
|
||||||
|
struct TELNET *tn = data->req.p.telnet;
|
||||||
|
|
||||||
/* Determine size of new buffer after escaping */
|
DEBUGASSERT(tn);
|
||||||
escapes = 0;
|
|
||||||
for(i = 0; i < nread; i++)
|
|
||||||
if((unsigned char)buffer[i] == CURL_IAC)
|
|
||||||
escapes++;
|
|
||||||
outlen = nread + escapes;
|
|
||||||
|
|
||||||
if(outlen == nread)
|
if(memchr(buffer, CURL_IAC, nread)) {
|
||||||
outbuf = (unsigned char *)buffer;
|
/* only use the escape buffer when necessary */
|
||||||
else {
|
Curl_dyn_reset(&tn->out);
|
||||||
ssize_t j;
|
|
||||||
outbuf = malloc(nread + escapes + 1);
|
|
||||||
if(!outbuf)
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
j = 0;
|
for(i = 0; i < nread && !result; i++) {
|
||||||
for(i = 0; i < nread; i++) {
|
result = Curl_dyn_addn(&tn->out, &buffer[i], 1);
|
||||||
outbuf[j++] = (unsigned char)buffer[i];
|
if(!result && ((unsigned char)buffer[i] == CURL_IAC))
|
||||||
if((unsigned char)buffer[i] == CURL_IAC)
|
/* IAC is FF in hex */
|
||||||
outbuf[j++] = CURL_IAC;
|
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) {
|
while(!result && total_written < outlen) {
|
||||||
/* Make sure socket is writable to avoid EWOULDBLOCK condition */
|
/* Make sure socket is writable to avoid EWOULDBLOCK condition */
|
||||||
struct pollfd pfd[1];
|
struct pollfd pfd[1];
|
||||||
@ -1272,19 +1270,13 @@ static CURLcode send_telnet_data(struct Curl_easy *data,
|
|||||||
break;
|
break;
|
||||||
default: /* write! */
|
default: /* write! */
|
||||||
bytes_written = 0;
|
bytes_written = 0;
|
||||||
result = Curl_nwrite(data, FIRSTSOCKET,
|
result = Curl_nwrite(data, FIRSTSOCKET, outbuf + total_written,
|
||||||
outbuf + total_written,
|
outlen - total_written, &bytes_written);
|
||||||
outlen - total_written,
|
|
||||||
&bytes_written);
|
|
||||||
total_written += bytes_written;
|
total_written += bytes_written;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free malloc copy if escaped */
|
|
||||||
if(outbuf != (unsigned char *)buffer)
|
|
||||||
free(outbuf);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1300,6 +1292,7 @@ static CURLcode telnet_done(struct Curl_easy *data,
|
|||||||
|
|
||||||
curl_slist_free_all(tn->telnet_vars);
|
curl_slist_free_all(tn->telnet_vars);
|
||||||
tn->telnet_vars = NULL;
|
tn->telnet_vars = NULL;
|
||||||
|
Curl_dyn_free(&tn->out);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user