summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorMax Christian Pohle2021-11-21 00:10:29 +0100
committerMax Christian Pohle2021-11-21 00:10:29 +0100
commitb7b47e662a75096c7f99881b0d609731d5d6c8ce (patch)
tree113da9bbb5335f6ba48f08029c9e5a050d6304b7 /main.c
parentf5e12f35af533713312f29054ad0ffd00c0fcabd (diff)
downloadohmycgi-b7b47e662a75096c7f99881b0d609731d5d6c8ce.tar.bz2
ohmycgi-b7b47e662a75096c7f99881b0d609731d5d6c8ce.zip
First working version
TODO: needs refactoring
Diffstat (limited to 'main.c')
-rw-r--r--main.c70
1 files changed, 15 insertions, 55 deletions
diff --git a/main.c b/main.c
index 3a0c5ca..8f1d3ef 100644
--- a/main.c
+++ b/main.c
@@ -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
70typedef struct { 57static 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
80void 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
99int 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
121void * next_customer(size_t new_socket) { 79static 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
267int serve(int server_fd) 229static 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
..