mirror of
https://github.com/curl/curl.git
synced 2024-11-21 01:16:58 +08:00
http2: fixed the header accessor functions for the push callback
This commit is contained in:
parent
feea9263e9
commit
f65ab8864e
@ -27,15 +27,8 @@ CURLMOPT_PUSHFUNCTION \- approve or deny server pushes
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
struct curl_headerpair {
|
||||
unsigned char *name; /* zero terminated name */
|
||||
size_t namelen; /* length of 'name' */
|
||||
unsigned char *value; /* zero terminated name */
|
||||
size_t valuelen; /* length of 'value' */
|
||||
};
|
||||
|
||||
struct curl_headerpair *curl_pushheader_bynum(push_headers, int num);
|
||||
struct curl_headerpair *curl_pushheader_byname(push_headers, char *name);
|
||||
char *curl_pushheader_bynum(push_headers, int num);
|
||||
char *curl_pushheader_byname(push_headers, char *name);
|
||||
|
||||
int curl_push_callback(CURL *parent,
|
||||
CURL *easy,
|
||||
@ -78,12 +71,12 @@ functions. These functions can only be used from within this callback and they
|
||||
can only access the PUSH_PROMISE headers. The normal response headers will be
|
||||
pased to the header callback for pushed streams just as for normal streams.
|
||||
.IP curl_pushheader_bynum
|
||||
Returns the header pair at index 'num' (or NULL). The returned pointer points
|
||||
to a struct that will be freed when this callback returns.
|
||||
Returns the header at index 'num' (or NULL). The returned pointer points
|
||||
to a "name:value" string that will be freed when this callback returns.
|
||||
.IP curl_pushheader_byname
|
||||
Returns the header pair for the given header name (or NULL). This is a
|
||||
shortcut so that the application doesn't have to loop through all headers to
|
||||
find the one it is interested in.
|
||||
Returns the value for the given header name (or NULL). This is a shortcut so
|
||||
that the application doesn't have to loop through all headers to find the one
|
||||
it is interested in.
|
||||
.SH CALLBACK RETURN VALUE
|
||||
.IP "CURL_PUSH_OK (0)"
|
||||
The application has accepted the stream and it can now start receiving data,
|
||||
|
@ -294,18 +294,13 @@ typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
|
||||
#define CURL_PUSH_OK 0
|
||||
#define CURL_PUSH_DENY 1
|
||||
|
||||
struct curl_headerpair {
|
||||
unsigned char *name; /* zero terminated name */
|
||||
size_t namelen; /* length of 'name' */
|
||||
unsigned char *value; /* zero terminated name */
|
||||
size_t valuelen; /* length of 'value' */
|
||||
};
|
||||
|
||||
struct curl_pushheaders; /* forward declaration only */
|
||||
struct curl_headerpair *curl_pushheader_bynum(struct curl_pushheaders *h,
|
||||
int num);
|
||||
struct curl_headerpair *curl_pushheader_byname(struct curl_pushheaders *h,
|
||||
char *name);
|
||||
|
||||
CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h,
|
||||
size_t num);
|
||||
|
||||
CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h,
|
||||
char *name);
|
||||
|
||||
typedef int (*curl_push_callback)(CURL *parent,
|
||||
CURL *easy,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
78
lib/http2.c
78
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user