Commit 0fba746fe27ecdba40793fd1213c561a1c78d7b4

Authored by Georg Hopp
1 parent d87cd09b

first working version of content delivery from file....very crude... @TODO: rewr…

…ite complete response handline.
... ... @@ -16,13 +16,13 @@ CLASS(HttpMessage) {
16 16 HttpHeader header;
17 17
18 18 HttpMessageType type;
19   - union {
20   - char * buffer;
21   - int handle;
22   - } body;
  19 + int handle;
  20 + char * body;
23 21 int nbody;
24 22 };
25 23
  24 +char httpMessageHasKeepAlive(HttpMessage);
  25 +
26 26 #endif // __HTTP_MESSAGE__
27 27
28 28 // vim: set ts=4 sw=4:
... ...
... ... @@ -11,8 +11,6 @@ CLASS(HttpRequest) {
11 11 char * uri;
12 12 };
13 13
14   -char httpRequestHasKeepAlive(HttpRequest);
15   -
16 14 #endif /* __HTTP_REQUEST_H__ */
17 15
18 16 // vim: set ts=4 sw=4:
... ...
... ... @@ -27,7 +27,7 @@ CLASS(HttpResponseWriter) {
27 27 HttpResponseState state;
28 28 };
29 29
30   -size_t httpResponseWriterWrite(HttpResponseWriter, int);
  30 +HttpResponse httpResponseWriterWrite(HttpResponseWriter, int);
31 31
32 32 #endif // __HTTP_RESPONSE_WRITER_H__
33 33
... ...
... ... @@ -7,8 +7,8 @@ CLASS = class.c interface.c
7 7 SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c
8 8 SERVER = server.c server/run.c server/close_conn.c
9 9 LOGGER = logger.c logger/stderr.c logger/syslog.c
10   -MSG = http/message.c http/message/queue.c
11   -REQ = http/request.c http/request/has_keep_alive.c
  10 +MSG = http/message.c http/message/queue.c http/message/has_keep_alive.c
  11 +REQ = http/request.c
12 12 RESP = http/response.c http/response/404.c http/response/size_get.c \
13 13 http/response/to_string.c
14 14 WRITER = http/response/writer.c http/response/writer/write.c
... ...
... ... @@ -43,11 +43,11 @@ dtor(void * _this)
43 43
44 44 switch (this->type) {
45 45 case HTTP_MESSAGE_BUFFERED:
46   - _free((void **)&((this->body).buffer));
  46 + _free((void **)&(this->body));
47 47 break;
48 48
49 49 case HTTP_MESSAGE_PIPED:
50   - close((this->body).handle);
  50 + if (2 < this->handle) close(this->handle);
51 51 break;
52 52
53 53 default:
... ...
... ... @@ -7,9 +7,8 @@
7 7
8 8
9 9 char
10   -httpRequestHasKeepAlive(HttpRequest request)
  10 +httpMessageHasKeepAlive(HttpMessage message)
11 11 {
12   - HttpMessage message = (HttpMessage)request;
13 12 char * header;
14 13 char * header_ptr;
15 14
... ...
... ... @@ -26,8 +26,8 @@ httpRequestParserGetBody(HttpRequestParser this)
26 26 }
27 27
28 28 if (REMAINS(this) >= message->nbody) {
29   - (message->body).buffer = calloc(1, message->nbody + 1);
30   - memcpy((message->body).buffer,
  29 + message->body = calloc(1, message->nbody + 1);
  30 + memcpy(message->body,
31 31 this->cur_data,
32 32 message->nbody);
33 33 this->cur_data += message->nbody;
... ...
... ... @@ -37,10 +37,10 @@ httpResponse404()
37 37 httpHeaderAdd(&(message->header),
38 38 new(HttpHeader, "Server", "testserver"));
39 39
40   - message->type = HTTP_MESSAGE_BUFFERED;
41   - message->nbody = sizeof(RESP_DATA) - 1;
42   - (message->body).buffer = calloc(1, sizeof(RESP_DATA));
43   - strcpy((message->body).buffer, RESP_DATA);
  40 + message->type = HTTP_MESSAGE_BUFFERED;
  41 + message->nbody = sizeof(RESP_DATA) - 1;
  42 + message->body = calloc(1, sizeof(RESP_DATA));
  43 + strcpy(message->body, RESP_DATA);
44 44
45 45 sprintf(buffer, "%d", message->nbody);
46 46 httpHeaderAdd(&(message->header),
... ...
... ... @@ -49,7 +49,7 @@ httpResponseToString(HttpResponse response, char * _string)
49 49 *string++ = '\n';
50 50
51 51 if (HTTP_MESSAGE_BUFFERED == message->type) {
52   - memcpy(string, (message->body).buffer, message->nbody);
  52 + memcpy(string, message->body, message->nbody);
53 53 }
54 54
55 55 return string;
... ...
  1 +#include <stdio.h>
1 2 #include <unistd.h>
2 3 #include <stdlib.h>
3 4 #include <string.h>
4 5 #include <sys/types.h>
  6 +#include <sys/stat.h>
  7 +#include <fcntl.h>
5 8
6 9 #include "class.h"
7 10 #include "interface/class.h"
8 11 #include "http/response.h"
9 12 #include "http/response/writer.h"
10 13
11   -size_t
  14 +HttpResponse
12 15 httpResponseWriterWrite(HttpResponseWriter this, int fd)
13 16 {
14 17 HttpMessageQueue respq = this->response_queue;
15 18 int cont = 1;
16   - size_t written = 0;
  19 + HttpResponse retval = NULL;
17 20
18 21 while (cont) {
19 22 switch (this->state) {
20 23 case HTTP_RESPONSE_NO:
21 24 if (NULL == this->cur_response && 0 < respq->nmsgs) {
22   - this->cur_response = (HttpResponse)respq->msgs[0];
23   - memmove(respq->msgs, &(respq->msgs[1]), --respq->nmsgs);
  25 + retval = this->cur_response = (HttpResponse)respq->msgs[0];
  26 + memmove(respq->msgs,
  27 + &(respq->msgs[1]),
  28 + sizeof(void*) * (--respq->nmsgs + 1));
24 29 this->state = HTTP_RESPONSE_START;
25 30 }
26 31 else {
... ... @@ -29,51 +34,86 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd)
29 34 break;
30 35
31 36 case HTTP_RESPONSE_START:
32   - if (NULL == this->buffer) {
33   - this->nbuffer = httpResponseSizeGet(this->cur_response);
34   - this->buffer = calloc(1, this->nbuffer);
35   - httpResponseToString(this->cur_response, this->buffer);
  37 + if (HTTP_MESSAGE_PIPED ==
  38 + ((HttpMessage)(this->cur_response))->type) {
  39 + struct stat st;
  40 + HttpMessage message = (HttpMessage)this->cur_response;
  41 + char buffer[200];
  42 +
  43 + message->handle =
  44 + open("./assets/waldschrat.jpg", O_RDONLY);
  45 + fstat(message->handle, &st);
  46 + message->nbody = st.st_size;
  47 +
  48 + sprintf(buffer, "%d", message->nbody);
  49 + httpHeaderAdd(&(message->header),
  50 + new(HttpHeader, "Content-Length", buffer));
  51 +
36 52 }
  53 +
  54 + this->state = HTTP_RESPONSE_PIPE;
  55 + break;
  56 +
  57 + case HTTP_RESPONSE_PIPE:
37 58 {
38   - written = write(fd, this->buffer, this->nbuffer);
  59 + HttpMessage message = (HttpMessage)(this->cur_response);
  60 + size_t headsize = httpResponseSizeGet(this->cur_response);
  61 +
  62 + this->buffer = malloc(headsize + message->nbody);
  63 + httpResponseToString(this->cur_response, this->buffer);
  64 + this->rpipe = headsize;
39 65
40   - if (-1 == written) {
41   - free (this->buffer);
42   - this->buffer = NULL;
43   - return written;
  66 + if (HTTP_MESSAGE_PIPED == message->type &&
  67 + 0 != message->handle) {
  68 + char * data = &(this->buffer[headsize]);
  69 + size_t togo = message->nbody;
  70 +
  71 + size_t rsize = read(message->handle, data, togo);
  72 +
  73 + while (rsize < togo) {
  74 + data += rsize;
  75 + togo -= rsize;
  76 + rsize = read(message->handle, data, togo);
  77 + }
  78 +
  79 + this->wpipe = 0;
  80 + this->rpipe += message->nbody;
  81 + close(message->handle);
  82 + message->handle = 0;
44 83 }
45 84
46   - if (written == this->nbuffer) {
47   - if (HTTP_MESSAGE_BUFFERED ==
48   - ((HttpMessage)(this->cur_response))->type) {
  85 + {
  86 + char * data = &(this->buffer[this->wpipe]);
  87 + size_t written;
  88 +
  89 + written = write(fd, data, this->rpipe - this->wpipe);
  90 + data += written;
  91 + this->wpipe += written;
  92 +
  93 + if (this->rpipe == this->wpipe) {
  94 + this->rpipe = 0;
  95 + this->wpipe = 0;
  96 + free (this->buffer);
  97 + this->buffer = NULL;
49 98 this->state = HTTP_RESPONSE_DONE;
50 99 }
51 100 else {
52   - this->state = HTTP_RESPONSE_PIPE;
  101 + cont = 0;
53 102 }
54 103 }
55   - else {
56   - this->nbuffer -= written;
57   - memmove(this->buffer, this->buffer + written, this->nbuffer);
58   - cont = 0;
59   - }
60 104 }
61 105 break;
62 106
63   - case HTTP_RESPONSE_PIPE:
64   - break;
65   -
66 107 case HTTP_RESPONSE_DONE:
67   - free (this->buffer);
68   - this->buffer = NULL;
69   - delete(&(this->cur_response));
70   - this->state = HTTP_RESPONSE_NO;
  108 + this->state = HTTP_RESPONSE_NO;
  109 + this->cur_response = NULL;
  110 + cont = 0;
71 111
72 112 break;
73 113 }
74 114 }
75 115
76   - return written;
  116 + return retval;
77 117 }
78 118
79 119 // vim: set ts=4 sw=4:
... ...
... ... @@ -6,6 +6,9 @@
6 6 #include <ctype.h>
7 7 #include <time.h>
8 8 #include <errno.h>
  9 +#include <fcntl.h>
  10 +#include <sys/types.h>
  11 +#include <sys/stat.h>
9 12
10 13 #include "server.h"
11 14 #include "socket.h"
... ... @@ -114,16 +117,78 @@ serverRun(Server this)
114 117 * @TODO: for now simply remove request and send not found.
115 118 * Make this sane.
116 119 */
117   - HttpMessage response = (HttpMessage)httpResponse404();
  120 + HttpRequest request = (HttpRequest)(reqq->msgs[j]);
  121 + HttpMessage response = NULL;
  122 +
  123 + if (0 == strcmp("GET", request->method) &&
  124 + 0 == strcmp("/me/", request->uri)) {
  125 + const char foo[] =
  126 + "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
  127 + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
  128 + " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
  129 + "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
  130 + "<head><title>200 - OK</title></head>"
  131 + "<body><h1>200 - OK</h1>"
  132 + "<img src=\"http://localhost:11212/image/\" /></body>"
  133 + "</html>";
  134 + char buffer[200];
  135 + time_t t;
  136 + struct tm * tmp;
  137 +
  138 + response = (HttpMessage)new(HttpResponse, "HTTP/1.1", 200, "OK");
  139 +
  140 + httpHeaderAdd(&(response->header),
  141 + new(HttpHeader, "Content-Type", "text/html"));
  142 + httpHeaderAdd(&(response->header),
  143 + new(HttpHeader, "Server", "testserver"));
  144 +
  145 + response->type = HTTP_MESSAGE_BUFFERED;
  146 + response->nbody = sizeof(foo) - 1;
  147 + response->body = calloc(1, sizeof(foo));
  148 + strcpy(response->body, foo);
  149 +
  150 + sprintf(buffer, "%d", response->nbody);
  151 + httpHeaderAdd(&(response->header),
  152 + new(HttpHeader, "Content-Length", buffer));
  153 +
  154 + t = time(NULL);
  155 + tmp = localtime(&t);
  156 + strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);
  157 + httpHeaderAdd(&(response->header),
  158 + new(HttpHeader, "Date", buffer));
  159 + }
  160 + else if (0 == strcmp("GET", request->method) &&
  161 + 0 == strcmp("/image/", request->uri)) {
  162 + char buffer[200];
  163 + time_t t;
  164 + struct tm * tmp;
  165 +
  166 + response = (HttpMessage)new(
  167 + HttpResponse, "HTTP/1.1", 200, "OK");
  168 +
  169 + httpHeaderAdd(&(response->header),
  170 + new(HttpHeader, "Content-Type", "image/jpeg"));
  171 + httpHeaderAdd(&(response->header),
  172 + new(HttpHeader, "Server", "testserver"));
  173 +
  174 + response->type = HTTP_MESSAGE_PIPED;
  175 +
  176 + t = time(NULL);
  177 + tmp = localtime(&t);
  178 + strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);
  179 + httpHeaderAdd(&(response->header),
  180 + new(HttpHeader, "Date", buffer));
  181 + }
  182 + else {
  183 + response = (HttpMessage)httpResponse404();
  184 + }
118 185
119   - if (httpRequestHasKeepAlive((HttpRequest)reqq->msgs[j])) {
120   - (this->conns)[fd].keep_alive = 1;
  186 + if (httpMessageHasKeepAlive(reqq->msgs[j])) {
121 187 httpHeaderAdd(
122 188 &(response->header),
123 189 new(HttpHeader, "Connection", "Keep-Alive"));
124 190 }
125 191 else {
126   - (this->conns)[fd].keep_alive = 0;
127 192 httpHeaderAdd(
128 193 &(response->header),
129 194 new(HttpHeader, "Connection", "Close"));
... ... @@ -145,18 +210,32 @@ serverRun(Server this)
145 210 * handle writes
146 211 */
147 212 if (0 != ((this->fds)[i].revents & POLLOUT) && 0 < nwrites) {
148   - int size;
  213 + HttpResponseWriter writer =
  214 + (HttpResponseWriter)(this->conns)[fd].writer;
  215 + HttpMessage message;
149 216
150 217 events--;
151 218 nwrites--;
152 219
153   - size = streamWriterWrite((this->conns)[fd].writer, fd);
  220 + message = (HttpMessage)streamWriterWrite(writer, fd);
154 221
155   - if ((this->conns)[fd].keep_alive) {
156   - (this->fds)[i].events &= ~POLLOUT;
157   - }
158   - else {
159   - serverCloseConn(this, i);
  222 + while (NULL != message) {
  223 + if (writer->state == HTTP_RESPONSE_NO) {
  224 + if (httpMessageHasKeepAlive(message)) {
  225 + delete(&message);
  226 + if (0 == writer->response_queue->nmsgs) {
  227 + (this->fds)[i].events &= ~POLLOUT;
  228 + break;
  229 + }
  230 + }
  231 + else {
  232 + delete(&message);
  233 + serverCloseConn(this, i);
  234 + break;
  235 + }
  236 + }
  237 +
  238 + message = (HttpMessage)streamWriterWrite(writer, fd);
160 239 }
161 240 }
162 241 }
... ...
Please register or login to post a comment