/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "fcgid_bucket.h"
#include "fcgid_protocol.h"
#include "fcgid_bridge.h"

#define FCGID_FEED_LEN 8192
static apr_status_t fcgid_feed_data(fcgid_bucket_ctx * ctx,
                                    apr_bucket_alloc_t * bucketalloc,
                                    char **buffer, apr_size_t * bufferlen)
{
    server_rec *main_server = ctx->ipc.request->server;
    apr_status_t rv;

    if (!ctx->buffer) {
        *buffer = apr_bucket_alloc(FCGID_FEED_LEN, bucketalloc);
        if (!buffer)
            return APR_ENOMEM;

        *bufferlen = FCGID_FEED_LEN;
        if ((rv =
             proc_read_ipc(main_server, &ctx->ipc, *buffer,
                           bufferlen)) != APR_SUCCESS) {
            ctx->has_error = 1;
            apr_bucket_free(*buffer);
            return rv;
        }

        ctx->buffer =
            apr_bucket_heap_create(*buffer, FCGID_FEED_LEN,
                                   apr_bucket_free, bucketalloc);
        if (*bufferlen != FCGID_FEED_LEN) {
            apr_bucket *buckettmp;

            apr_bucket_split(ctx->buffer, *bufferlen);
            buckettmp = APR_BUCKET_NEXT(ctx->buffer);
            apr_bucket_delete(buckettmp);
        }
    } else {
        apr_bucket_read(ctx->buffer, (const char **) buffer, bufferlen,
                        APR_BLOCK_READ);
    }
    return APR_SUCCESS;
}

static void fcgid_ignore_bytes(fcgid_bucket_ctx * ctx,
                               apr_size_t ignorebyte)
{
    apr_bucket *buckettmp;

    if (ignorebyte == ctx->buffer->length) {
        apr_bucket_destroy(ctx->buffer);
        ctx->buffer = NULL;
    } else {
        apr_bucket_split(ctx->buffer, ignorebyte);
        buckettmp = ctx->buffer;
        ctx->buffer = APR_BUCKET_NEXT(ctx->buffer);
        apr_bucket_delete(buckettmp);
    }
}

static apr_status_t fcgid_header_bucket_read(apr_bucket * b,
                                             const char **str,
                                             apr_size_t * len,
                                             apr_read_type_e block)
{
    fcgid_bucket_ctx *ctx = (fcgid_bucket_ctx *) b->data;
    server_rec *main_server = ctx->ipc.request->server;
    apr_status_t rv;
    apr_size_t hasread, bodysize;
    FCGI_Header header;
    apr_bucket *curbucket = b;

    /* Keep reading until I get a fastcgi header */
    hasread = 0;
    while (hasread < sizeof(header)) {
        char *buffer;
        apr_size_t bufferlen, putsize;

        /* Feed some data if necessary */
        if ((rv =
             fcgid_feed_data(ctx, b->list, &buffer,
                             &bufferlen)) != APR_SUCCESS)
            return rv;

        /* Initialize header */
        putsize = fcgid_min(bufferlen, sizeof(header) - hasread);
        memcpy(&header + hasread, buffer, putsize);
        hasread += putsize;

        /* Ignore the bytes that have read */
        fcgid_ignore_bytes(ctx, putsize);
    }

    /* Get the body size */
    bodysize = header.contentLengthB1;
    bodysize <<= 8;
    bodysize += header.contentLengthB0;

    /* Handle FCGI_STDERR body, write the content to log file */
    if (header.type == FCGI_STDERR) {
        char *logbuf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->list);
        char *line;

        if (!logbuf)
            return APR_ENOMEM;
        memset(logbuf, 0, APR_BUCKET_BUFF_SIZE);

        hasread = 0;
        while (hasread < bodysize) {
            char *buffer;
            apr_size_t bufferlen, canput, willput;

            /* Feed some data if necessary */
            if ((rv =
                 fcgid_feed_data(ctx, b->list, &buffer,
                                 &bufferlen)) != APR_SUCCESS) {
                apr_bucket_free(logbuf);
                return rv;
            }

            canput = fcgid_min(bufferlen, bodysize - hasread);
            willput =
                fcgid_min(canput, APR_BUCKET_BUFF_SIZE - hasread - 1);
            memcpy(logbuf + hasread, buffer, willput);
            hasread += canput;

            /* Ignore the "canput" bytes */
            fcgid_ignore_bytes(ctx, canput);
        }

        /* Now I get the log data, write log and release the buffer */
        line = logbuf;
        while (*line) {
            char *end = strpbrk(line, "\r\n");

            if (end != NULL) {
                *end = '\0';
            }
            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, main_server,
                         "mod_fcgid: stderr: %s", line);
            if (end == NULL) {
                break;
            }
            ++end;
            line = end + strspn(end, "\r\n");
        }

        apr_bucket_free(logbuf);
    }

    /* if( header.type==FCGI_STDERR ) */
    /* Now handle FCGI_STDOUT */
    else if (header.type == FCGI_STDOUT) {
        hasread = 0;
        while (hasread < bodysize) {
            char *buffer;
            apr_size_t bufferlen, canput;
            apr_bucket *buckettmp;

            /* Feed some data if necessary */
            if ((rv =
                 fcgid_feed_data(ctx, b->list, &buffer,
                                 &bufferlen)) != APR_SUCCESS)
                return rv;

            canput = fcgid_min(bufferlen, bodysize - hasread);

            /* Change the current bucket to refer to what we read */
            buckettmp = ctx->buffer;
            if (canput == (bodysize - hasread)) {
                apr_bucket_split(ctx->buffer, canput);
                ctx->buffer = APR_BUCKET_NEXT(ctx->buffer);
                APR_BUCKET_REMOVE(buckettmp);
            } else {
                /* canput==bufferlen */
                ctx->buffer = NULL;
            }

            APR_BUCKET_INSERT_AFTER(curbucket, buckettmp);
            curbucket = buckettmp;
            hasread += canput;
        }                       /* while( hasread<bodysize ) */
    }

    /* if( header.type==FCGI_STDOUT ) */
    /* Now FCGI_END_REQUEST */
    else if (header.type == FCGI_END_REQUEST) {
        /* Just ignore the body */
        hasread = 0;
        while (hasread < bodysize) {
            char *buffer;
            apr_size_t bufferlen, canignore;

            /* Feed some data if necessary */
            if ((rv =
                 fcgid_feed_data(ctx, b->list, &buffer,
                                 &bufferlen)) != APR_SUCCESS)
                return rv;

            canignore = fcgid_min(bufferlen, bodysize);
            hasread += canignore;

            /* Ignore the bytes */
            fcgid_ignore_bytes(ctx, canignore);
        }
    }

    /* Now ignore padding data */
    hasread = 0;
    while (hasread < header.paddingLength) {
        char *buffer;
        apr_size_t bufferlen, canignore;

        /* Feed some data if necessary */
        if ((rv =
             fcgid_feed_data(ctx, b->list, &buffer,
                             &bufferlen)) != APR_SUCCESS)
            return rv;

        canignore = fcgid_min(bufferlen, header.paddingLength - hasread);
        hasread += canignore;

        /* Ignore the bytes */
        fcgid_ignore_bytes(ctx, canignore);
    }

    /* Tail another fastcgi header bucket if it's not ending */
    if (header.type != FCGI_END_REQUEST) {
        apr_bucket *headerbucket =
            ap_bucket_fcgid_header_create(b->list, ctx);
        if (!headerbucket)
            return APR_ENOMEM;
        APR_BUCKET_INSERT_AFTER(curbucket, headerbucket);
    } else {
        /* Release the process ASAP */
        if ((rv = apr_pool_cleanup_run(ctx->ipc.request->pool,
                                       ctx,
                                       bucket_ctx_cleanup)) != APR_SUCCESS)
            return rv;
    }

    b = apr_bucket_immortal_make(b, "", 0);
    return apr_bucket_read(b, str, len, APR_BLOCK_READ);
}

apr_bucket *ap_bucket_fcgid_header_make(apr_bucket * b,
                                        fcgid_bucket_ctx * ctx)
{
    b->length = (apr_size_t) (-1);
    b->start = -1;
    b->data = ctx;
    b->type = &ap_bucket_type_fcgid_header;

    return b;
}

apr_bucket *ap_bucket_fcgid_header_create(apr_bucket_alloc_t * list,
                                          fcgid_bucket_ctx * ctx)
{
    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);

    APR_BUCKET_INIT(b);
    b->free = apr_bucket_free;
    b->list = list;
    return ap_bucket_fcgid_header_make(b, ctx);
}

const apr_bucket_type_t ap_bucket_type_fcgid_header = {
    "FCGID_HEADER", 5, APR_BUCKET_DATA,
    apr_bucket_destroy_noop,
    fcgid_header_bucket_read,
    apr_bucket_setaside_notimpl,
    apr_bucket_split_notimpl,
    apr_bucket_copy_notimpl
};
