From 89944e70b8e100e39ef65190ad1816dafde326eb Mon Sep 17 00:00:00 2001 From: Max Christian Pohle Date: Sun, 14 Nov 2021 15:23:27 +0100 Subject: 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. --- main.c | 79 +++++++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 25 deletions(-) diff --git a/main.c b/main.c index 9c1d177..6613df0 100644 --- a/main.c +++ b/main.c @@ -64,50 +64,80 @@ void * next_customer(void * new_socket) { char boundary[64] = {0}; int boundary_size = 0; + char current_name[64] = {0}; + usleep(100); // wait to avoid poll, epoll or evil select + char * output_buffer = NULL; + size_t output_buffer_length = 0; + FILE * output = open_memstream(&output_buffer, &output_buffer_length); + FILE * f = fdopen((size_t) new_socket, "r"); char buffer[MAX_HEADER_LINE_LENGTH]; - while(fgets(buffer, MAX_HEADER_LINE_LENGTH, f)) { - printf("%s [%d]", buffer, errno); + char * s = NULL; + while(1) { + // printf("[errno: %d] %s", errno, buffer); + s = fgets(buffer, MAX_HEADER_LINE_LENGTH, f); + + if(boundary[0] != '\0' && buffer[0] == '-') { // first char minus. could be a new chunk of post data + int i = 0; + for(i = 1; i < MAX_HEADER_LINE_LENGTH; i++) { + if(buffer[i] != '-') { // skip all minus + if(0 == strncmp(&buffer[i], boundary, boundary_size)) { + fflush(output); + printf("> name='%s' value='%*s'\n", current_name, (int) output_buffer_length, output_buffer); + setenv(current_name, output_buffer, 0); + current_name[0] = '\0'; + rewind(output); + i = 0; + + puts("================================================================================"); + } + break; + } + } + if (i == 0) continue; + } + - if(buffer[0] == '\n' || (buffer[0] == '\r' && buffer[1] == '\n')) { // either LF or CR/LF (windows) + if(!s || strspn(buffer, "\n\r") > 0) { // either LF or CR/LF (windows) puts("END HEADER\n"); - if (!boundary[0]) break; - continue; + // s != NULL ? break : continue; + if(!s) break; else continue; // either eof or only end of (chunk-)header } const char header_multipart[] = "Content-Type: multipart/form-data; boundary="; if (!boundary[0] && 0 == strncasecmp(buffer, header_multipart, sizeof(header_multipart) - 1)) { + // we could potentially optimize this part with strspn and moving the buffer point, why not? for(int i=sizeof(header_multipart); i [%s] %s\n", header_multipart, boundary); break; } + continue; } const char header_disposition[] = "Content-Disposition: form-data; "; if (boundary[0] && 0 == strncasecmp(header_disposition, buffer, sizeof(header_disposition) - 1)) { - printf("FFFFFFFFFFFFFFFFFFFFFFF %s\n", buffer); + printf("> %s :: %s\n", header_disposition, buffer); + const char header_disposition_name[] = "name=\""; + s = strstr(&buffer[sizeof(header_disposition) - 1], header_disposition_name); + if(s) { + s += sizeof(header_disposition_name) - 1; + s[strcspn(s, "\"")] = '\0'; + strncpy(current_name, s, 64); + printf("> /%s.*%s/ :: \"%s\"\n", header_disposition, header_disposition_name, s); + } else { + warnx("string not found in \"%s\".", &buffer[sizeof(header_disposition)]); + } continue; }// else { printf("FUCK: %*s [%d/%ld]\n", (int) sizeof(header_disposition), buffer, strncasecmp(header_disposition, buffer, sizeof(header_disposition)), sizeof(header_disposition)); } - if(buffer[0] == '-') { // first char minus. could be a new chunk of post data - for(int i=1; i NEXT CHUNK: %s\n", buffer); - i = 0; - } - break; - } - } - } else { - printf("%s", buffer); - } + printf("> [unknown] %s", buffer); + fputs(buffer, output); // 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[]) address.sin_port = htons(PORT); 0 == (server_fd = socket(AF_INET, SOCK_STREAM, 0)) - ? err(EXIT_FAILURE, NULL) + ? err(errno, NULL) : setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) - ? err(EXIT_FAILURE, "setsockopt failed on socket with fileno %d", server_fd) + ? err(errno, "setsockopt failed on socket with fileno %d", server_fd) : bind(server_fd, (struct sockaddr*) &address, sizeof(address)) - ? err(EXIT_FAILURE, NULL) + ? err(errno, NULL) : listen(server_fd, SOMAXCONN) - ? err(EXIT_FAILURE, NULL) + ? err(errno, NULL) : serve(server_fd); - return 0; } -- cgit v1.2.3