]> granicus.if.org Git - libevent/commitdiff
make chunked requests work correctly; this is done by providing
authorNiels Provos <provos@gmail.com>
Wed, 14 Feb 2007 06:10:32 +0000 (06:10 +0000)
committerNiels Provos <provos@gmail.com>
Wed, 14 Feb 2007 06:10:32 +0000 (06:10 +0000)
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
http.c

index ecb9bfbb024e246e53dd8a9862b5be24dd593318..3f33c4874b4d20d23d74b6cdffd9ac3aeb0b67b0 100644 (file)
--- 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 cb98e276b91aba2e92f21ef9baced3f3d8e6490c..281434cc23eebbb9a575ec163a96fc0d7678c262 100644 (file)
--- 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
  */