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.
154 lines
3.3 KiB
154 lines
3.3 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"
|
|
|
|
#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 = (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 :
|
|
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:
|