+ struct dispatch *d = &cl->dispatch;
+ struct http_request *r = &cl->request;
+ int consumed = 0;
+ int cur_len = 0;
+
+ if (!d->data_send)
+ return false;
+
+ while (len) {
+ char *sep;
+
+ r->content_length -= cur_len;
+ consumed += cur_len;
+ buf += cur_len;
+ len -= cur_len;
+ cur_len = min(r->content_length, len);
+
+ if (cur_len) {
+ if (d->data_send)
+ d->data_send(cl, buf, cur_len);
+ continue;
+ }
+
+ if (!r->transfer_chunked)
+ break;
+
+ sep = strstr(buf, "\r\n");
+ if (!sep)
+ break;
+
+ *sep = 0;
+ cur_len = sep + 2 - buf;
+
+ r->content_length = strtoul(buf, &sep, 16);
+
+ /* invalid chunk length */
+ if (sep && *sep)
+ return false;
+
+ /* empty chunk == eof */
+ if (!r->content_length) {
+ r->transfer_chunked = false;
+ continue;
+ }
+ }
+
+ ustream_consume(cl->us, consumed);
+ return r->content_length || r->transfer_chunked;