diff --git a/Main.c b/Main.c
index 83cdf989537589e4e6c1e3fa6af29be88a1147ce..8c6b662fc93538096dc1044e5fd73738721b715f 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;
 }