.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,
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,
#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,
/*
* 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;
}
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);
/* 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;
}