diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 70 |
1 files changed, 15 insertions, 55 deletions
@@ -35,20 +35,7 @@ | |||
35 | * }}} | 35 | * }}} |
36 | */ | 36 | */ |
37 | 37 | ||
38 | // {{{ INCLUDES | 38 | #include "main.h" |
39 | #include <stdlib.h> | ||
40 | #include <stdio.h> | ||
41 | #include <string.h> | ||
42 | #include <unistd.h> | ||
43 | #include <sys/socket.h> | ||
44 | #include <err.h> | ||
45 | #include <errno.h> | ||
46 | #include <arpa/inet.h> | ||
47 | #include <fcntl.h> | ||
48 | #include <sys/sendfile.h> | ||
49 | #include <sys/stat.h> | ||
50 | // #include <pthread.h> // maybe later | ||
51 | // }}} | ||
52 | // {{{ MACROS | 39 | // {{{ MACROS |
53 | #define EWOULDBLOCK_DELAY 100 | 40 | #define EWOULDBLOCK_DELAY 100 |
54 | #define READ_BUFFER_LENGTH 9000 // jumboframe? | 41 | #define READ_BUFFER_LENGTH 9000 // jumboframe? |
@@ -67,36 +54,7 @@ static inline int verbose(const char * format, ...) { | |||
67 | #endif | 54 | #endif |
68 | // }}} | 55 | // }}} |
69 | 56 | ||
70 | typedef struct { | 57 | static int read_everything(FILE * f_r, FILE * output) { |
71 | int newline_length; // lenght of one newline in bytes (\n has 1, CR/LF has 2) | ||
72 | char * method; // GET/POST or something like that | ||
73 | char * url; // request URL (e.g. /index.html) | ||
74 | char * boundary; // usually looks similar to ------1234 | ||
75 | size_t boundary_size; // size in bytes, calculated after first header complete; is an indicator for the first header | ||
76 | char * content_type; // sometimes 'text/html', also sometimes 'text/html; boundary=------1234' | ||
77 | char * content_disposition; // includes file names of uploaded files or field names with form-data (e.g. curl -F) | ||
78 | } Http_Header; | ||
79 | |||
80 | void send_answer(int fd_socket, Http_Header * http_header) { | ||
81 | FILE * f = fdopen((size_t) fd_socket, "w"); | ||
82 | fputs("HTTP/1.0 200 OK\n", f); | ||
83 | fputs("content-type: text/plain\n\n", f); | ||
84 | fflush(f); | ||
85 | |||
86 | int file = open(&http_header->url[1], O_RDONLY); | ||
87 | if(0 < file) { | ||
88 | struct stat stat; | ||
89 | fstat(file, &stat); | ||
90 | sendfile (fileno(f), file, NULL, stat.st_size); | ||
91 | } else { | ||
92 | if(http_header->url) // TODO: too dangerous to check that here, that is too late. | ||
93 | fprintf(f, "could not open file \"%s\"\n", &http_header->url[1]); | ||
94 | } | ||
95 | |||
96 | fclose(f); | ||
97 | } | ||
98 | |||
99 | int read_everything(FILE * f_r, FILE * output) { | ||
100 | const int read_buffer_length = READ_BUFFER_LENGTH; | 58 | const int read_buffer_length = READ_BUFFER_LENGTH; |
101 | char read_buffer[read_buffer_length]; | 59 | char read_buffer[read_buffer_length]; |
102 | for(size_t size = -2 ; ; size = fread(read_buffer, 1, read_buffer_length, f_r)) { | 60 | for(size_t size = -2 ; ; size = fread(read_buffer, 1, read_buffer_length, f_r)) { |
@@ -118,7 +76,7 @@ int read_everything(FILE * f_r, FILE * output) { | |||
118 | return EXIT_SUCCESS; | 76 | return EXIT_SUCCESS; |
119 | } | 77 | } |
120 | 78 | ||
121 | void * next_customer(size_t new_socket) { | 79 | static void * next_customer(size_t new_socket) { |
122 | FILE * f_r = fdopen((size_t) new_socket, "r"); | 80 | FILE * f_r = fdopen((size_t) new_socket, "r"); |
123 | 81 | ||
124 | char * output_buffer = NULL; | 82 | char * output_buffer = NULL; |
@@ -229,12 +187,16 @@ void * next_customer(size_t new_socket) { | |||
229 | end += strspn(end, "-"); | 187 | end += strspn(end, "-"); |
230 | if(0 == strncmp(end, http_header.boundary, http_header.boundary_size)) { | 188 | if(0 == strncmp(end, http_header.boundary, http_header.boundary_size)) { |
231 | size_t file_size = content_end - content_start; | 189 | size_t file_size = content_end - content_start; |
232 | DEBUG("> Content ends here, size of the last file is %ld.", file_size); | 190 | DEBUG("> Content ends here, size of the last file is %ld\n", file_size); |
191 | |||
192 | content_start[file_size + 1] = '\0'; | ||
193 | next_part(&http_header, content_start, file_size); | ||
233 | 194 | ||
234 | end += http_header.boundary_size; | 195 | end += http_header.boundary_size; |
235 | matchlen = strspn(end, "\r\n"); | 196 | matchlen = strspn(end, "\r\n"); |
236 | DEBUG("> end is at %p, matchlen is %ld\n", end, matchlen); | 197 | DEBUG("> end is at %p, matchlen is %ld\n", end, matchlen); |
237 | 198 | ||
199 | |||
238 | search = ":"; | 200 | search = ":"; |
239 | break; | 201 | break; |
240 | } else { | 202 | } else { |
@@ -252,9 +214,9 @@ void * next_customer(size_t new_socket) { | |||
252 | start = end + matchlen; | 214 | start = end + matchlen; |
253 | } | 215 | } |
254 | 216 | ||
255 | DEBUG("> sending answer..."); | 217 | DEBUG("> sending answer...\n"); |
256 | send_answer(new_socket, &http_header); | 218 | send_answer(&http_header, new_socket); |
257 | DEBUG("> answer sent."); | 219 | DEBUG("> answer sent.\n"); |
258 | 220 | ||
259 | fclose(f_r); | 221 | fclose(f_r); |
260 | 222 | ||
@@ -264,7 +226,7 @@ void * next_customer(size_t new_socket) { | |||
264 | return NULL; | 226 | return NULL; |
265 | } | 227 | } |
266 | 228 | ||
267 | int serve(int server_fd) | 229 | static int serve(int server_fd) |
268 | { | 230 | { |
269 | struct sockaddr_in address; | 231 | struct sockaddr_in address; |
270 | socklen_t address_len = sizeof(address); | 232 | socklen_t address_len = sizeof(address); |
@@ -276,10 +238,8 @@ int serve(int server_fd) | |||
276 | DEBUG("> Client %ld is connected via port %d\n", new_socket, address.sin_port); | 238 | DEBUG("> Client %ld is connected via port %d\n", new_socket, address.sin_port); |
277 | 239 | ||
278 | // set non blocking mode... | 240 | // set non blocking mode... |
279 | fcntl( | 241 | fcntl(new_socket, F_SETFL, |
280 | (size_t) new_socket, | 242 | fcntl(new_socket, F_GETFL) | O_NONBLOCK |
281 | F_SETFL, | ||
282 | fcntl((size_t) new_socket, F_GETFL) | O_NONBLOCK | ||
283 | ); | 243 | ); |
284 | 244 | ||
285 | next_customer(new_socket); | 245 | next_customer(new_socket); |
@@ -321,4 +281,4 @@ int main(const int argc, char const * argv[]) { | |||
321 | ; return EXIT_FAILURE; | 281 | ; return EXIT_FAILURE; |
322 | } | 282 | } |
323 | 283 | ||
324 | // vim: shiftwidth=2 tabstop=2 number foldmethod=marker | 284 | // modeline for vim: shiftwidth=2 tabstop=2 number foldmethod=marker |