mirror of
https://github.com/moparisthebest/curl
synced 2024-12-23 08:38:49 -05:00
parent
7a86a25f5b
commit
18815aa670
@ -54,7 +54,7 @@ Reset the buffer length, but leave the allocation.
|
||||
|
||||
Keep `length` bytes of the buffer tail (the last `length` bytes of the
|
||||
buffer). The rest of the buffer is dropped. The specified `length` must not be
|
||||
larger than the buffer length. (**This function is currently not provided**.)
|
||||
larger than the buffer length.
|
||||
|
||||
## ptr
|
||||
|
||||
|
@ -123,7 +123,7 @@ void Curl_dyn_reset(struct dynbuf *s)
|
||||
s->leng = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#ifdef USE_NGTCP2
|
||||
/*
|
||||
* Specify the size of the tail to keep (number of bytes from the end of the
|
||||
* buffer). The rest will be dropped.
|
||||
@ -147,7 +147,6 @@ CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail)
|
||||
return CURLE_OK;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -182,9 +182,7 @@ struct HTTP {
|
||||
#ifdef USE_NGHTTP3
|
||||
size_t unacked_window;
|
||||
struct h3out *h3out; /* per-stream buffers for upload */
|
||||
char *overflow_buf; /* excess data received during a single Curl_read */
|
||||
size_t overflow_buflen; /* amount of data currently in overflow_buf */
|
||||
size_t overflow_bufsize; /* size of the overflow_buf allocation */
|
||||
struct dynbuf overflow; /* excess data received during a single Curl_read */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "strcase.h"
|
||||
#include "connect.h"
|
||||
#include "strerror.h"
|
||||
#include "dynbuf.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
@ -1018,57 +1019,12 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Minimum size of the overflow buffer */
|
||||
#define OVERFLOWSIZE 1024
|
||||
|
||||
/*
|
||||
* allocate_overflow() ensures that there is room for incoming data in the
|
||||
* overflow buffer, growing it to accommodate the new data if necessary. We
|
||||
* may need to use the overflow buffer because we can't precisely limit the
|
||||
* amount of HTTP/3 header data we receive using QUIC flow control mechanisms.
|
||||
*/
|
||||
static CURLcode allocate_overflow(struct Curl_easy *data,
|
||||
struct HTTP *stream,
|
||||
size_t length)
|
||||
{
|
||||
size_t maxleft;
|
||||
size_t newsize;
|
||||
/* length can be arbitrarily large, so take care not to overflow newsize */
|
||||
maxleft = CURL_MAX_READ_SIZE - stream->overflow_buflen;
|
||||
if(length > maxleft) {
|
||||
/* The reason to have a max limit for this is to avoid the risk of a bad
|
||||
server feeding libcurl with a highly compressed list of headers that
|
||||
will cause our overflow buffer to grow too large */
|
||||
failf(data, "Rejected %zu bytes of overflow data (max is %d)!",
|
||||
stream->overflow_buflen + length, CURL_MAX_READ_SIZE);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
newsize = stream->overflow_buflen + length;
|
||||
if(newsize > stream->overflow_bufsize) {
|
||||
/* We enlarge the overflow buffer as it is too small */
|
||||
char *newbuff;
|
||||
newsize = CURLMAX(newsize * 3 / 2, stream->overflow_bufsize*2);
|
||||
newsize = CURLMIN(CURLMAX(OVERFLOWSIZE, newsize), CURL_MAX_READ_SIZE);
|
||||
newbuff = realloc(stream->overflow_buf, newsize);
|
||||
if(!newbuff) {
|
||||
failf(data, "Failed to alloc memory for overflow buffer!");
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
stream->overflow_buf = newbuff;
|
||||
stream->overflow_bufsize = newsize;
|
||||
infof(data, "Grew HTTP/3 overflow buffer to %zu bytes\n", newsize);
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* write_data() copies data to the stream's receive buffer. If not enough
|
||||
* space is available in the receive buffer, it copies the rest to the
|
||||
* stream's overflow buffer.
|
||||
*/
|
||||
static CURLcode write_data(struct Curl_easy *data,
|
||||
struct HTTP *stream,
|
||||
const void *mem, size_t memlen)
|
||||
static CURLcode write_data(struct HTTP *stream, const void *mem, size_t memlen)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
const char *buf = mem;
|
||||
@ -1076,10 +1032,6 @@ static CURLcode write_data(struct Curl_easy *data,
|
||||
/* copy as much as possible to the receive buffer */
|
||||
if(stream->len) {
|
||||
size_t len = CURLMIN(ncopy, stream->len);
|
||||
#if 0 /* extra debugging of incoming h3 data */
|
||||
fprintf(stderr, "!! Copies %zd bytes to %p (total %zd)\n",
|
||||
len, stream->mem, stream->memlen);
|
||||
#endif
|
||||
memcpy(stream->mem, buf, len);
|
||||
stream->len -= len;
|
||||
stream->memlen += len;
|
||||
@ -1088,26 +1040,8 @@ static CURLcode write_data(struct Curl_easy *data,
|
||||
ncopy -= len;
|
||||
}
|
||||
/* copy the rest to the overflow buffer */
|
||||
if(ncopy) {
|
||||
result = allocate_overflow(data, stream, ncopy);
|
||||
if(result) {
|
||||
return result;
|
||||
}
|
||||
#if 0 /* extra debugging of incoming h3 data */
|
||||
fprintf(stderr, "!! Copies %zd overflow bytes to %p (total %zd)\n",
|
||||
ncopy, stream->overflow_buf, stream->overflow_buflen);
|
||||
#endif
|
||||
memcpy(stream->overflow_buf + stream->overflow_buflen, buf, ncopy);
|
||||
stream->overflow_buflen += ncopy;
|
||||
}
|
||||
#if 0 /* extra debugging of incoming h3 data */
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < memlen; i++) {
|
||||
fprintf(stderr, "!! data[%d]: %02x '%c'\n", i, buf[i], buf[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(ncopy)
|
||||
result = Curl_dyn_addn(&stream->overflow, buf, ncopy);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1120,7 +1054,7 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream_id,
|
||||
CURLcode result = CURLE_OK;
|
||||
(void)conn;
|
||||
|
||||
result = write_data(data, stream, buf, buflen);
|
||||
result = write_data(stream, buf, buflen);
|
||||
if(result) {
|
||||
return -1;
|
||||
}
|
||||
@ -1183,7 +1117,7 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
|
||||
|
||||
/* add a CRLF only if we've received some headers */
|
||||
if(stream->firstheader) {
|
||||
result = write_data(data, stream, "\r\n", 2);
|
||||
result = write_data(stream, "\r\n", 2);
|
||||
if(result) {
|
||||
return -1;
|
||||
}
|
||||
@ -1214,26 +1148,26 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
|
||||
int status = decode_status_code(h3val.base, h3val.len);
|
||||
DEBUGASSERT(status != -1);
|
||||
ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n", status);
|
||||
result = write_data(data, stream, line, ncopy);
|
||||
result = write_data(stream, line, ncopy);
|
||||
if(result) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* store as a HTTP1-style header */
|
||||
result = write_data(data, stream, h3name.base, h3name.len);
|
||||
result = write_data(stream, h3name.base, h3name.len);
|
||||
if(result) {
|
||||
return -1;
|
||||
}
|
||||
result = write_data(data, stream, ": ", 2);
|
||||
result = write_data(stream, ": ", 2);
|
||||
if(result) {
|
||||
return -1;
|
||||
}
|
||||
result = write_data(data, stream, h3val.base, h3val.len);
|
||||
result = write_data(stream, h3val.base, h3val.len);
|
||||
if(result) {
|
||||
return -1;
|
||||
}
|
||||
result = write_data(data, stream, "\r\n", 2);
|
||||
result = write_data(stream, "\r\n", 2);
|
||||
if(result) {
|
||||
return -1;
|
||||
}
|
||||
@ -1341,15 +1275,16 @@ static Curl_send ngh3_stream_send;
|
||||
|
||||
static size_t drain_overflow_buffer(struct HTTP *stream)
|
||||
{
|
||||
size_t ncopy = CURLMIN(stream->overflow_buflen, stream->len);
|
||||
size_t overlen = Curl_dyn_len(&stream->overflow);
|
||||
size_t ncopy = CURLMIN(overlen, stream->len);
|
||||
if(ncopy > 0) {
|
||||
memcpy(stream->mem, stream->overflow_buf, ncopy);
|
||||
memcpy(stream->mem, Curl_dyn_ptr(&stream->overflow), ncopy);
|
||||
stream->len -= ncopy;
|
||||
stream->mem += ncopy;
|
||||
stream->memlen += ncopy;
|
||||
stream->overflow_buflen -= ncopy;
|
||||
memmove(stream->overflow_buf, stream->overflow_buf + ncopy,
|
||||
stream->overflow_buflen);
|
||||
if(ncopy != overlen)
|
||||
/* make the buffer only keep the tail */
|
||||
(void)Curl_dyn_tail(&stream->overflow, overlen - ncopy);
|
||||
}
|
||||
return ncopy;
|
||||
}
|
||||
@ -1528,6 +1463,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
|
||||
|
||||
stream->stream3_id = stream3_id;
|
||||
stream->h3req = TRUE; /* senf off! */
|
||||
Curl_dyn_init(&stream->overflow, CURL_MAX_READ_SIZE);
|
||||
|
||||
/* Calculate number of headers contained in [mem, mem + len). Assumes a
|
||||
correctly generated HTTP header field block. */
|
||||
@ -2032,7 +1968,7 @@ void Curl_quic_done(struct Curl_easy *data, bool premature)
|
||||
if(data->conn->handler == &Curl_handler_http3) {
|
||||
/* only for HTTP/3 transfers */
|
||||
struct HTTP *stream = data->req.protop;
|
||||
Curl_safefree(stream->overflow_buf);
|
||||
Curl_dyn_free(&stream->overflow);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2047,7 +1983,7 @@ bool Curl_quic_data_pending(const struct Curl_easy *data)
|
||||
there's no more data coming on the socket, we need to keep reading
|
||||
until the overflow buffer is empty. */
|
||||
const struct HTTP *stream = data->req.protop;
|
||||
return stream->overflow_buflen > 0;
|
||||
return Curl_dyn_len(&stream->overflow) > 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user