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
This commit is contained in:
Niels Provos 2007-02-14 06:10:32 +00:00
parent 36950cef58
commit 8901c141c9
2 changed files with 35 additions and 12 deletions

View File

@ -138,6 +138,13 @@ struct evhttp_request {
/* Callback */ /* Callback */
void (*cb)(struct evhttp_request *, void *); void (*cb)(struct evhttp_request *, void *);
void *cb_arg; 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( struct evhttp_request *evhttp_request_new(
void (*cb)(struct evhttp_request *, void *), void *arg); 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. */ /* Frees the request object and removes associated events. */
void evhttp_request_free(struct evhttp_request *req); void evhttp_request_free(struct evhttp_request *req);

38
http.c
View File

@ -631,6 +631,9 @@ evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
int error; int error;
if (p == NULL) if (p == NULL)
break; break;
/* the last chunk is on a new line? */
if (strlen(p) == 0)
continue;
req->ntoread = strtol(p, &endp, 16); req->ntoread = strtol(p, &endp, 16);
error = *p == '\0' || *endp != '\0'; error = *p == '\0' || *endp != '\0';
free(p); free(p);
@ -642,18 +645,22 @@ evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
/* Last chunk */ /* Last chunk */
return (1); return (1);
} }
} else if (len >= req->ntoread) { continue;
/* Completed chunk */ }
evbuffer_add(req->input_buffer,
EVBUFFER_DATA(buf), req->ntoread); /* don't have enough to complete a chunk; wait for more */
evbuffer_drain(buf, req->ntoread); if (len < req->ntoread)
req->ntoread = -1; return (0);
if (req->cb != NULL) {
(*req->cb)(req, req->cb_arg); /* Completed chunk */
/* XXX(niels): not sure if i like semantics */ evbuffer_add(req->input_buffer,
evbuffer_drain(req->input_buffer, EVBUFFER_DATA(buf), req->ntoread);
EVBUFFER_LENGTH(req->input_buffer)); 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); 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 * Allows for inspection of the request URI
*/ */