
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
#include <ngx_http.h>


static void ngx_http_read_client_request_body_handler(ngx_event_t *rev);


int ngx_http_read_client_request_body(ngx_http_request_t *r,
                                      int request_buffer_size)
{
    ssize_t       size;
    ngx_hunk_t   *h;
    ngx_chain_t  *cl;

    size = r->header_in->last - r->header_in->pos;

    if (size) {
        ngx_test_null(h, ngx_calloc_hunk(r->pool),
                      NGX_HTTP_INTERNAL_SERVER_ERROR);

        h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
        h->start = h->pos = r->header_in->pos;
        h->end = h->last = r->header_in->last;

        ngx_alloc_link_and_set_hunk(r->request_hunks, h, r->pool,
                                    NGX_HTTP_INTERNAL_SERVER_ERROR);

        if (size >= r->headers_in.content_length_n) {
            r->header_in->pos += r->headers_in.content_length_n;

            return NGX_OK;
        }

        r->header_in->pos = r->header_in->last;
    }

    r->request_body_len = r->headers_in.content_length_n - size;

    if (r->request_body_len < request_buffer_size + (request_buffer_size >> 2))
    {
        size = r->request_body_len;

    } else {
        size = request_buffer_size;
    }

    ngx_test_null(r->request_body_hunk,
                  ngx_create_temp_hunk(r->pool, size, 0, 0),
                  NGX_HTTP_INTERNAL_SERVER_ERROR);

    r->connection->read->event_handler =
                                     ngx_http_read_client_request_body_handler;

    ngx_http_read_client_request_body_handler(r->connection->read);

    ngx_alloc_link_and_set_hunk(cl, r->request_body_hunk, r->pool,
                                NGX_HTTP_INTERNAL_SERVER_ERROR);

    if (r->request_hunks) {
        r->request_hunks->next = cl;

    } else {
        r->request_hunks = cl;
    }

    if (r->request_body_len) {
        return NGX_AGAIN;
    }

    return NGX_OK;
}


static void ngx_http_read_client_request_body_handler(ngx_event_t *rev)
{
    ssize_t                    n, size;
    ngx_hunk_t                *h;
    ngx_connection_t          *c;
    ngx_http_request_t        *r;
    ngx_http_core_loc_conf_t  *clcf;

    c = rev->data;
    r = c->data;

    if (r->request_body_hunk->end - r->request_body_hunk->last == 0) {
        n = ngx_write_chain_to_temp_file(r->temp_file,
                               r->request_hunks->next ? r->request_hunks->next:
                                                        r->request_hunks);
        /* TODO: n == 0 or not complete and level event */

        if (n == NGX_ERROR) {
            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
            return;
        }

        r->request_body_hunk->pos = r->request_body_hunk->start;
        r->request_body_hunk->last = r->request_body_hunk->start;
    }

    size = r->request_body_hunk->end - r->request_body_hunk->last;

    if (size > r->request_body_len) {
        size = r->request_body_len;
    }

    n = ngx_recv(c, r->request_body_hunk->last, size);

    if (n == NGX_AGAIN) {
        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
        ngx_add_timer(rev, clcf->client_body_timeout);

        if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        }

        return;
    }

    if (n == 0) {
        ngx_log_error(NGX_LOG_INFO, c->log, 0,
                      "client closed prematurely connection");
    }

    if (n == 0 || n == NGX_ERROR) {
        ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
        return;
    }

    r->request_body_hunk->last += n;
    r->request_body_len -= n;

    if (r->request_body_len) {
        return;
    }

    if (r->temp_file->file.fd != NGX_INVALID_FILE) {

        /* save the last part */
        n = ngx_write_chain_to_temp_file(r->temp_file,
                               r->request_hunks->next ? r->request_hunks->next:
                                                        r->request_hunks);
        /* TODO: n == 0 or not complete and level event */

        if (n == NGX_ERROR) {
            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
            return;
        }

        h = ngx_calloc_hunk(r->pool);
        if (h == NULL) {
            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
            return;
        }

        h->type = NGX_HUNK_FILE;
        h->file_pos = 0;
        h->file_last = r->temp_file->file.offset;
        h->file = &r->temp_file->file;

        if (r->request_hunks->next) {
            r->request_hunks->next->hunk = h;

        } else {
            r->request_hunks->hunk = h;
        }
    }

    r->request_body_handler(r->data);
}
