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,13 +16,13 @@ CLASS(HttpMessage) {
16 HttpHeader header; 16 HttpHeader header;
17 17
18 HttpMessageType type; 18 HttpMessageType type;
19 - union {  
20 - char * buffer;  
21 - int handle;  
22 - } body; 19 + int handle;
  20 + char * body;
23 int nbody; 21 int nbody;
24 }; 22 };
25 23
  24 +char httpMessageHasKeepAlive(HttpMessage);
  25 +
26 #endif // __HTTP_MESSAGE__ 26 #endif // __HTTP_MESSAGE__
27 27
28 // vim: set ts=4 sw=4: 28 // vim: set ts=4 sw=4:
@@ -11,8 +11,6 @@ CLASS(HttpRequest) { @@ -11,8 +11,6 @@ CLASS(HttpRequest) {
11 char * uri; 11 char * uri;
12 }; 12 };
13 13
14 -char httpRequestHasKeepAlive(HttpRequest);  
15 -  
16 #endif /* __HTTP_REQUEST_H__ */ 14 #endif /* __HTTP_REQUEST_H__ */
17 15
18 // vim: set ts=4 sw=4: 16 // vim: set ts=4 sw=4:
@@ -27,7 +27,7 @@ CLASS(HttpResponseWriter) { @@ -27,7 +27,7 @@ CLASS(HttpResponseWriter) {
27 HttpResponseState state; 27 HttpResponseState state;
28 }; 28 };
29 29
30 -size_t httpResponseWriterWrite(HttpResponseWriter, int); 30 +HttpResponse httpResponseWriterWrite(HttpResponseWriter, int);
31 31
32 #endif // __HTTP_RESPONSE_WRITER_H__ 32 #endif // __HTTP_RESPONSE_WRITER_H__
33 33
@@ -7,8 +7,8 @@ CLASS = class.c interface.c @@ -7,8 +7,8 @@ CLASS = class.c interface.c
7 SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c 7 SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c
8 SERVER = server.c server/run.c server/close_conn.c 8 SERVER = server.c server/run.c server/close_conn.c
9 LOGGER = logger.c logger/stderr.c logger/syslog.c 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 RESP = http/response.c http/response/404.c http/response/size_get.c \ 12 RESP = http/response.c http/response/404.c http/response/size_get.c \
13 http/response/to_string.c 13 http/response/to_string.c
14 WRITER = http/response/writer.c http/response/writer/write.c 14 WRITER = http/response/writer.c http/response/writer/write.c
@@ -43,11 +43,11 @@ dtor(void * _this) @@ -43,11 +43,11 @@ dtor(void * _this)
43 43
44 switch (this->type) { 44 switch (this->type) {
45 case HTTP_MESSAGE_BUFFERED: 45 case HTTP_MESSAGE_BUFFERED:
46 - _free((void **)&((this->body).buffer)); 46 + _free((void **)&(this->body));
47 break; 47 break;
48 48
49 case HTTP_MESSAGE_PIPED: 49 case HTTP_MESSAGE_PIPED:
50 - close((this->body).handle); 50 + if (2 < this->handle) close(this->handle);
51 break; 51 break;
52 52
53 default: 53 default:
@@ -7,9 +7,8 @@ @@ -7,9 +7,8 @@
7 7
8 8
9 char 9 char
10 -httpRequestHasKeepAlive(HttpRequest request) 10 +httpMessageHasKeepAlive(HttpMessage message)
11 { 11 {
12 - HttpMessage message = (HttpMessage)request;  
13 char * header; 12 char * header;
14 char * header_ptr; 13 char * header_ptr;
15 14
@@ -26,8 +26,8 @@ httpRequestParserGetBody(HttpRequestParser this) @@ -26,8 +26,8 @@ httpRequestParserGetBody(HttpRequestParser this)
26 } 26 }
27 27
28 if (REMAINS(this) >= message->nbody) { 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 this->cur_data, 31 this->cur_data,
32 message->nbody); 32 message->nbody);
33 this->cur_data += message->nbody; 33 this->cur_data += message->nbody;
@@ -37,10 +37,10 @@ httpResponse404() @@ -37,10 +37,10 @@ httpResponse404()
37 httpHeaderAdd(&(message->header), 37 httpHeaderAdd(&(message->header),
38 new(HttpHeader, "Server", "testserver")); 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 sprintf(buffer, "%d", message->nbody); 45 sprintf(buffer, "%d", message->nbody);
46 httpHeaderAdd(&(message->header), 46 httpHeaderAdd(&(message->header),
@@ -49,7 +49,7 @@ httpResponseToString(HttpResponse response, char * _string) @@ -49,7 +49,7 @@ httpResponseToString(HttpResponse response, char * _string)
49 *string++ = '\n'; 49 *string++ = '\n';
50 50
51 if (HTTP_MESSAGE_BUFFERED == message->type) { 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 return string; 55 return string;
  1 +#include <stdio.h>
1 #include <unistd.h> 2 #include <unistd.h>
2 #include <stdlib.h> 3 #include <stdlib.h>
3 #include <string.h> 4 #include <string.h>
4 #include <sys/types.h> 5 #include <sys/types.h>
  6 +#include <sys/stat.h>
  7 +#include <fcntl.h>
5 8
6 #include "class.h" 9 #include "class.h"
7 #include "interface/class.h" 10 #include "interface/class.h"
8 #include "http/response.h" 11 #include "http/response.h"
9 #include "http/response/writer.h" 12 #include "http/response/writer.h"
10 13
11 -size_t 14 +HttpResponse
12 httpResponseWriterWrite(HttpResponseWriter this, int fd) 15 httpResponseWriterWrite(HttpResponseWriter this, int fd)
13 { 16 {
14 HttpMessageQueue respq = this->response_queue; 17 HttpMessageQueue respq = this->response_queue;
15 int cont = 1; 18 int cont = 1;
16 - size_t written = 0; 19 + HttpResponse retval = NULL;
17 20
18 while (cont) { 21 while (cont) {
19 switch (this->state) { 22 switch (this->state) {
20 case HTTP_RESPONSE_NO: 23 case HTTP_RESPONSE_NO:
21 if (NULL == this->cur_response && 0 < respq->nmsgs) { 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 this->state = HTTP_RESPONSE_START; 29 this->state = HTTP_RESPONSE_START;
25 } 30 }
26 else { 31 else {
@@ -29,51 +34,86 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) @@ -29,51 +34,86 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd)
29 break; 34 break;
30 35
31 case HTTP_RESPONSE_START: 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 this->state = HTTP_RESPONSE_DONE; 98 this->state = HTTP_RESPONSE_DONE;
50 } 99 }
51 else { 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 break; 105 break;
62 106
63 - case HTTP_RESPONSE_PIPE:  
64 - break;  
65 -  
66 case HTTP_RESPONSE_DONE: 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 break; 112 break;
73 } 113 }
74 } 114 }
75 115
76 - return written; 116 + return retval;
77 } 117 }
78 118
79 // vim: set ts=4 sw=4: 119 // vim: set ts=4 sw=4:
@@ -6,6 +6,9 @@ @@ -6,6 +6,9 @@
6 #include <ctype.h> 6 #include <ctype.h>
7 #include <time.h> 7 #include <time.h>
8 #include <errno.h> 8 #include <errno.h>
  9 +#include <fcntl.h>
  10 +#include <sys/types.h>
  11 +#include <sys/stat.h>
9 12
10 #include "server.h" 13 #include "server.h"
11 #include "socket.h" 14 #include "socket.h"
@@ -114,16 +117,78 @@ serverRun(Server this) @@ -114,16 +117,78 @@ serverRun(Server this)
114 * @TODO: for now simply remove request and send not found. 117 * @TODO: for now simply remove request and send not found.
115 * Make this sane. 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 httpHeaderAdd( 187 httpHeaderAdd(
122 &(response->header), 188 &(response->header),
123 new(HttpHeader, "Connection", "Keep-Alive")); 189 new(HttpHeader, "Connection", "Keep-Alive"));
124 } 190 }
125 else { 191 else {
126 - (this->conns)[fd].keep_alive = 0;  
127 httpHeaderAdd( 192 httpHeaderAdd(
128 &(response->header), 193 &(response->header),
129 new(HttpHeader, "Connection", "Close")); 194 new(HttpHeader, "Connection", "Close"));
@@ -145,18 +210,32 @@ serverRun(Server this) @@ -145,18 +210,32 @@ serverRun(Server this)
145 * handle writes 210 * handle writes
146 */ 211 */
147 if (0 != ((this->fds)[i].revents & POLLOUT) && 0 < nwrites) { 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 events--; 217 events--;
151 nwrites--; 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