You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
2.7 KiB
129 lines
2.7 KiB
#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"
|
|
#include "cbuf.h"
|
|
|
|
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
|
#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;
|
|
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;
|
|
|
|
this->written = 0;
|
|
this->nbody = 0;
|
|
this->nheader = httpMessageHeaderSizeGet(message);
|
|
|
|
httpMessageHeaderToString(message, cbufGetWrite(this->buffer));
|
|
cbufIncWrite(this->buffer, this->nheader);
|
|
|
|
this->state = HTTP_RESPONSE_WRITE;
|
|
}
|
|
else {
|
|
cont = 0;
|
|
}
|
|
break;
|
|
|
|
case HTTP_RESPONSE_WRITE:
|
|
/**
|
|
* read
|
|
*/
|
|
if (this->nbody < message->nbody) {
|
|
size_t size = MIN(
|
|
message->nbody - this->nbody,
|
|
cbufGetFree(this->buffer));
|
|
|
|
switch (message->type) {
|
|
case HTTP_MESSAGE_BUFFERED:
|
|
cbufSetData(this->buffer,
|
|
message->body + this->nbody,
|
|
size);
|
|
break;
|
|
|
|
case HTTP_MESSAGE_PIPED:
|
|
size = cbufRead(this->buffer, message->handle);
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
this->nbody += size;
|
|
}
|
|
|
|
/**
|
|
* write
|
|
*/
|
|
{
|
|
ssize_t written = cbufWrite(this->buffer, fd);
|
|
|
|
if (0 <= written) {
|
|
this->written += written;
|
|
}
|
|
else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
this->state = HTTP_RESPONSE_GET;
|
|
|
|
memmove(respq->msgs,
|
|
&(respq->msgs[1]),
|
|
sizeof(void*) * (--respq->nmsgs + 1));
|
|
|
|
if (! httpMessageHasKeepAlive(message)) {
|
|
/**
|
|
* if the message did not have the keep-alive feature
|
|
* we don't care about further pipelined messages and
|
|
* return to the caller with a 0 indicating that the
|
|
* underlying connection should be closed.
|
|
*/
|
|
delete(&this->cur_response);
|
|
return -1;
|
|
}
|
|
|
|
delete(&this->cur_response);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return respq->nmsgs;
|
|
}
|
|
|
|
// vim: set ts=4 sw=4:
|