Commit 0fba746fe27ecdba40793fd1213c561a1c78d7b4
1 parent
d87cd09b
first working version of content delivery from file....very crude... @TODO: rewr…
…ite complete response handline.
Showing
12 changed files
with
177 additions
and
61 deletions
assets/waldschrat.jpg
0 → 100644
77.8 KB
@@ -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: |
@@ -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