#include #include #include #include #include #include #include #include "class.h" #include "interface/class.h" #include "http/message.h" #include "http/response.h" #include "http/response/writer.h" #define MAX(x,y) ((x) > (y) ? (x) : (y)) #define _PSIZE(x) (MAX((x),RESPONSE_WRITER_MAX_BUF)) #define PSIZE _PSIZE(this->nheader+message->nbody) ssize_t httpResponseWriterWrite(HttpResponseWriter this, int fd) { HttpMessageQueue respq = this->response_queue; HttpMessage message = (HttpMessage)this->cur_response; ssize_t processed = (message)? 1 : 0; int cont = 1; while (cont) { switch (this->state) { case HTTP_RESPONSE_GET: if (NULL == this->cur_response && 0 < respq->nmsgs) { message = respq->msgs[0]; this->cur_response = (HttpResponse)message; processed++; memmove(respq->msgs, &(respq->msgs[1]), sizeof(void*) * (--respq->nmsgs + 1)); this->nbuffer = 0; this->written = 0; this->pstart = 0; this->nheader = httpMessageHeaderSizeGet(message); this->pend = this->nheader; this->pipe = malloc(PSIZE); 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 = (PSIZE == this->pend)? 0 : this->pend; rsize = (this->pstart <= this->pend)? PSIZE - this->pend : this->pstart - 1; switch (message->type) { case HTTP_MESSAGE_BUFFERED: temp = message->nbody - this->nbuffer; temp = (rsizepipe[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 : PSIZE - this->pstart; temp = write(fd, &(this->pipe[this->pstart]), wsize); this->written += temp; this->pstart += temp; this->pstart = (PSIZE == this->pstart)? 0 : this->pstart; } if (this->written == message->nbody + this->nheader) { this->state = HTTP_RESPONSE_DONE; } else { cont = 0; } break; case HTTP_RESPONSE_DONE: if (HTTP_MESSAGE_PIPED == message->type) { close(message->handle); } free(this->pipe); this->nheader = 0; this->nbuffer = 0; this->written = 0; this->pstart = 0; this->pend = 0; if (! httpMessageHasKeepAlive(message)) { /** * if the message did not have the keep-alive feature * we don't care about further pipelined messages and * return the to caller with a 0 indicating that the * underlying connection should be closed. */ processed = 0; cont = 0; } delete(&this->cur_response); this->state = HTTP_RESPONSE_GET; break; } } return processed; } // vim: set ts=4 sw=4: