write.c 2.86 KB
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "class.h"
#include "interface/class.h"
#include "http/message.h"
#include "http/response.h"
#include "http/response/writer.h"

HttpResponse
httpResponseWriterWrite(HttpResponseWriter this, int fd)
{
	HttpMessageQueue respq   = this->response_queue;
	HttpResponse     retval  = this->cur_response;
	HttpMessage      message = (HttpMessage)this->cur_response;
	int              cont    = 1;

	while (cont) {
		switch (this->state) {
			case HTTP_RESPONSE_GET:
				if (NULL == this->cur_response && 0 < respq->nmsgs) {
					message = respq->msgs[0];
					retval  = this->cur_response = (HttpResponse)message;

					memmove(respq->msgs,
							&(respq->msgs[1]),
							sizeof(void*) * (--respq->nmsgs + 1));

					this->nbuffer = 0;
					this->written = 0;
					this->pstart  = 0;
					this->pend    = httpMessageHeaderSizeGet(message);
					this->nheader = this->pend;
					httpMessageHeaderToString(message, this->pipe);

					this->state = HTTP_RESPONSE_WRITE;
				}
				else {
					cont = 0;
				}
				break;

			case HTTP_RESPONSE_WRITE:
				/**
				 * read
				 */
				if (this->nbuffer < message->nbody) {
					size_t temp = 0;
					size_t rsize;

					this->pend = (RESPONSE_WRITER_BUF_SIZE == this->pend)?
						0 : this->pend;

					rsize = (this->pstart <= this->pend)?
						RESPONSE_WRITER_BUF_SIZE - this->pend :
						this->pstart - 1;

					switch (message->type) {
						case HTTP_MESSAGE_BUFFERED:
							temp = message->nbody - this->nbuffer;
							temp = (rsize<temp)?  rsize : temp;
							memcpy(
									&(this->pipe[this->pend]),
									&(message->body[this->nbuffer]),
									temp);

							break;

						case HTTP_MESSAGE_PIPED:
							temp = read(
									message->handle,
									&(this->pipe[this->pend]),
									rsize);
							break;
					}

					this->nbuffer += temp;
					this->pend    += temp;
				}

				/**
				 * write
				 */
				{
					size_t wsize;
					size_t temp;

					wsize = (this->pstart <= this->pend)?
						this->pend - this->pstart :
						RESPONSE_WRITER_BUF_SIZE - this->pstart;

					temp = write(fd, &(this->pipe[this->pstart]), wsize);

					this->written += temp;
					this->pstart  += temp;

					this->pstart = (RESPONSE_WRITER_BUF_SIZE == this->pstart)?
						0 : this->pstart;
				}

				if (this->written == message->nbody + this->nheader) {
					if (HTTP_MESSAGE_PIPED == message->type) {
						close(message->handle);
					}
					this->nheader = 0;
					this->nbuffer = 0;
					this->written = 0;
					this->pstart  = 0;
					this->pend    = 0;

					this->state = HTTP_RESPONSE_DONE;
				}
				else {
					cont = 0;
				}
				break;

			case HTTP_RESPONSE_DONE:
				this->cur_response = NULL;
	 			this->state = HTTP_RESPONSE_GET;
				cont = 0;

				break;
		}
	}

	return retval;
}

// vim: set ts=4 sw=4: