diff options
-rw-r--r-- | main.c | 104 |
1 files changed, 57 insertions, 47 deletions
@@ -16,6 +16,7 @@ | |||
16 | #include <errno.h> | 16 | #include <errno.h> |
17 | 17 | ||
18 | #include <pthread.h> | 18 | #include <pthread.h> |
19 | #include <stdarg.h> | ||
19 | 20 | ||
20 | 21 | ||
21 | void send_answer(FILE * f) { | 22 | void send_answer(FILE * f) { |
@@ -36,34 +37,34 @@ void send_answer(FILE * f) { | |||
36 | fputs("</html>", f); | 37 | fputs("</html>", f); |
37 | } | 38 | } |
38 | 39 | ||
39 | void * next_customer(size_t new_socket) { | ||
40 | 40 | ||
41 | char * output_buffer = NULL; | 41 | #define EWOULDBLOCK_DELAY 1000 |
42 | size_t output_buffer_length = 0; | 42 | #define READ_BUFFER_LENGTH 10 |
43 | FILE * output = open_memstream(&output_buffer, &output_buffer_length); | 43 | #define DEBUG_SLEEP_TIME 50000 |
44 | 44 | ||
45 | const int read_buffer_length = 10; | 45 | static inline int verbose(const char * format, ...) { |
46 | char read_buffer[read_buffer_length]; | 46 | va_list va; va_start(va, format); usleep(DEBUG_SLEEP_TIME); return vprintf(format, va); |
47 | } | ||
47 | 48 | ||
48 | puts("\n\n########################################## Content Reader"); | ||
49 | FILE * q = fdopen((size_t) new_socket, "r"); | ||
50 | printf("fd : %p\n", q); | ||
51 | 49 | ||
52 | for(size_t size = -2 ; ; size = fread(read_buffer, read_buffer_length, 1, q)) { | 50 | void read_everything(FILE * f_r, FILE * output) { |
51 | const int read_buffer_length = READ_BUFFER_LENGTH; | ||
52 | char read_buffer[read_buffer_length]; | ||
53 | for(size_t size = -2 ; ; size = fread(read_buffer, read_buffer_length, 1, f_r)) { | ||
53 | if(-2 == size || (-1 == size && EWOULDBLOCK == errno)) { | 54 | if(-2 == size || (-1 == size && EWOULDBLOCK == errno)) { |
54 | usleep(1000); | 55 | usleep(EWOULDBLOCK_DELAY); // try again a little later |
55 | continue; | 56 | continue; |
56 | } else if (1 != size) { // I expect one nmemb of data | 57 | } else if (1 != size) { // I expect one nmemb of data |
57 | break; | 58 | break; |
58 | } | 59 | } |
59 | 60 | ||
60 | fwrite(read_buffer, read_buffer_length, 1, output); | 61 | fwrite(read_buffer, read_buffer_length, 1, output); |
61 | fwrite(read_buffer, read_buffer_length, 1, stdout); | ||
62 | } | 62 | } |
63 | fflush(output); | 63 | fflush(output); |
64 | } | ||
64 | 65 | ||
65 | 66 | void header_next(const char * key, const char * value) { | |
66 | puts("\n\n########################################## Content Parser"); | 67 | // this sample function will be removed later |
67 | typedef struct { | 68 | typedef struct { |
68 | const char * name; | 69 | const char * name; |
69 | const char * value; | 70 | const char * value; |
@@ -73,6 +74,27 @@ void * next_customer(size_t new_socket) { | |||
73 | {"Content-Type", NULL}, | 74 | {"Content-Type", NULL}, |
74 | {"Content-Length", NULL} | 75 | {"Content-Length", NULL} |
75 | }; | 76 | }; |
77 | for(int i=0; i < sizeof(namevalue) / sizeof(NameValue); i++) { | ||
78 | // printf("next name: %s\n", namevalue[i].name); | ||
79 | if(NULL == namevalue[i].value && 0 == strcasecmp(namevalue[i].name, key)) { | ||
80 | namevalue[i].value = value; | ||
81 | break; | ||
82 | } | ||
83 | } | ||
84 | } | ||
85 | |||
86 | void * next_customer(size_t new_socket) { | ||
87 | FILE * f_r = fdopen((size_t) new_socket, "r"); | ||
88 | FILE * f_w = fdopen((size_t) new_socket, "w"); | ||
89 | |||
90 | char * output_buffer = NULL; | ||
91 | size_t output_buffer_length = 0; | ||
92 | FILE * output = open_memstream(&output_buffer, &output_buffer_length); | ||
93 | |||
94 | verbose("\n\n########################################## Content Reader [%d]\n", f_r); | ||
95 | read_everything(f_r, output); | ||
96 | verbose("\n\n########################################## Content Parser"); | ||
97 | |||
76 | 98 | ||
77 | // token parser... | 99 | // token parser... |
78 | const char * boundary = NULL; | 100 | const char * boundary = NULL; |
@@ -84,10 +106,8 @@ void * next_customer(size_t new_socket) { | |||
84 | char * content_start = NULL; | 106 | char * content_start = NULL; |
85 | char * content_end = NULL; | 107 | char * content_end = NULL; |
86 | 108 | ||
87 | while(1) { | 109 | while(key ? key[0] != '\0' : 1) { |
88 | 110 | verbose("> [!] Next iteration with search '%s'\n", search); | |
89 | printf("NEXT ITERATION with search '%s'\n", search); | ||
90 | |||
91 | for(char * | 111 | for(char * |
92 | token = strtok_r(NULL == saveptr ? output_buffer : saveptr, NULL == search ? "\n\r" : search, &saveptr); | 112 | token = strtok_r(NULL == saveptr ? output_buffer : saveptr, NULL == search ? "\n\r" : search, &saveptr); |
93 | token != NULL; | 113 | token != NULL; |
@@ -95,8 +115,7 @@ void * next_customer(size_t new_socket) { | |||
95 | { | 115 | { |
96 | 116 | ||
97 | if(!search) { // first round: HTTP status code | 117 | if(!search) { // first round: HTTP status code |
98 | puts("FIRST ITERATION"); | 118 | verbose("> First Iteration: HTTP sanity check of: %s\n", token); |
99 | printf("HTTP sanity check: %s\n", token); | ||
100 | search = ":"; | 119 | search = ":"; |
101 | continue; | 120 | continue; |
102 | } | 121 | } |
@@ -119,18 +138,12 @@ void * next_customer(size_t new_socket) { | |||
119 | if(!boundary && strstr(key, "Content-Type") && strncmp(value, pattern, sizeof(pattern))) { | 138 | if(!boundary && strstr(key, "Content-Type") && strncmp(value, pattern, sizeof(pattern))) { |
120 | boundary = &value[sizeof(pattern) + strspn(&value[sizeof(pattern)], "-")]; | 139 | boundary = &value[sizeof(pattern) + strspn(&value[sizeof(pattern)], "-")]; |
121 | boundary_length = strlen(boundary); | 140 | boundary_length = strlen(boundary); |
122 | printf("> [!] boundary detected '%s' ", boundary); | 141 | verbose("> [!] boundary detected '%s' ", boundary); |
123 | } | 142 | } |
124 | 143 | ||
125 | for(int i=0; i < sizeof(namevalue) / sizeof(NameValue); i++) { | 144 | header_next(key, value); |
126 | // printf("next name: %s\n", namevalue[i].name); | ||
127 | if(NULL == namevalue[i].value && 0 == strcasecmp(namevalue[i].name, key)) { | ||
128 | namevalue[i].value = value; | ||
129 | break; | ||
130 | } | ||
131 | } | ||
132 | 145 | ||
133 | printf("> [%ld] \"%s\" :: \"%s\"\n", key - output_buffer, key, value); fflush(stdout); | 146 | verbose("> [%ld] \"%s\" :: \"%s\"\n", key - output_buffer, key, value); fflush(stdout); |
134 | 147 | ||
135 | search = ":"; | 148 | search = ":"; |
136 | key = NULL; | 149 | key = NULL; |
@@ -140,13 +153,13 @@ void * next_customer(size_t new_socket) { | |||
140 | if(!key) | 153 | if(!key) |
141 | break; | 154 | break; |
142 | // printf("We are now here: %ld\n", key - output_buffer); | 155 | // printf("We are now here: %ld\n", key - output_buffer); |
143 | printf("We are now here: %s\n", key); | 156 | verbose("We are now here: %s\n", key); |
144 | 157 | ||
145 | // jump over the content... | 158 | // jump over the content... |
146 | content_start = key; | 159 | content_start = key; |
147 | while((key = memchr(key, '\n', output_buffer_length - (key - output_buffer)))) { | 160 | while((key = memchr(key, '\n', output_buffer_length - (key - output_buffer)))) { |
148 | if(!key) { | 161 | if(!key) { |
149 | warnx("out at %p\n", key); | 162 | verbose("out at %p\n", key); |
150 | break; | 163 | break; |
151 | } else { | 164 | } else { |
152 | key++; | 165 | key++; |
@@ -154,7 +167,7 @@ void * next_customer(size_t new_socket) { | |||
154 | 167 | ||
155 | if(key[0] == '-') { | 168 | if(key[0] == '-') { |
156 | if(0 == strncmp(&key[strspn(key, "-")], boundary, boundary_length)) { | 169 | if(0 == strncmp(&key[strspn(key, "-")], boundary, boundary_length)) { |
157 | puts("GEIL1"); | 170 | verbose("> boundary found."); |
158 | 171 | ||
159 | if(key[-1] == '\n') key--; | 172 | if(key[-1] == '\n') key--; |
160 | if(key[-1] == '\r') key--; | 173 | if(key[-1] == '\r') key--; |
@@ -171,7 +184,7 @@ void * next_customer(size_t new_socket) { | |||
171 | } | 184 | } |
172 | } | 185 | } |
173 | 186 | ||
174 | printf("content is %p - %p = %ld in size\n", content_end, content_start, content_end - content_start); | 187 | verbose("content is %p - %p = %ld in size\n", content_end, content_start, content_end - content_start); |
175 | if(content_end - content_start > 1000) { | 188 | if(content_end - content_start > 1000) { |
176 | FILE * f_w = fopen("/tmp/test.gif", "w"); | 189 | FILE * f_w = fopen("/tmp/test.gif", "w"); |
177 | fwrite(content_start, content_end - content_start, 1, f_w); | 190 | fwrite(content_start, content_end - content_start, 1, f_w); |
@@ -186,16 +199,13 @@ void * next_customer(size_t new_socket) { | |||
186 | // usleep(100000); | 199 | // usleep(100000); |
187 | } | 200 | } |
188 | 201 | ||
189 | 202 | verbose("> sending answer..."); | |
190 | puts("> sending answer..."); | ||
191 | FILE * f_w = fdopen((size_t) new_socket, "w"); | ||
192 | send_answer(f_w); | 203 | send_answer(f_w); |
193 | 204 | ||
194 | fclose(f_w); | 205 | fclose(f_w); |
195 | fclose(q); | 206 | fclose(f_r); |
196 | puts("> answer sent."); | ||
197 | 207 | ||
198 | printf("still in knowledge of out boundary: %s\n", namevalue[0].value); | 208 | verbose("> answer sent."); |
199 | 209 | ||
200 | return NULL; | 210 | return NULL; |
201 | } | 211 | } |
@@ -206,19 +216,19 @@ int serve(int server_fd) | |||
206 | { | 216 | { |
207 | struct sockaddr_in address; | 217 | struct sockaddr_in address; |
208 | socklen_t address_len = sizeof(address); | 218 | socklen_t address_len = sizeof(address); |
209 | warnx("waiting for connections on server file descriptor %d", server_fd); | 219 | verbose("waiting for connections on server file descriptor %d", server_fd); |
210 | 220 | ||
211 | size_t new_socket = -1; | 221 | size_t new_socket = -1; |
212 | while(-1 != | 222 | while(-1 != (new_socket = accept(server_fd, (struct sockaddr*) &address, &address_len))) |
213 | (new_socket = accept(server_fd, | ||
214 | (struct sockaddr*) &address, | ||
215 | &address_len))) | ||
216 | { | 223 | { |
217 | warnx("> Client %ld is connected via port %d", new_socket, address.sin_port); | 224 | verbose("> Client %ld is connected via port %d", new_socket, address.sin_port); |
218 | 225 | ||
219 | // set non blocking mode... | 226 | // set non blocking mode... |
220 | fcntl((size_t) new_socket, F_SETFL, | 227 | fcntl( |
221 | fcntl((size_t) new_socket, F_GETFL) | O_NONBLOCK); | 228 | (size_t) new_socket, |
229 | F_SETFL, | ||
230 | fcntl((size_t) new_socket, F_GETFL) | O_NONBLOCK | ||
231 | ); | ||
222 | 232 | ||
223 | next_customer(new_socket); | 233 | next_customer(new_socket); |
224 | 234 | ||