diff --git a/server/request_handling.c b/server/request_handling.c index 86517ce..413e7ec 100644 --- a/server/request_handling.c +++ b/server/request_handling.c @@ -87,9 +87,15 @@ int parse_request_line(const char *line, struct request_line *parsed_line) { * @param parsed_line The request_line made by parse_request_line */ void free_request_line_items(struct request_line *parsed_line) { - free(parsed_line->http_version); - free(parsed_line->method); - free(parsed_line->uri); + if (parsed_line->http_version != NULL) { + free(parsed_line->http_version); + } + if (parsed_line->method != NULL) { + free(parsed_line->method); + } + if (parsed_line->uri != NULL) { + free(parsed_line->uri); + } } /** diff --git a/server/socket_server.c b/server/socket_server.c index 10ed379..f92e972 100644 --- a/server/socket_server.c +++ b/server/socket_server.c @@ -168,20 +168,55 @@ static int send_file(int client_fd, struct requested_file file) { return 0; } +static enum request_parse_result parse_and_validate_request(struct http_message message, struct request_line *req_line) { + int parse_result = parse_request_line(message.start_line, req_line); + if (parse_result == -1) { + return PARSE_RESULT_MALFORMED; + } else if (strcmp(req_line->method, "GET") != 0) { + return PARSE_RESULT_BAD_METHOD; + } else if (strcmp(req_line->http_version, HTTP_VERSION) != 0) { + return PARSE_RESULT_BAD_VERSION; + } + + return PARSE_RESULT_OK; +} + enum socket_result serve_one_request(int sock_fd) { int client_fd = accept(sock_fd, NULL, NULL); if (client_fd == -1) { return RESULT_WRITE_ERROR; } struct http_message message = {}; - get_all_remote_parts(client_fd, TYPE_SERVER, &message); - struct request_line parsed_request_line; - int parse_result = parse_request_line(message.start_line, &parsed_request_line); - if (parse_result == -1) { + enum socket_result read_result = get_all_remote_parts(client_fd, TYPE_SERVER, &message); + if (read_result == RESULT_MALFORMED) { send_headers(400, client_fd, -1); + close(client_fd); + return RESULT_MALFORMED; + } else if (read_result != RESULT_OK){ + send_headers(500, client_fd, -1); + close(client_fd); + return RESULT_READ_ERROR; + } + struct request_line parsed_request_line = {}; + enum request_parse_result parse_result = parse_and_validate_request(message, &parsed_request_line); + // Ensure our the request line's info is congruent with the server's expectations. + if (parse_result != PARSE_RESULT_OK) { + int status_code = 500; + if (parse_result == PARSE_RESULT_MALFORMED) { + status_code = 400; + } else if (parse_result == PARSE_RESULT_BAD_METHOD) { + status_code = 405; + } else if (parse_result == PARSE_RESULT_BAD_VERSION) { + status_code = 505; + } + send_headers(status_code, client_fd, -1); free_request_line_items(&parsed_request_line); - free(message.start_line); - free(message.contents); + if (message.start_line != NULL) { + free(message.start_line); + } + if (message.contents != NULL) { + free(message.contents); + } if (message.headers != NULL) { free_headers(message.headers); } @@ -189,7 +224,8 @@ enum socket_result serve_one_request(int sock_fd) { close(client_fd); return RESULT_PROCESSING_ERROR; } - struct requested_file file; + // Attempt to read the file and return it. + struct requested_file file = {}; int file_result = get_file_from_url(parsed_request_line.uri, &file); if (file_result == -1) { int send_result = 0; @@ -199,8 +235,12 @@ enum socket_result serve_one_request(int sock_fd) { send_result = send_headers(403, client_fd, -1); } else { free_request_line_items(&parsed_request_line); - free(message.start_line); - free(message.contents); + if (message.start_line != NULL) { + free(message.start_line); + } + if (message.contents != NULL) { + free(message.contents); + } if (message.headers != NULL) { free_headers(message.headers); } @@ -212,8 +252,12 @@ enum socket_result serve_one_request(int sock_fd) { if (send_result != 0) { free_request_line_items(&parsed_request_line); - free(message.start_line); - free(message.contents); + if (message.start_line != NULL) { + free(message.start_line); + } + if (message.contents != NULL) { + free(message.contents); + } if (message.headers != NULL) { free_headers(message.headers); } @@ -226,8 +270,12 @@ enum socket_result serve_one_request(int sock_fd) { send_file(client_fd, file); } free_request_line_items(&parsed_request_line); - free(message.start_line); - free(message.contents); + if (message.start_line != NULL) { + free(message.start_line); + } + if (message.contents != NULL) { + free(message.contents); + } if (message.headers != NULL) { free_headers(message.headers); } diff --git a/server/socket_server.h b/server/socket_server.h index a29c941..0a109e3 100644 --- a/server/socket_server.h +++ b/server/socket_server.h @@ -9,6 +9,7 @@ #define FILE_BUFFER_SIZE 1024 enum server_status {STATUS_LISTENING, STATUS_CLOSED, STATUS_ERROR}; +enum request_parse_result {PARSE_RESULT_OK, PARSE_RESULT_MALFORMED, PARSE_RESULT_BAD_METHOD, PARSE_RESULT_BAD_VERSION}; struct server_info { int sock_fd; enum server_status status;