aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/http.c4
-rw-r--r--lib/http.h5
-rw-r--r--lib/http2.c78
3 files changed, 69 insertions, 18 deletions
diff --git a/lib/http.c b/lib/http.c
index d307eabd5..f64a56546 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -176,6 +176,8 @@ static CURLcode http_disconnect(struct connectdata *conn, bool dead_connection)
if(http) {
Curl_add_buffer_free(http->header_recvbuf);
http->header_recvbuf = NULL; /* clear the pointer */
+ free(http->push_headers);
+ http->push_headers = NULL;
}
#else
(void)conn;
@@ -1492,6 +1494,8 @@ CURLcode Curl_http_done(struct connectdata *conn,
DEBUGF(infof(data, "free header_recvbuf!!\n"));
Curl_add_buffer_free(http->header_recvbuf);
http->header_recvbuf = NULL; /* clear the pointer */
+ free(http->push_headers);
+ http->push_headers = NULL;
}
#endif
diff --git a/lib/http.h b/lib/http.h
index 80ec68303..63ea4ace4 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -176,7 +176,10 @@ struct HTTP {
const uint8_t *upload_mem; /* points to a buffer to read from */
size_t upload_len; /* size of the buffer 'upload_mem' points to */
curl_off_t upload_left; /* number of bytes left to upload */
- Curl_send_buffer *push_recvbuf; /* store incoming push headers */
+
+ char **push_headers; /* allocated array */
+ size_t push_headers_used; /* number of entries filled in */
+ size_t push_headers_alloc; /* number of entries allocated */
#endif
};
diff --git a/lib/http2.c b/lib/http2.c
index 8f5b6930b..674a39c09 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -219,14 +219,42 @@ struct curl_pushheaders {
/*
* push header access function. Only to be used from within the push callback
*/
-struct curl_headerpair *curl_pushheader_bynum(struct curl_pushheaders *h,
- int num)
+char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num)
{
/* Verify that we got a good easy handle in the push header struct, mostly to
detect rubbish input fast(er). */
if(!h || !GOOD_EASY_HANDLE(h->data))
return NULL;
- (void)num;
+ else {
+ struct HTTP *stream = h->data->req.protop;
+ if(num < stream->push_headers_used)
+ return stream->push_headers[num];
+ }
+ return NULL;
+}
+
+/*
+ * push header access function. Only to be used from within the push callback
+ */
+char *curl_pushheader_byname(struct curl_pushheaders *h, char *header)
+{
+ /* Verify that we got a good easy handle in the push header struct, mostly to
+ detect rubbish input fast(er). */
+ if(!h || !GOOD_EASY_HANDLE(h->data) || !header)
+ return NULL;
+ else {
+ struct HTTP *stream = h->data->req.protop;
+ size_t len = strlen(header);
+ size_t i;
+ for(i=0; i<stream->push_headers_used; i++) {
+ if(!strncmp(header, stream->push_headers[i], len)) {
+ /* sub-match, make sure that it us followed by a colon */
+ if(stream->push_headers[i][len] != ':')
+ continue;
+ return &stream->push_headers[i][len+1];
+ }
+ }
+ }
return NULL;
}
@@ -283,13 +311,14 @@ static int push_promise(struct SessionHandle *data,
stream = data->req.protop;
-#ifdef CURLDEBUG
- fprintf(stderr, "PUSHHDR %s\n", stream->push_recvbuf->buffer);
-#endif
-
rv = data->multi->push_cb(data, newhandle,
- frame->nvlen, &heads,
+ stream->push_headers_used, &heads,
data->multi->push_userp);
+
+ /* free the headers array again */
+ free(stream->push_headers);
+ stream->push_headers = NULL;
+
if(rv) {
/* denied, kill off the new handle again */
(void)Curl_close(newhandle);
@@ -667,15 +696,30 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
/* Store received PUSH_PROMISE headers to be used when the subsequent
PUSH_PROMISE callback comes */
if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
- fprintf(stderr, "*** PUSH_PROMISE headers on stream %u for %u\n",
- stream_id,
- frame->push_promise.promised_stream_id);
- if(!stream->push_recvbuf)
- stream->push_recvbuf = Curl_add_buffer_init();
- Curl_add_buffer(stream->push_recvbuf, name, namelen);
- Curl_add_buffer(stream->push_recvbuf, ":", 1);
- Curl_add_buffer(stream->push_recvbuf, value, valuelen);
- Curl_add_buffer(stream->push_recvbuf, "\r\n", 2);
+ char *h;
+
+ if(!stream->push_headers) {
+ stream->push_headers_alloc = 10;
+ stream->push_headers = malloc(stream->push_headers_alloc *
+ sizeof(char *));
+ stream->push_headers_used = 0;
+ }
+ else if(stream->push_headers_used ==
+ stream->push_headers_alloc) {
+ char **headp;
+ stream->push_headers_alloc *= 2;
+ headp = realloc(stream->push_headers,
+ stream->push_headers_alloc * sizeof(char *));
+ if(!headp) {
+ free(stream->push_headers);
+ stream->push_headers = NULL;
+ return 1;
+ }
+ stream->push_headers = headp;
+ }
+ h = aprintf("%s:%s", name, value);
+ if(h)
+ stream->push_headers[stream->push_headers_used++] = h;
return 0;
}