summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_http_chunk_parse.c
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2020-06-23 14:16:45 +0300
committerIgor Sysoev <igor@sysoev.ru>2020-06-23 14:16:45 +0300
commit65799c7252e56d287d967bf3f036a10d5764f82c (patch)
tree70488dd10766b07784732fab1074dde526732fae /src/nxt_http_chunk_parse.c
parentf671d1bc54d6db164cf4b03a9ef0e1ddcdd39c72 (diff)
downloadunit-65799c7252e56d287d967bf3f036a10d5764f82c.tar.gz
unit-65799c7252e56d287d967bf3f036a10d5764f82c.tar.bz2
Upstream chunked transfer encoding support.
Diffstat (limited to 'src/nxt_http_chunk_parse.c')
-rw-r--r--src/nxt_http_chunk_parse.c113
1 files changed, 62 insertions, 51 deletions
diff --git a/src/nxt_http_chunk_parse.c b/src/nxt_http_chunk_parse.c
index 644b9805..2164524b 100644
--- a/src/nxt_http_chunk_parse.c
+++ b/src/nxt_http_chunk_parse.c
@@ -21,13 +21,17 @@ static nxt_int_t nxt_http_chunk_buffer(nxt_http_chunk_parse_t *hcp,
nxt_buf_t ***tail, nxt_buf_t *in);
+static void nxt_http_chunk_buf_completion(nxt_task_t *task, void *obj,
+ void *data);
+
+
nxt_buf_t *
nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp,
nxt_buf_t *in)
{
u_char c, ch;
nxt_int_t ret;
- nxt_buf_t *b, *out, *nb, **tail;
+ nxt_buf_t *b, *out, *next, **tail;
enum {
sw_start = 0,
sw_chunk_size,
@@ -37,12 +41,13 @@ nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp,
sw_chunk,
} state;
+ next = NULL;
out = NULL;
tail = &out;
state = hcp->state;
- for (b = in; b != NULL; b = b->next) {
+ for (b = in; b != NULL; b = next) {
hcp->pos = b->mem.pos;
@@ -60,7 +65,7 @@ nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp,
if (nxt_slow_path(ret == NXT_ERROR)) {
hcp->error = 1;
- goto done;
+ return out;
}
state = sw_chunk_end_newline;
@@ -152,7 +157,7 @@ nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp,
continue;
}
- goto done;
+ return out;
}
goto chunk_error;
@@ -168,15 +173,15 @@ nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp,
if (b->retain == 0) {
/* No chunk data was found in a buffer. */
- nxt_thread_current_work_queue_add(task->thread,
- b->completion_handler,
- task, b, b->parent);
+ nxt_work_queue_add(&task->thread->engine->fast_work_queue,
+ b->completion_handler, task, b, b->parent);
}
next:
- continue;
+ next = b->next;
+ b->next = NULL;
}
hcp->state = state;
@@ -187,20 +192,6 @@ chunk_error:
hcp->chunk_error = 1;
-done:
-
- nb = nxt_buf_sync_alloc(hcp->mem_pool, NXT_BUF_SYNC_LAST);
-
- if (nxt_fast_path(nb != NULL)) {
- *tail = nb;
-
- } else {
- hcp->error = 1;
- }
-
- // STUB: hcp->chunk_error = 1;
- // STUB: hcp->error = 1;
-
return out;
}
@@ -216,43 +207,35 @@ nxt_http_chunk_buffer(nxt_http_chunk_parse_t *hcp, nxt_buf_t ***tail,
p = hcp->pos;
size = in->mem.free - p;
- if (hcp->chunk_size >= size && in->retain == 0) {
- /*
- * Use original buffer if the buffer is lesser than or equal
- * to a chunk size and this is the first chunk in the buffer.
- */
- in->mem.pos = p;
- **tail = in;
- *tail = &in->next;
-
- } else {
- b = nxt_buf_mem_alloc(hcp->mem_pool, 0, 0);
- if (nxt_slow_path(b == NULL)) {
- return NXT_ERROR;
- }
+ b = nxt_buf_mem_alloc(hcp->mem_pool, 0, 0);
+ if (nxt_slow_path(b == NULL)) {
+ return NXT_ERROR;
+ }
- **tail = b;
- *tail = &b->next;
+ **tail = b;
+ *tail = &b->next;
- b->parent = in;
- in->retain++;
- b->mem.pos = p;
- b->mem.start = p;
+ nxt_mp_retain(hcp->mem_pool);
+ b->completion_handler = nxt_http_chunk_buf_completion;
- if (hcp->chunk_size < size) {
- p += hcp->chunk_size;
- hcp->pos = p;
+ b->parent = in;
+ in->retain++;
+ b->mem.pos = p;
+ b->mem.start = p;
- b->mem.free = p;
- b->mem.end = p;
+ if (hcp->chunk_size < size) {
+ p += hcp->chunk_size;
+ hcp->pos = p;
- return NXT_HTTP_CHUNK_END;
- }
+ b->mem.free = p;
+ b->mem.end = p;
- b->mem.free = in->mem.free;
- b->mem.end = in->mem.free;
+ return NXT_HTTP_CHUNK_END;
}
+ b->mem.free = in->mem.free;
+ b->mem.end = in->mem.free;
+
hcp->chunk_size -= size;
if (hcp->chunk_size == 0) {
@@ -261,3 +244,31 @@ nxt_http_chunk_buffer(nxt_http_chunk_parse_t *hcp, nxt_buf_t ***tail,
return NXT_HTTP_CHUNK_MIDDLE;
}
+
+
+static void
+nxt_http_chunk_buf_completion(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_mp_t *mp;
+ nxt_buf_t *b, *next, *parent;
+
+ b = obj;
+ parent = data;
+
+ nxt_debug(task, "buf completion: %p %p", b, b->mem.start);
+
+ nxt_assert(data == b->parent);
+
+ do {
+ next = b->next;
+ parent = b->parent;
+ mp = b->data;
+
+ nxt_mp_free(mp, b);
+ nxt_mp_release(mp);
+
+ nxt_buf_parent_completion(task, parent);
+
+ b = next;
+ } while (b != NULL);
+}