diff options
author | Max Christian Pohle | 2021-11-14 15:23:27 +0100 |
---|---|---|
committer | Max Christian Pohle | 2021-11-14 15:23:27 +0100 |
commit | 89944e70b8e100e39ef65190ad1816dafde326eb (patch) | |
tree | 7712082026a7e323c30faeabacb112af8069370c | |
parent | 8f0f398fc49cd5d0ed5d97099bd6547ea52ce44b (diff) | |
download | ohmycgi-89944e70b8e100e39ef65190ad1816dafde326eb.tar.bz2 ohmycgi-89944e70b8e100e39ef65190ad1816dafde326eb.zip |
Now that I can parse individual fields I see potential optimizations.
Well-- If I had read the entire input stream into the buffer, I would
afterwards be able to change the buffer in memory and append \0 in
places, where a name/value pair exists and that would every second pair
a name and avoid many unnecessary memcpy.
-rw-r--r-- | main.c | 79 |
1 files changed, 54 insertions, 25 deletions
@@ -64,50 +64,80 @@ void * next_customer(void * new_socket) { | |||
64 | char boundary[64] = {0}; | 64 | char boundary[64] = {0}; |
65 | int boundary_size = 0; | 65 | int boundary_size = 0; |
66 | 66 | ||
67 | char current_name[64] = {0}; | ||
68 | |||
67 | usleep(100); // wait to avoid poll, epoll or evil select | 69 | usleep(100); // wait to avoid poll, epoll or evil select |
68 | 70 | ||
71 | char * output_buffer = NULL; | ||
72 | size_t output_buffer_length = 0; | ||
73 | FILE * output = open_memstream(&output_buffer, &output_buffer_length); | ||
74 | |||
69 | FILE * f = fdopen((size_t) new_socket, "r"); | 75 | FILE * f = fdopen((size_t) new_socket, "r"); |
70 | char buffer[MAX_HEADER_LINE_LENGTH]; | 76 | char buffer[MAX_HEADER_LINE_LENGTH]; |
71 | while(fgets(buffer, MAX_HEADER_LINE_LENGTH, f)) { | 77 | char * s = NULL; |
72 | printf("%s [%d]", buffer, errno); | 78 | while(1) { |
79 | // printf("[errno: %d] %s", errno, buffer); | ||
80 | s = fgets(buffer, MAX_HEADER_LINE_LENGTH, f); | ||
81 | |||
82 | if(boundary[0] != '\0' && buffer[0] == '-') { // first char minus. could be a new chunk of post data | ||
83 | int i = 0; | ||
84 | for(i = 1; i < MAX_HEADER_LINE_LENGTH; i++) { | ||
85 | if(buffer[i] != '-') { // skip all minus | ||
86 | if(0 == strncmp(&buffer[i], boundary, boundary_size)) { | ||
87 | fflush(output); | ||
88 | printf("> name='%s' value='%*s'\n", current_name, (int) output_buffer_length, output_buffer); | ||
89 | setenv(current_name, output_buffer, 0); | ||
90 | current_name[0] = '\0'; | ||
91 | rewind(output); | ||
92 | i = 0; | ||
93 | |||
94 | puts("================================================================================"); | ||
95 | } | ||
96 | break; | ||
97 | } | ||
98 | } | ||
99 | if (i == 0) continue; | ||
100 | } | ||
101 | |||
73 | 102 | ||
74 | if(buffer[0] == '\n' || (buffer[0] == '\r' && buffer[1] == '\n')) { // either LF or CR/LF (windows) | 103 | if(!s || strspn(buffer, "\n\r") > 0) { // either LF or CR/LF (windows) |
75 | puts("END HEADER\n"); | 104 | puts("END HEADER\n"); |
76 | if (!boundary[0]) break; | 105 | // s != NULL ? break : continue; |
77 | continue; | 106 | if(!s) break; else continue; // either eof or only end of (chunk-)header |
78 | } | 107 | } |
79 | 108 | ||
80 | const char header_multipart[] = "Content-Type: multipart/form-data; boundary="; | 109 | const char header_multipart[] = "Content-Type: multipart/form-data; boundary="; |
81 | if (!boundary[0] && 0 == strncasecmp(buffer, header_multipart, sizeof(header_multipart) - 1)) { | 110 | if (!boundary[0] && 0 == strncasecmp(buffer, header_multipart, sizeof(header_multipart) - 1)) { |
111 | // we could potentially optimize this part with strspn and moving the buffer point, why not? | ||
82 | for(int i=sizeof(header_multipart); i<MAX_HEADER_LINE_LENGTH; i++) | 112 | for(int i=sizeof(header_multipart); i<MAX_HEADER_LINE_LENGTH; i++) |
83 | if(buffer[i] != '-') { | 113 | if(buffer[i] != '-') { |
84 | strncpy(boundary, &buffer[i], 64); | 114 | strncpy(boundary, &buffer[i], 64); |
85 | boundary_size = strnlen(boundary, 64); | 115 | boundary_size = strnlen(boundary, 64); |
86 | boundary[boundary_size] = '\0'; | 116 | boundary[boundary_size] = '\0'; |
87 | printf("BOUNDARY[%d]: %s\n", boundary_size, boundary); | 117 | printf("> [%s] %s\n", header_multipart, boundary); |
88 | break; | 118 | break; |
89 | } | 119 | } |
120 | continue; | ||
90 | } | 121 | } |
91 | 122 | ||
92 | const char header_disposition[] = "Content-Disposition: form-data; "; | 123 | const char header_disposition[] = "Content-Disposition: form-data; "; |
93 | if (boundary[0] && 0 == strncasecmp(header_disposition, buffer, sizeof(header_disposition) - 1)) { | 124 | if (boundary[0] && 0 == strncasecmp(header_disposition, buffer, sizeof(header_disposition) - 1)) { |
94 | printf("FFFFFFFFFFFFFFFFFFFFFFF %s\n", buffer); | 125 | printf("> %s :: %s\n", header_disposition, buffer); |
126 | const char header_disposition_name[] = "name=\""; | ||
127 | s = strstr(&buffer[sizeof(header_disposition) - 1], header_disposition_name); | ||
128 | if(s) { | ||
129 | s += sizeof(header_disposition_name) - 1; | ||
130 | s[strcspn(s, "\"")] = '\0'; | ||
131 | strncpy(current_name, s, 64); | ||
132 | printf("> /%s.*%s/ :: \"%s\"\n", header_disposition, header_disposition_name, s); | ||
133 | } else { | ||
134 | warnx("string not found in \"%s\".", &buffer[sizeof(header_disposition)]); | ||
135 | } | ||
95 | continue; | 136 | continue; |
96 | }// else { printf("FUCK: %*s [%d/%ld]\n", (int) sizeof(header_disposition), buffer, strncasecmp(header_disposition, buffer, sizeof(header_disposition)), sizeof(header_disposition)); } | 137 | }// else { printf("FUCK: %*s [%d/%ld]\n", (int) sizeof(header_disposition), buffer, strncasecmp(header_disposition, buffer, sizeof(header_disposition)), sizeof(header_disposition)); } |
97 | 138 | ||
98 | if(buffer[0] == '-') { // first char minus. could be a new chunk of post data | 139 | printf("> [unknown] %s", buffer); |
99 | for(int i=1; i<MAX_HEADER_LINE_LENGTH; i++) { | 140 | fputs(buffer, output); |
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 | 141 | ||
112 | 142 | ||
113 | // I think another if could now search for "Content-Disposition: form-data; " and store the remaining fields | 143 | // I think another if could now search for "Content-Disposition: form-data; " and store the remaining fields |
@@ -161,16 +191,15 @@ int main(int argc, char const *argv[]) | |||
161 | address.sin_port = htons(PORT); | 191 | address.sin_port = htons(PORT); |
162 | 192 | ||
163 | 0 == (server_fd = socket(AF_INET, SOCK_STREAM, 0)) | 193 | 0 == (server_fd = socket(AF_INET, SOCK_STREAM, 0)) |
164 | ? err(EXIT_FAILURE, NULL) | 194 | ? err(errno, NULL) |
165 | : setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) | 195 | : setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) |
166 | ? err(EXIT_FAILURE, "setsockopt failed on socket with fileno %d", server_fd) | 196 | ? err(errno, "setsockopt failed on socket with fileno %d", server_fd) |
167 | : bind(server_fd, (struct sockaddr*) &address, sizeof(address)) | 197 | : bind(server_fd, (struct sockaddr*) &address, sizeof(address)) |
168 | ? err(EXIT_FAILURE, NULL) | 198 | ? err(errno, NULL) |
169 | : listen(server_fd, SOMAXCONN) | 199 | : listen(server_fd, SOMAXCONN) |
170 | ? err(EXIT_FAILURE, NULL) | 200 | ? err(errno, NULL) |
171 | : serve(server_fd); | 201 | : serve(server_fd); |
172 | 202 | ||
173 | |||
174 | return 0; | 203 | return 0; |
175 | } | 204 | } |
176 | 205 | ||