write.c 2.71 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/response.h"
#include "http/response/writer.h"

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

	while (cont) {
		switch (this->state) {
			case HTTP_RESPONSE_NO:
				if (NULL == this->cur_response && 0 < respq->nmsgs) {
					retval = this->cur_response = (HttpResponse)respq->msgs[0];
					memmove(respq->msgs,
							&(respq->msgs[1]),
							sizeof(void*) * (--respq->nmsgs + 1));
					this->state = HTTP_RESPONSE_START;
				}
				else {
					cont = 0;
				}
				break;

			case HTTP_RESPONSE_START:
				if (HTTP_MESSAGE_PIPED ==
						((HttpMessage)(this->cur_response))->type) {
					struct stat st;
					HttpMessage message = (HttpMessage)this->cur_response;
					char buffer[200];

					message->handle =
						open("./assets/waldschrat.jpg", O_RDONLY);
					fstat(message->handle, &st);
					message->nbody = st.st_size;

					sprintf(buffer, "%d", message->nbody);
					httpHeaderAdd(&(message->header),
							new(HttpHeader, "Content-Length", buffer));

				}

				this->state = HTTP_RESPONSE_PIPE;
				break;

			case HTTP_RESPONSE_PIPE:
				{
					HttpMessage message  = (HttpMessage)(this->cur_response);
					size_t      headsize = httpResponseSizeGet(this->cur_response);

					this->buffer = malloc(headsize + message->nbody);
					httpResponseToString(this->cur_response, this->buffer);
					this->rpipe = headsize;

					if (HTTP_MESSAGE_PIPED == message->type &&
							0 != message->handle) {
						char * data = &(this->buffer[headsize]);
						size_t togo = message->nbody;

						size_t rsize = read(message->handle, data, togo);

						while (rsize < togo) {
							data += rsize;
							togo -= rsize;
							rsize = read(message->handle, data, togo);
						}

						this->wpipe = 0;
						this->rpipe += message->nbody;
						close(message->handle);
						message->handle = 0;
					}

					{
						char * data = &(this->buffer[this->wpipe]);
						size_t written;

						written = write(fd, data, this->rpipe - this->wpipe);
						data += written;
						this->wpipe += written;

						if (this->rpipe == this->wpipe) {
							this->rpipe = 0;
							this->wpipe = 0;
							free (this->buffer);
							this->buffer = NULL;
							this->state = HTTP_RESPONSE_DONE;
						}
						else {
							cont = 0;
						}
					}
				}
				break;

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

				break;
		}
	}

	return retval;
}

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