From 8901c141c9bef59baf308764c8c0f4dcadc6a487 Mon Sep 17 00:00:00 2001 From: Niels Provos Date: Wed, 14 Feb 2007 06:10:32 +0000 Subject: [PATCH] make chunked requests work correctly; this is done by providing a separate callback for invidiual chunks. if this callback is not set, all the data is going to be delivered at the end. svn:r327 --- evhttp.h | 9 +++++++++ http.c | 38 ++++++++++++++++++++++++++------------ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/evhttp.h b/evhttp.h index ecb9bfbb..3f33c487 100644 --- a/evhttp.h +++ b/evhttp.h @@ -138,6 +138,13 @@ struct evhttp_request { /* Callback */ void (*cb)(struct evhttp_request *, void *); void *cb_arg; + + /* + * Chunked data callback - call for each completed chunk if + * specified. If not specified, all the data is delivered via + * the regular callback. + */ + void (*chunk_cb)(struct evhttp_request *, void *); }; /* @@ -147,6 +154,8 @@ struct evhttp_request { */ struct evhttp_request *evhttp_request_new( void (*cb)(struct evhttp_request *, void *), void *arg); +void evhttp_request_set_chunked_cb(struct evhttp_request *, + void (*cb)(struct evhttp_request *, void *)); /* Frees the request object and removes associated events. */ void evhttp_request_free(struct evhttp_request *req); diff --git a/http.c b/http.c index cb98e276..281434cc 100644 --- a/http.c +++ b/http.c @@ -631,6 +631,9 @@ evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf) int error; if (p == NULL) break; + /* the last chunk is on a new line? */ + if (strlen(p) == 0) + continue; req->ntoread = strtol(p, &endp, 16); error = *p == '\0' || *endp != '\0'; free(p); @@ -642,18 +645,22 @@ evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf) /* Last chunk */ return (1); } - } else if (len >= req->ntoread) { - /* Completed chunk */ - evbuffer_add(req->input_buffer, - EVBUFFER_DATA(buf), req->ntoread); - evbuffer_drain(buf, req->ntoread); - req->ntoread = -1; - if (req->cb != NULL) { - (*req->cb)(req, req->cb_arg); - /* XXX(niels): not sure if i like semantics */ - evbuffer_drain(req->input_buffer, - EVBUFFER_LENGTH(req->input_buffer)); - } + continue; + } + + /* don't have enough to complete a chunk; wait for more */ + if (len < req->ntoread) + return (0); + + /* Completed chunk */ + evbuffer_add(req->input_buffer, + EVBUFFER_DATA(buf), req->ntoread); + evbuffer_drain(buf, req->ntoread); + req->ntoread = -1; + if (req->chunk_cb != NULL) { + (*req->chunk_cb)(req, req->cb_arg); + evbuffer_drain(req->input_buffer, + EVBUFFER_LENGTH(req->input_buffer)); } } @@ -2029,6 +2036,13 @@ evhttp_request_free(struct evhttp_request *req) free(req); } +void +evhttp_request_set_chunked_cb(struct evhttp_request *req, + void (*cb)(struct evhttp_request *, void *)) +{ + req->chunk_cb = cb; +} + /* * Allows for inspection of the request URI */ -- 2.40.0