summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Christian Pohle2021-11-16 12:18:36 +0100
committerMax Christian Pohle2021-11-16 12:18:36 +0100
commite2f46e15df9ef19be4f05583b5a9513cdbf09720 (patch)
tree3a1a31459994ccef6204564bc879ea5a1654eafe
parente2ca5eb8dde31ea31b7fa1014d087829e4146bac (diff)
downloadohmycgi-e2f46e15df9ef19be4f05583b5a9513cdbf09720.tar.bz2
ohmycgi-e2f46e15df9ef19be4f05583b5a9513cdbf09720.zip
First refactoring round
Still open: Split the header/body parser, but this is more complicated, so maybe some automated tests first.
-rw-r--r--main.c104
1 files changed, 57 insertions, 47 deletions
diff --git a/main.c b/main.c
index 69ac01e..2bf2e14 100644
--- a/main.c
+++ b/main.c
@@ -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
21void send_answer(FILE * f) { 22void 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
39void * 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; 45static 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)) { 50void 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 66void 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
86void * 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
..