/*
 * 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
};
