diff options
Diffstat (limited to 'http.c')
| -rw-r--r-- | http.c | 149 |
1 files changed, 106 insertions, 43 deletions
@@ -102,6 +102,7 @@ struct http_ctx size_t n_args, n_headers; struct http_header *headers; bool has_length, expect_continue; + int (*response)(struct http_ctx *); } ctx; struct write_ctx @@ -1211,15 +1212,22 @@ static int process_payload(struct http_ctx *const h) { struct ctx *const c = &h->ctx; const struct http_payload p = ctx_to_payload(c); + struct http_response *const r = &h->wctx.r; const int ret = h->cfg.payload(&p, &h->wctx.r, h->cfg.user); - h->wctx.op = c->op; - ctx_free(c); - if (ret) + { + ctx_free(c); return ret; + } + else if (!r->step) + { + h->wctx.op = c->op; + ctx_free(c); + return start_response(h); + } - return start_response(h); + return 0; } static int get_field_value(const char *const line, size_t *const n, @@ -1470,6 +1478,7 @@ static int check_length(struct http_ctx *const h) static int process_expect(struct http_ctx *const h) { struct ctx *const c = &h->ctx; + struct write_ctx *const w = &h->wctx; const int res = check_length(h); if (res) @@ -1480,7 +1489,7 @@ static int process_expect(struct http_ctx *const h) return res; } - h->wctx.close = true; + w->close = true; return start_response(h); } @@ -1488,36 +1497,51 @@ static int process_expect(struct http_ctx *const h) p.expect_continue = true; - const int ret = h->cfg.payload(&p, &h->wctx.r, h->cfg.user); - - h->wctx.op = c->op; + struct http_response *const r = &h->wctx.r; + const int ret = h->cfg.payload(&p, r, h->cfg.user); if (ret) + { + ctx_free(c); return ret; + } + else if (!r->step) + { + w->op = c->op; + c->state = BODY_LINE; + return start_response(h); + } - c->state = BODY_LINE; - return start_response(h); + return 0; } static int process_get(struct http_ctx *const h) { + int ret; struct ctx *const c = &h->ctx; struct http_payload p = ctx_to_payload(c); struct write_ctx *const w = &h->wctx; + struct http_response *const r = &w->r; p.u.get.range = w->gr = c->u2.get.range; - const int ret = h->cfg.payload(&p, &h->wctx.r, h->cfg.user); + if ((ret = h->cfg.payload(&p, &h->wctx.r, h->cfg.user))) + { + ctx_free(c); + return ret; + } + else if (!r->step) + { + w->op = c->op; + ctx_free(c); - w->op = c->op; - ctx_free(c); + if (w->gr.state) + w->r.status = HTTP_STATUS_PARTIAL_CONTENT; - if (ret) - return ret; - else if (w->gr.state) - w->r.status = HTTP_STATUS_PARTIAL_CONTENT; + return start_response(h); + } - return start_response(h); + return 0; } static int header_cr_line(struct http_ctx *const h) @@ -1530,17 +1554,25 @@ static int header_cr_line(struct http_ctx *const h) switch (c->op) { case HTTP_OP_GET: - return process_get(h); + c->response = process_get; + return 0; case HTTP_OP_HEAD: - return process_payload(h); + c->response = process_payload; + return 0; case HTTP_OP_POST: { if (!c->u2.payload.len) - return process_payload(h); + { + c->response = process_payload; + return 0; + } else if (c->expect_continue) - return process_expect(h); + { + c->response = process_expect; + return 0; + } else if (c->boundary) { const int res = check_length(h); @@ -1571,9 +1603,15 @@ static int header_cr_line(struct http_ctx *const h) return 1; } else if (!c->u2.payload.len) - return process_payload(h); + { + c->response = process_payload; + return 0; + } else if (c->expect_continue) - return process_expect(h); + { + c->response = process_expect; + return 0; + } c->state = BODY_LINE; return 0; @@ -1594,14 +1632,21 @@ static int send_payload(struct http_ctx *const h, const struct http_payload *const p) { struct ctx *const c = &h->ctx; - const int ret = h->cfg.payload(p, &h->wctx.r, h->cfg.user); - - ctx_free(c); + struct http_response *const r = &h->wctx.r; + const int ret = h->cfg.payload(p, r, h->cfg.user); if (ret) + { + ctx_free(c); return ret; + } + else if (!r->step) + { + ctx_free(c); + return start_response(h); + } - return start_response(h); + return 0; } static int update_lstate(struct http_ctx *const h, @@ -2216,7 +2261,7 @@ static int read_mf_end_boundary(struct http_ctx *const h, /* Found end boundary. */ if (!*n) - return end_boundary(h); + c->response = end_boundary; else m->state = MF_END_BOUNDARY_CR_LINE; } @@ -2243,7 +2288,8 @@ static int process_mf_end_crlf(struct http_ctx *const h) return 1; } - return end_boundary(h); + h->ctx.response = end_boundary; + return 0; } static int read_multiform(struct http_ctx *const h, const char *const buf, @@ -2284,6 +2330,15 @@ static int read_multiform(struct http_ctx *const h, const char *const buf, return 0; } +static int send_line_payload(struct http_ctx *const h) +{ + struct ctx *const c = &h->ctx; + struct http_payload pl = ctx_to_payload(c); + + pl.u.post.data = h->line; + return send_payload(h, &pl); +} + static int read_body_to_mem(struct http_ctx *const h, const char *const buf, size_t *const sz) { @@ -2302,11 +2357,8 @@ static int read_body_to_mem(struct http_ctx *const h, const char *const buf, if (p->read >= p->len) { - struct http_payload pl = ctx_to_payload(c); - h->line[p->len] = '\0'; - pl.u.post.data = h->line; - return send_payload(h, &pl); + c->response = send_line_payload; } return 0; @@ -2396,6 +2448,15 @@ static int read_put_body_to_file(struct http_ctx *const h, return 0; } +static int send_put_payload(struct http_ctx *const h) +{ + struct ctx *const c = &h->ctx; + struct http_payload pl = ctx_to_payload(c); + + pl.u.put.tmpname = c->u.put.tmpname; + return send_payload(h, &pl); +} + static int read_to_file(struct http_ctx *const h, const char *const buf, size_t *const sz) { @@ -2405,12 +2466,7 @@ static int read_to_file(struct http_ctx *const h, const char *const buf, if (read_put_body_to_file(h, buf, sz)) return -1; else if (p->read >= p->len) - { - struct http_payload pl = ctx_to_payload(c); - - pl.u.put.tmpname = c->u.put.tmpname; - return send_payload(h, &pl); - } + c->response = send_put_payload; return 0; } @@ -2547,12 +2603,19 @@ failure: int http_update(struct http_ctx *const h, bool *const write, bool *const close) { + int ret; + struct ctx *const c = &h->ctx; + struct write_ctx *const w = &h->wctx; + struct http_response *const r = &w->r; + *close = false; - struct write_ctx *const w = &h->wctx; - const int ret = w->pending ? http_write(h, close) : http_read(h, close); + if (c->response) + ret = c->response(h); + else + ret = w->pending ? http_write(h, close) : http_read(h, close); - *write = w->pending; + *write = c->response || w->pending; return ret; } |
