summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c150
1 files changed, 103 insertions, 47 deletions
diff --git a/main.c b/main.c
index b8be592..9c1d177 100644
--- a/main.c
+++ b/main.c
@@ -1,51 +1,25 @@
1#include <netinet/in.h> 1#include <netinet/in.h>
2#include <stdio.h> 2#include <stdio.h>
3#include <stdio_ext.h>
3#include <stdlib.h> 4#include <stdlib.h>
4#include <string.h> 5#include <string.h>
5#include <sys/socket.h> 6#include <sys/socket.h>
6#include <sys/epoll.h> 7#include <sys/epoll.h>
8#include <sys/sendfile.h>
7#include <fcntl.h> 9#include <fcntl.h>
8#include <unistd.h> 10#include <unistd.h>
11#include <poll.h>
9 12
10#include <err.h> 13#include <err.h>
11#include <errno.h> 14#include <errno.h>
12 15
13#include <pthread.h> 16#include <pthread.h>
14 17
15void * next_customer(void * new_socket)
16{
17 if (new_socket == 0) return NULL;
18
19
20 // read the input data...
21 char * input_buffer = {0};
22 size_t input_buffer_position = 0;
23 FILE * f_input = open_memstream(&input_buffer, &input_buffer_position);
24
25
26 for(
27 int size=1024,
28 read_buffer[1024] = {0};
29 size>0;
30 size=recv((size_t) new_socket, read_buffer, 1024, MSG_WAITALL)) {
31 fwrite(read_buffer, size, 1, f_input);
32 usleep(10); // TODO: implement with some sort of epoll
33 }
34
35 fflush(f_input);
36 printf("input_buffer has %ld bytes and contains:\n", input_buffer_position);
37
38 char * c = strstr(input_buffer, "Content-Type");
39 printf("WE ARE HERE: %s\n", c);
40 write(STDOUT_FILENO, input_buffer, input_buffer_position);
41
42
43 18
44 // answer the call...
45 19
46 char * buffer = {0}; 20void send_answer(void * new_socket) {
47 size_t buffer_position = 0; 21 FILE * f = fdopen((size_t) new_socket, "w");
48 FILE * f = open_memstream(&buffer, &buffer_position); 22 puts("> sending answer...");
49 fputs("HTTP/1.0 200 OK\n", f); 23 fputs("HTTP/1.0 200 OK\n", f);
50 fputs("content-type: text/html\n\n", f); 24 fputs("content-type: text/html\n\n", f);
51 fputs("<html>", f); 25 fputs("<html>", f);
@@ -57,19 +31,101 @@ void * next_customer(void * new_socket)
57 fputs("<label>Line1<br/>\n", f); 31 fputs("<label>Line1<br/>\n", f);
58 fputs("<textarea type=\"text\" name=\"text\"></textarea>", f); 32 fputs("<textarea type=\"text\" name=\"text\"></textarea>", f);
59 fputs("</label><br/>\n", f); 33 fputs("</label><br/>\n", f);
34 fputs("<input type=\"file\" name=\"okay\" value=\"ok\" />", f);
60 fputs("<input type=\"submit\" name=\"okay\" value=\"ok\" />", f); 35 fputs("<input type=\"submit\" name=\"okay\" value=\"ok\" />", f);
61 fputs("</form>", f); 36 fputs("</form>", f);
62 fputs("</html>\n", f); 37 fputs("</html>\n\0", f);
63 fflush(f); 38 fflush(f);
64 printf("OOOOO [%ld] %s\n", buffer_position, buffer); 39 puts("> answer sent.");
65
66 send((size_t) new_socket, buffer, buffer_position, MSG_EOR);
67 // fclose(f_socket);
68 close((size_t) new_socket);
69 fclose(f_input);
70 fclose(f); 40 fclose(f);
41}
42
43
44// #define FOREACH_HEADER(HEADER) \
45// HEADER("Content-Type: multipart/form-data; boundary=")
46// #define GENERATE_HEADERS(H) sizeof(H), H
47//
48// typedef struct {
49// const int length;
50// const char * string;
51// } length_value;
52//
53// const length_value headers[] = {
54// FOREACH_HEADER(GENERATE_HEADERS)
55// };
56
57
58void * next_customer(void * new_socket) {
59 if (new_socket == 0) return NULL;
60
61 const int MAX_HEADER_LINE_LENGTH = 1024;
62 const int MAX_BOUNDARY_LENGTH = 64;
63
64 char boundary[64] = {0};
65 int boundary_size = 0;
66
67 usleep(100); // wait to avoid poll, epoll or evil select
68
69 FILE * f = fdopen((size_t) new_socket, "r");
70 char buffer[MAX_HEADER_LINE_LENGTH];
71 while(fgets(buffer, MAX_HEADER_LINE_LENGTH, f)) {
72 printf("%s [%d]", buffer, errno);
73
74 if(buffer[0] == '\n' || (buffer[0] == '\r' && buffer[1] == '\n')) { // either LF or CR/LF (windows)
75 puts("END HEADER\n");
76 if (!boundary[0]) break;
77 continue;
78 }
79
80 const char header_multipart[] = "Content-Type: multipart/form-data; boundary=";
81 if (!boundary[0] && 0 == strncasecmp(buffer, header_multipart, sizeof(header_multipart) - 1)) {
82 for(int i=sizeof(header_multipart); i<MAX_HEADER_LINE_LENGTH; i++)
83 if(buffer[i] != '-') {
84 strncpy(boundary, &buffer[i], 64);
85 boundary_size = strnlen(boundary, 64);
86 boundary[boundary_size] = '\0';
87 printf("BOUNDARY[%d]: %s\n", boundary_size, boundary);
88 break;
89 }
90 }
91
92 const char header_disposition[] = "Content-Disposition: form-data; ";
93 if (boundary[0] && 0 == strncasecmp(header_disposition, buffer, sizeof(header_disposition) - 1)) {
94 printf("FFFFFFFFFFFFFFFFFFFFFFF %s\n", buffer);
95 continue;
96 }// else { printf("FUCK: %*s [%d/%ld]\n", (int) sizeof(header_disposition), buffer, strncasecmp(header_disposition, buffer, sizeof(header_disposition)), sizeof(header_disposition)); }
97
98 if(buffer[0] == '-') { // first char minus. could be a new chunk of post data
99 for(int i=1; i<MAX_HEADER_LINE_LENGTH; i++) {
100 if(buffer[i] != '-') { // skip all minus
101 if(0 == strncmp(&buffer[i], boundary, boundary_size)) {
102 printf("\n\n> NEXT CHUNK: %s\n", buffer);
103 i = 0;
104 }
105 break;
106 }
107 }
108 } else {
109 printf("%s", buffer);
110 }
111
112
113 // I think another if could now search for "Content-Disposition: form-data; " and store the remaining fields
114 // somewhere, e.g. name="okay"; filename="1.gif". Also there may also be a content-type per chunk, which we
115 // could also add and erase, where I have currently NEXT CHUNK.
116 // After that the text output (printf("%s", buffer)) will only contain content without headers, so that printf
117 // can then be replaced with some fwrite to a memstream and we are done :)
118 }
119
120 puts("> sending answer...");
121 send_answer(new_socket);
122 puts("> answer sent.");
123
71 124
72 return NULL; 125 puts("> file closed.");
126 //close((size_t) new_socket);
127 // pthread_exit(EXIT_SUCCESS);
128 return NULL;
73} 129}
74 130
75void serve(int server_fd) 131void serve(int server_fd)
@@ -84,17 +140,17 @@ void serve(int server_fd)
84 warn("next: %ld\n", new_socket); 140 warn("next: %ld\n", new_socket);
85 // set non blocking mode... 141 // set non blocking mode...
86 fcntl((size_t) new_socket, F_SETFL, 142 fcntl((size_t) new_socket, F_SETFL,
87 fcntl((size_t) new_socket, F_GETFL) | O_NONBLOCK); 143 fcntl((size_t) new_socket, F_GETFL) | O_NONBLOCK);
88 144
89 // next_customer(new_socket); 145 next_customer((void*) new_socket);
90 pthread_t thread_id; 146 // pthread_t thread_id;
91 pthread_create(&thread_id, NULL, next_customer, (void*) new_socket); 147 // pthread_create(&thread_id, NULL, next_customer, (void*) new_socket);
92 pthread_join(thread_id, NULL); 148 // pthread_join(thread_id, NULL);
93 } 149 }
94} 150}
95 151
96#define PORT 8080 152#define PORT 8080
97int main(int argc, char const *argv[]) 153int main(int argc, char const *argv[])
98{ 154{
99 int server_fd; 155 int server_fd;
100 int opt = 1; 156 int opt = 1;
@@ -110,7 +166,7 @@ int main(int argc, char const *argv[])
110 ? err(EXIT_FAILURE, "setsockopt failed on socket with fileno %d", server_fd) 166 ? err(EXIT_FAILURE, "setsockopt failed on socket with fileno %d", server_fd)
111 : bind(server_fd, (struct sockaddr*) &address, sizeof(address)) 167 : bind(server_fd, (struct sockaddr*) &address, sizeof(address))
112 ? err(EXIT_FAILURE, NULL) 168 ? err(EXIT_FAILURE, NULL)
113 : listen(server_fd, 3) 169 : listen(server_fd, SOMAXCONN)
114 ? err(EXIT_FAILURE, NULL) 170 ? err(EXIT_FAILURE, NULL)
115 : serve(server_fd); 171 : serve(server_fd);
116 172
..