From 091c16ed7a88511b838a5c02ec12971d4acd49ea Mon Sep 17 00:00:00 2001 From: Brandon Rodriguez <brodriguez8774@gmail.com> Date: Sat, 9 Dec 2017 22:43:47 -0500 Subject: [PATCH] Add ability to parse client urls --- Main.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 168 insertions(+), 19 deletions(-) diff --git a/Main.c b/Main.c index 83cdf98..8c6b662 100644 --- a/Main.c +++ b/Main.c @@ -17,17 +17,20 @@ * */ +#define _BSD_SOURCE // Import headers. #include <arpa/inet.h> #include <ctype.h> +#include <dirent.h> #include <netdb.h> #include <pthread.h> #include <stdio.h> #include <string.h> #include <stdlib.h> -#include <sys/types.h> #include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> #include <unistd.h> #include "apue.h" #include "HelperHeader.h" @@ -48,6 +51,7 @@ struct conn_obj { int threads_finished; int thread_free[THREAD_MAX]; int thread_joinable[THREAD_MAX]; +char* media_path; struct sockaddr_in server_address; unsigned short port_number; pthread_t* thread_array; @@ -57,6 +61,7 @@ pthread_t* thread_array; void* serve_request(); // Handles processing of a request from a new thread. void join_threads(); // Attempts to join all finished child threads. void send_response(); // Generates and sends http response to requesting client. +char* generate_index(); // Generates server index page. /** @@ -69,7 +74,6 @@ int main(int argc, char* argv[]) { int listen_fd; int thread_created; int* conn_fd; - char* media_path; struct sockaddr_in* client_address; socklen_t address_len; pthread_attr_t attr; @@ -121,7 +125,7 @@ int main(int argc, char* argv[]) { printf("Server IP: %s\n", temp_string); // Actually listen for connections. Holds a buffer of 10 connections, if they back up. - return_int = listen(listen_fd, 10); + return_int = listen(listen_fd, 5); if (return_int < 0) { err_sys("Error on listen attempt"); } @@ -242,30 +246,175 @@ void join_threads() { * Generates and sends http response to requesting client. */ void send_response(struct conn_obj* connection) { + int index; + int return_int; + int iterate_bool = 1; + int file_found; char* temp_string; - char* response_buffer_1 = calloc(BUFFER_SIZE, sizeof(char*)); - char* response_buffer_2 = calloc(BUFFER_SIZE, sizeof(char*)); + char* temp_pointer; + char* client_request; + char* request_path; + char* file_path; + char* response_buffer_head = calloc(BUFFER_SIZE, sizeof(char*)); + char* response_buffer_body = calloc(BUFFER_SIZE, sizeof(char*)); + struct dirent* dir_struct; + struct stat stat_buffer; + DIR* dir_pointer; printf("Creating and sending response...\n\n"); - // First setup desired content. - strcat(response_buffer_2, "<body><h1>This is a response.</h1></body>"); + // Read client request first. + client_request = calloc(BUFFER_SIZE, sizeof(char)); + request_path = calloc(BUFFER_SIZE, sizeof(char)); + return_int = read(*connection->conn_fd, client_request, BUFFER_SIZE); + if (return_int < 0) { + err_msg("Could not read socket."); + } + printf("Client Request: \n%s\n", client_request); + + // Find start of request path. + printf("Parsing out request path...\n"); + temp_pointer = client_request; + + while (iterate_bool == 1) { + if ((*temp_pointer == ' ') && (*++temp_pointer) == '/') { + iterate_bool = 0; + } else if (temp_pointer == NULL) { + iterate_bool = 0; + } + ++temp_pointer; + } + + printf("Found start of request path! Reading path...\n"); + + // Read request path. + index = 0; + while (*temp_pointer != ' ') { + request_path[index] = *temp_pointer; + temp_pointer++; + index++; + } + printf("Request Path: %s\n", request_path); + printf("Media Path: %s\n", media_path); + + // Setup desired content based on client request path. + + // Check that directory has read permissions. + if (strcmp(request_path, "") == 0) { + // Index requested. Display all possible files. + strcat(response_buffer_body, "<body><h1>Server Index</h1>"); + generate_index(response_buffer_body); + } else { + // Search for matching file. + // Media directory is small so just iterate through all files every time. + dir_pointer = opendir(media_path); + strcat(response_buffer_body, "<body>"); + file_found = 0; + + while (dir_pointer != NULL) { + if ((dir_struct = readdir(dir_pointer)) != NULL) { + // More files found. Continue. + if ((strcmp(dir_struct->d_name, ".") != 0) && (strcmp(dir_struct->d_name, "..") != 0)) { + file_path = copy_string_with_buffer(media_path, BUFFER_SIZE); + strcat(file_path, "/"); + strcat(file_path, dir_struct->d_name); + + return_int = lstat(file_path, &stat_buffer); + if (return_int < 0) { + err_msg("Failed to stat file with err %d", return_int); + } else { + if (strcmp(to_lower_case(dir_struct->d_name), to_lower_case(request_path)) == 0) { + strcat(response_buffer_body, "<h1>"); + strcat(response_buffer_body, dir_struct->d_name); + strcat(response_buffer_body, "</h1>"); + file_found = 1; + } + } + free(file_path); + } + } else { + // End of directory. + return_int = closedir(dir_pointer); + if (return_int < 0) { + err_msg("Failed to properly close directory."); + } + dir_pointer = NULL; + } + } + + // Check that file was actually found. + if (file_found == 1) { + strcat(response_buffer_body, "</body>"); + } else { + strcat(response_buffer_body, "<body><h1>File was not found.</h1>"); + strcat(response_buffer_body, "<h2>Did you mean one of these?</h2>"); + generate_index(response_buffer_body); + } + } + + // strcat(response_buffer_body, "<body><h1>This is a response.</h1></body>"); - // Then set up response header. - strcat(response_buffer_1, "HTTP/1.2 200 Okay\r\n"); - strcat(response_buffer_1, "Server: Cat/1.0.0"); - strcat(response_buffer_1, "\r\n"); - strcat(response_buffer_1, "Content-Type: text/html\r\n"); - strcat(response_buffer_1, "Content-Length: "); + // Finally set up response header. + strcat(response_buffer_head, "HTTP/1.2 200 Okay\r\n"); + strcat(response_buffer_head, "Server: Cat/1.0.1"); + strcat(response_buffer_head, "\r\n"); + strcat(response_buffer_head, "Content-Type: text/html\r\n"); + strcat(response_buffer_head, "Content-Length: "); temp_string = calloc(BUFFER_SIZE, sizeof(char)); - sprintf(temp_string, "%ld", strlen(response_buffer_2)); - strcat(response_buffer_1, temp_string); - strcat(response_buffer_1, "\r\n\r\n"); + sprintf(temp_string, "%ld", strlen(response_buffer_body)); + strcat(response_buffer_head, temp_string); + strcat(response_buffer_head, "\r\n\r\n"); - printf("%s\n", response_buffer_1); + printf("%s\n", response_buffer_head); + printf("%s\n", response_buffer_body); // Send header. - send(*connection->conn_fd, response_buffer_1, (strlen(response_buffer_1) + 1), 0); + send(*connection->conn_fd, response_buffer_head, (strlen(response_buffer_head) + 1), 0); // Send actual content. - send(*connection->conn_fd, response_buffer_2, (strlen(response_buffer_2) + 1), 0); + send(*connection->conn_fd, response_buffer_body, (strlen(response_buffer_body) + 1), 0); +} + + +/** + * Generate index page of all possible media files to grab. + */ +char* generate_index(char* response_buffer_body) { + int return_int; + char* file_path; + struct dirent* dir_struct; + struct stat stat_buffer; + DIR* dir_pointer = opendir(media_path);; + + // Media directory is small so just iterate through all files every time. + while (dir_pointer != NULL) { + if ((dir_struct = readdir(dir_pointer)) != NULL) { + // More files found. Continue. + if ((strcmp(dir_struct->d_name, ".") != 0) && (strcmp(dir_struct->d_name, "..") != 0)) { + file_path = copy_string_with_buffer(media_path, BUFFER_SIZE); + strcat(file_path, "/"); + strcat(file_path, dir_struct->d_name); + + printf("File Name: %s\n", file_path); + return_int = lstat(file_path, &stat_buffer); + if (return_int < 0) { + err_sys("Failed to stat file with err %d", return_int); + } else { + strcat(response_buffer_body, "<p>"); + strcat(response_buffer_body, dir_struct->d_name); + strcat(response_buffer_body, "</p>"); + } + free(file_path); + } + } else { + // End of directory. + return_int = closedir(dir_pointer); + if (return_int < 0) { + err_msg("Failed to properly close directory."); + } + dir_pointer = NULL; + } + } + + strcat(response_buffer_body, "</body>"); + return response_buffer_body; } -- GitLab