summaryrefslogtreecommitdiff
path: root/lib/http2.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2020-05-02 17:04:08 +0200
committerDaniel Stenberg <daniel@haxx.se>2020-05-04 10:40:39 +0200
commited35d6590e72c23c568af1e3b8ac6e4e2d883888 (patch)
tree57555732f4f452bf84c3c7296581485be064a853 /lib/http2.c
parent00c2e8da9a9555ce6171e3f7ddc5e43fc6f9bb4b (diff)
downloadcurl-ed35d6590e72c23c568af1e3b8ac6e4e2d883888.tar.gz
dynbuf: introduce internal generic dynamic buffer functions
A common set of functions instead of many separate implementations for creating buffers that can grow when appending data to them. Existing functionality has been ported over. In my early basic testing, the total number of allocations seem at roughly the same amount as before, possibly a few less. See docs/DYNBUF.md for a description of the API. Closes #5300
Diffstat (limited to 'lib/http2.c')
-rw-r--r--lib/http2.c115
1 files changed, 50 insertions, 65 deletions
diff --git a/lib/http2.c b/lib/http2.c
index 93dfbdb7d..2ca0fdeb2 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -36,6 +36,7 @@
#include "connect.h"
#include "strtoofft.h"
#include "strdup.h"
+#include "dynbuf.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -124,8 +125,8 @@ static int http2_getsock(struct connectdata *conn,
static void http2_stream_free(struct HTTP *http)
{
if(http) {
- Curl_add_buffer_free(&http->header_recvbuf);
- Curl_add_buffer_free(&http->trailer_recvbuf);
+ Curl_dyn_free(&http->header_recvbuf);
+ Curl_dyn_free(&http->trailer_recvbuf);
for(; http->push_headers_used > 0; --http->push_headers_used) {
free(http->push_headers[http->push_headers_used - 1]);
}
@@ -259,7 +260,6 @@ void Curl_http2_setup_req(struct Curl_easy *data)
{
struct HTTP *http = data->req.protop;
- http->nread_header_recvbuf = 0;
http->bodystarted = FALSE;
http->status_code = -1;
http->pausedata = NULL;
@@ -463,15 +463,9 @@ static struct Curl_easy *duphandle(struct Curl_easy *data)
}
else {
second->req.protop = http;
- http->header_recvbuf = Curl_add_buffer_init();
- if(!http->header_recvbuf) {
- free(http);
- (void)Curl_close(&second);
- }
- else {
- Curl_http2_setup_req(second);
- second->state.stream_weight = data->state.stream_weight;
- }
+ Curl_dyn_init(&http->header_recvbuf, DYN_H2_HEADERS);
+ Curl_http2_setup_req(second);
+ second->state.stream_weight = data->state.stream_weight;
}
}
return second;
@@ -668,15 +662,17 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
stream->status_code = -1;
}
- result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
+ result = Curl_dyn_add(&stream->header_recvbuf, "\r\n");
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
+ left = Curl_dyn_len(&stream->header_recvbuf) -
+ stream->nread_header_recvbuf;
ncopy = CURLMIN(stream->len, left);
memcpy(&stream->mem[stream->memlen],
- stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
+ Curl_dyn_ptr(&stream->header_recvbuf) +
+ stream->nread_header_recvbuf,
ncopy);
stream->nread_header_recvbuf += ncopy;
@@ -852,12 +848,6 @@ static int on_begin_headers(nghttp2_session *session,
return 0;
}
- if(!stream->trailer_recvbuf) {
- stream->trailer_recvbuf = Curl_add_buffer_init();
- if(!stream->trailer_recvbuf) {
- return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
- }
- }
return 0;
}
@@ -980,19 +970,19 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
value));
- result = Curl_add_buffer(&stream->trailer_recvbuf, &n, sizeof(n));
+ result = Curl_dyn_addn(&stream->trailer_recvbuf, &n, sizeof(n));
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->trailer_recvbuf, name, namelen);
+ result = Curl_dyn_addn(&stream->trailer_recvbuf, name, namelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->trailer_recvbuf, ": ", 2);
+ result = Curl_dyn_add(&stream->trailer_recvbuf, ": ");
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->trailer_recvbuf, value, valuelen);
+ result = Curl_dyn_addn(&stream->trailer_recvbuf, value, valuelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->trailer_recvbuf, "\r\n\0", 3);
+ result = Curl_dyn_add(&stream->trailer_recvbuf, "\r\n\0");
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -1007,14 +997,14 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
stream->status_code = decode_status_code(value, valuelen);
DEBUGASSERT(stream->status_code != -1);
- result = Curl_add_buffer(&stream->header_recvbuf, "HTTP/2 ", 7);
+ result = Curl_dyn_add(&stream->header_recvbuf, "HTTP/2 ");
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
+ result = Curl_dyn_addn(&stream->header_recvbuf, value, valuelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* the space character after the status code is mandatory */
- result = Curl_add_buffer(&stream->header_recvbuf, " \r\n", 3);
+ result = Curl_dyn_add(&stream->header_recvbuf, " \r\n");
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
@@ -1029,16 +1019,16 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
/* nghttp2 guarantees that namelen > 0, and :status was already
received, and this is not pseudo-header field . */
/* convert to a HTTP1-style header */
- result = Curl_add_buffer(&stream->header_recvbuf, name, namelen);
+ result = Curl_dyn_addn(&stream->header_recvbuf, name, namelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->header_recvbuf, ": ", 2);
+ result = Curl_dyn_add(&stream->header_recvbuf, ": ");
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
+ result = Curl_dyn_addn(&stream->header_recvbuf, value, valuelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
+ result = Curl_dyn_add(&stream->header_recvbuf, "\r\n");
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
@@ -1139,17 +1129,15 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
/* there might be allocated resources done before this got the 'h2' pointer
setup */
- if(http->header_recvbuf) {
- Curl_add_buffer_free(&http->header_recvbuf);
- Curl_add_buffer_free(&http->trailer_recvbuf);
- if(http->push_headers) {
- /* if they weren't used and then freed before */
- for(; http->push_headers_used > 0; --http->push_headers_used) {
- free(http->push_headers[http->push_headers_used - 1]);
- }
- free(http->push_headers);
- http->push_headers = NULL;
+ Curl_dyn_free(&http->header_recvbuf);
+ Curl_dyn_free(&http->trailer_recvbuf);
+ if(http->push_headers) {
+ /* if they weren't used and then freed before */
+ for(; http->push_headers_used > 0; --http->push_headers_used) {
+ free(http->push_headers[http->push_headers_used - 1]);
}
+ free(http->push_headers);
+ http->push_headers = NULL;
}
if(!httpc->h2) /* not HTTP/2 ? */
@@ -1238,7 +1226,7 @@ static CURLcode http2_init(struct connectdata *conn)
/*
* Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
*/
-CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
+CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
struct connectdata *conn)
{
CURLcode result;
@@ -1257,7 +1245,7 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
httpc->local_settings_num);
if(!binlen) {
failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
- Curl_add_buffer_free(&req);
+ Curl_dyn_free(req);
return CURLE_FAILED_INIT;
}
conn->proto.httpc.binlen = binlen;
@@ -1265,15 +1253,15 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
&base64, &blen);
if(result) {
- Curl_add_buffer_free(&req);
+ Curl_dyn_free(req);
return result;
}
- result = Curl_add_bufferf(&req,
- "Connection: Upgrade, HTTP2-Settings\r\n"
- "Upgrade: %s\r\n"
- "HTTP2-Settings: %s\r\n",
- NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
+ result = Curl_dyn_addf(req,
+ "Connection: Upgrade, HTTP2-Settings\r\n"
+ "Upgrade: %s\r\n"
+ "HTTP2-Settings: %s\r\n",
+ NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
free(base64);
k->upgr101 = UPGR101_REQUESTED;
@@ -1432,9 +1420,9 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
return -1;
}
- if(stream->trailer_recvbuf && stream->trailer_recvbuf->buffer) {
- trailer_pos = stream->trailer_recvbuf->buffer;
- trailer_end = trailer_pos + stream->trailer_recvbuf->size_used;
+ if(Curl_dyn_len(&stream->trailer_recvbuf)) {
+ trailer_pos = Curl_dyn_ptr(&stream->trailer_recvbuf);
+ trailer_end = trailer_pos + Curl_dyn_len(&stream->trailer_recvbuf);
for(; trailer_pos < trailer_end;) {
uint32_t n;
@@ -1541,13 +1529,13 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
*/
if(stream->bodystarted &&
- stream->nread_header_recvbuf < stream->header_recvbuf->size_used) {
- /* If there is body data pending for this stream to return, do that */
+ stream->nread_header_recvbuf < Curl_dyn_len(&stream->header_recvbuf)) {
+ /* If there is header data pending for this stream to return, do that */
size_t left =
- stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
+ Curl_dyn_len(&stream->header_recvbuf) - stream->nread_header_recvbuf;
size_t ncopy = CURLMIN(len, left);
- memcpy(mem, stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
- ncopy);
+ memcpy(mem, Curl_dyn_ptr(&stream->header_recvbuf) +
+ stream->nread_header_recvbuf, ncopy);
stream->nread_header_recvbuf += ncopy;
H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n",
@@ -2129,11 +2117,8 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
stream->stream_id = -1;
- if(!stream->header_recvbuf) {
- stream->header_recvbuf = Curl_add_buffer_init();
- if(!stream->header_recvbuf)
- return CURLE_OUT_OF_MEMORY;
- }
+ Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS);
+ Curl_dyn_init(&stream->trailer_recvbuf, DYN_H2_TRAILERS);
if((conn->handler == &Curl_handler_http2_ssl) ||
(conn->handler == &Curl_handler_http2))
@@ -2146,7 +2131,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
result = http2_init(conn);
if(result) {
- Curl_add_buffer_free(&stream->header_recvbuf);
+ Curl_dyn_free(&stream->header_recvbuf);
return result;
}