write.c 3.03 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 = httpMessageHeaderSizeGet(message);
					this->buffer  = malloc(this->nbuffer);
					this->written = 0;

					httpMessageHeaderToString(message, this->buffer);

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

			case HTTP_RESPONSE_HEADER:
				this->written += write(
						fd,
						&(this->buffer[this->written]),
						this->nbuffer - this->written);

				if (this->written == this->nbuffer) {
					free(this->buffer);
					this->buffer  = NULL;
					this->nbuffer = 0;
					this->written = 0;
					this->pstart  = 0;
					this->pend    = 0;

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

			case HTTP_RESPONSE_PIPE:
				switch (message->type) {
					case HTTP_MESSAGE_BUFFERED:
						this->written += write(
								fd,
								&(message->body[this->written]),
								message->nbody - this->written);
						break;

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

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

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

							temp = read(
									message->handle,
									&(this->pipe[this->pend]),
									rsize);

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

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

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

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

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

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

					default:
						break;
				}

				if (this->written == message->nbody) {
					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: