diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/http.c | 4 | ||||
-rw-r--r-- | lib/http.h | 5 | ||||
-rw-r--r-- | lib/http2.c | 78 |
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; } |