From 4057f6aeb1627e147f73baeccb6dea01e765ec54 Mon Sep 17 00:00:00 2001 From: Joey Vrba Date: Sat, 20 Jan 2024 10:43:41 -0500 Subject: [PATCH] POST requests without a target return path. If a POST request comes in the server doesn't actually care to do anything with it. So it just drops the information. Previously it would just break the connection, but now it sends back the path it received in the request. --- README.txt | 3 ++ asl.c | 6 ++-- crvr.c | 18 +++++++----- http.c | 85 ++++++++++++++++++++++++++++++++++++++---------------- http.h | 17 +++++++++-- 5 files changed, 92 insertions(+), 37 deletions(-) diff --git a/README.txt b/README.txt index 7f8388f..e4c9e0b 100644 --- a/README.txt +++ b/README.txt @@ -38,6 +38,9 @@ FUTURE ENHANCEMENTS Save card data when a quiz is completed. For each card, save the users's score for the front and back of the card and when it should next be reviewed. +Write automated tests so I don't have to do all this manual testing. Its +painful. + Split out the ASL specific stuff into its own project the server loads via .so. The idea here is to have the .so be an "application" that the server can be told to load with an attached URI. If that URI is specified in a request, the diff --git a/asl.c b/asl.c index 69bc81f..6756cb3 100644 --- a/asl.c +++ b/asl.c @@ -147,11 +147,11 @@ int asl_post(struct request *r, int client) static const struct str good_btn = STR("good"); static const struct str great_btn = STR("great"); - for (long i = 0; i < r->param_count; ++i) { + for (long i = 0; i < r->header_count; ++i) { printf("param %li=", i); - str_print(stdout, &r->params[i].key); + str_print(stdout, &r->headers[i].key); puts("="); - str_print(stdout, &r->params[i].value); + str_print(stdout, &r->headers[i].value); puts("\n"); } diff --git a/crvr.c b/crvr.c index e820c6e..c42e46e 100644 --- a/crvr.c +++ b/crvr.c @@ -79,13 +79,13 @@ static int parse_into_param(struct str *line, struct http_param *param) static int add_param_to_request(struct request *r, struct http_param *param) { if (!r || !param) return EINVAL; - assert(LEN(r->params) <= LONG_MAX); - if (r->param_count >= (long)LEN(r->params)) { + assert(LEN(r->headers) <= LONG_MAX); + if (r->header_count >= (long)LEN(r->headers)) { DEBUG("invalid param count"); return ENOBUFS; } - r->params[r->param_count] = *param; - r->param_count++; + r->headers[r->header_count] = *param; + r->header_count++; return 0; } @@ -111,8 +111,8 @@ static int parse_header_options(struct str rest_of_header, struct request *r) return EINVAL; } - while ((rest_of_header.len > 0) && (r->param_count < - (long)LEN(r->params))) + while ((rest_of_header.len > 0) && (r->header_count < + (long)LEN(r->headers))) { long eol = str_find_substr(&rest_of_header, &newline); struct str line; @@ -137,7 +137,7 @@ static int parse_header_options(struct str rest_of_header, struct request *r) error = add_param_to_request(r, ¶m); } - printf("Found %lu headers.\n", r->param_count); + printf("Found %lu headers.\n", r->header_count); return 0; } @@ -394,6 +394,10 @@ int handle_post_request(int client, struct request *r, struct pool *p, if (str_cmp_cstr(&r->path, "asl.html") == 0) return asl_post(r, client); + printf("No post response\n"); + + send_path(&r->path, client, p); + printf("Don't know what to do with post to \""); str_print(stdout, &r->path); printf("\"\n"); diff --git a/http.c b/http.c index 9356ab3..d19199b 100644 --- a/http.c +++ b/http.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -21,10 +22,10 @@ int find_param(const struct request *r, const char *param_name, if (!out || !r || !param_name) return EINVAL; static_assert(SIZE_MAX > LONG_MAX); - assert((size_t)r->param_count < LEN(r->params)); - for (long i = 0; i < r->param_count; ++i) { - if (str_cmp_cstr(&r->params[i].key, param_name) == 0) { - *out = r->params[i]; + assert((size_t)r->header_count < LEN(r->headers)); + for (long i = 0; i < r->header_count; ++i) { + if (str_cmp_cstr(&r->headers[i].key, param_name) == 0) { + *out = r->headers[i]; return 0; } } @@ -35,9 +36,9 @@ int header_find_value(struct request *r, const char *key, struct str *value) { if (!r || !key || !value) return EINVAL; - for (long i = 0; i < r->param_count; ++i) { - if (str_cmp_cstr(&r->params[i].key, key) == 0) { - *value = r->params[i].value; + for (long i = 0; i < r->header_count; ++i) { + if (str_cmp_cstr(&r->headers[i].key, key) == 0) { + *value = r->headers[i].value; return 0; } } @@ -62,14 +63,14 @@ void print_request(struct request *r) puts("\nFormat: "); str_print(stdout, &r->format); puts("\n"); - if (r->param_count > 0) { + if (r->header_count > 0) { printf("Parameters:\n" "-----------\n"); - for (long i = 0; i < r->param_count; ++i) { + for (long i = 0; i < r->header_count; ++i) { printf("%li: ", i); - str_print(stdout, &r->params[i].key); + str_print(stdout, &r->headers[i].key); puts(":"); - str_print(stdout, &r->params[i].value); + str_print(stdout, &r->headers[i].value); puts("\n"); } printf("-----------\n"); @@ -120,6 +121,27 @@ int send_data(int client, const char *header, const char *contents, return 0; } +int send_path(struct str *file_path, int client, struct pool *p) +{ + char path[PATH_MAX + 1] = {0}; + int err = str_copy_to_cstr(file_path, path, PATH_MAX); + if (err) { + fprintf(stderr, "Failed to copy path to c-string: %i\n", err); + return err; + } + FILE *f = fopen(path, "r"); + if (!f) { + fprintf(stderr, "Failed to open file \"%s\": %i\n", path, + errno); + return errno; + } + err = send_file(f, client, p); + fclose(f); + if (err) + fprintf(stderr, "send_file failed for \"%s\": %i\n", path, err); + return err; +} + int send_file(FILE *f, int client, struct pool *p) { char *contents; @@ -143,28 +165,41 @@ int send_file(FILE *f, int client, struct pool *p) return -1; } printf("File is %lu bytes.\n", file_size); - contents = calloc((size_t)file_size, sizeof(*contents)); + + long pool_cap = pool_get_remaining_capacity(p); + if (pool_cap < file_size) { + fprintf(stderr, "%s> No pool space. Needed %li have %li\n", + __func__, file_size, pool_cap); + return ENOBUFS; + } + long pool_pos = pool_get_position(p); + assert(pool_pos != -1); + contents = pool_alloc(p, file_size); if (!contents) { fprintf(stderr, "Failed to allocate buffer for file: %d.\n", errno); return errno; - } else { - chars_read = fread((void*)contents, sizeof(*contents), - (size_t)file_size, f); - if (chars_read != (size_t)file_size) { - printf("Failed to read in file: %lu of %ld\n", - chars_read, file_size); - result = errno; - } + } + // Note: don't return without resetting the pool now + + chars_read = fread((void*)contents, sizeof(*contents), + (size_t)file_size, f); + if (chars_read == (size_t)file_size) { result = send_data(client, ok_header, contents, (size_t)file_size); - if (result < 0) { - fprintf(stderr, "Failed to send message.\n"); - result = errno; - } - free(contents); + } else { + printf("Failed to read in file: %lu of %ld\n", chars_read, + file_size); + result = errno; + } + + if (result != 0) { + fprintf(stderr, "Failed to send message.\n"); + result = errno; } + pool_reset(p, pool_pos); + return result; } diff --git a/http.h b/http.h index 1a6de78..8d8dc05 100644 --- a/http.h +++ b/http.h @@ -45,8 +45,8 @@ struct request { enum request_type type; struct str path; struct str format; - long param_count; - struct http_param params[MAX_HEADER_LINES]; + long header_count; + struct http_param headers[MAX_HEADER_LINES]; struct str buffer; struct str post_params_buffer; }; @@ -103,6 +103,19 @@ void print_request(struct request *r); int send_data(int client, const char *header, const char *contents, size_t content_len); +/** + * @file Sends the file with the specified path to a client. + * + * @param[in] file_path - The path to the file to send. + * @param[in] client - The client to send the file to. + * @param[in] p - The pool to use to allocate space to send the file to the + * client. + * + * @return Returns 0 if the file is sent successfully. Otherwise returns an + * error code. + */ +int send_path(struct str *file_path, int client, struct pool *p); + /* * DEPRECATED Sends a file to the client with the HTTP 200 OK header. *