From d6e59d18d34ddecb171f8c7d61ec81d37eeaa4ac Mon Sep 17 00:00:00 2001
From: Saleh Ahmed Khan <s.khan20@student.unimelb.edu.au>
Date: Wed, 18 Apr 2018 19:56:36 +1000
Subject: [PATCH] Code cleaned up, better separation of functions

---
 .gitignore            |  1 +
 .vscode/settings.json |  7 +++-
 get.c                 | 86 +++++++++++++++++++++++++++++++++----------
 get.h                 | 10 +++--
 server.c              | 43 +++++-----------------
 5 files changed, 91 insertions(+), 56 deletions(-)

diff --git a/.gitignore b/.gitignore
index b23ffb6..a4c86dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ test/*
 .vscode/c_cpp_properties.json
 .vscode/settings.json
 home/file.txt
+server
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 82a41b8..b150ea6 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -5,6 +5,11 @@
         "iostream": "c",
         "get.h": "c",
         "system_error": "c",
-        "ostream": "c"
+        "ostream": "c",
+        "initializer_list": "c",
+        "type_traits": "c",
+        "xstring": "c",
+        "xutility": "c",
+        "stdio.h": "c"
     }
 }
\ No newline at end of file
diff --git a/get.c b/get.c
index c9137a4..c9e9bd0 100644
--- a/get.c
+++ b/get.c
@@ -1,41 +1,89 @@
+#define FOUND_RESPONSE "HTTP/1.0 200 OK\r\n" /* add \n*/
+#define NOT_FOUND_RESPONSE "HTTP/1.0 404\r\n\r\n"
+
 #include "get.h"
 #include <stdio.h>
 #include <string.h>
+#include <pthread.h>
+#include <sys/types.h> 
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <sys/sendfile.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
-#define FOUND 0
-#define NOT_FOUND -1
+#define FOUND 1
+#define NOT_FOUND 0
 
-void get(char* req, char* root, FILE** content) {
-    // Extract just the file path from the request message into the char array 'path'.
-    const char* path_start = strstr(req, "GET") + 4;
-    const char* path_end = strstr(req, "HTTP")-1;
+void parse_request_and_send_response(char* root, char* buffer, int newsockfd) {
+    const char* path_start = strstr(buffer, "GET") + 4;
+    const char* path_end = strstr(buffer, "HTTP")-1;
     char path[path_end - path_start];
-    // int l = (path_end-path_start);
-    // printf("%c", l);
     strncpy(path, path_start, path_end - path_start); 
     path[sizeof(path)] = '\0'; // null terminator
     char full_path[sizeof(path) + sizeof(root)];
     strcpy(full_path, root);
-    strcat(full_path, path);
-    printf("%s\n _____ \n", full_path);
-    if (find_file(full_path) == FOUND) open_file(content, full_path);
-    else *content = NULL;
+	strcat(full_path, path);
 
+    /* If the file is found, repond with the 200 header and the file */
+    if (file_found(full_path)) respond_OK_and_send_file(full_path, newsockfd);
+    /* otherwise, respond with a 404 NOT FOUND response */
+    else respond_NOTFOUND(newsockfd);
 }
 
-int find_file(char* path_to_file) {
-    FILE *fp;
-    fp = fopen(path_to_file, "r");
+int file_found(char* path_to_file) {
+    /* Try to open the file at given path, check
+       if a non-NULL FILE pointer is returned */
+    FILE* fp = fopen(path_to_file, "r");
     if (fp != NULL) {
         fclose(fp);
-        printf("FOUND\n");
         return FOUND;
     } else {
-        printf("NOT FOUND\n");
         return NOT_FOUND;
     }  
 }
 
-void open_file(FILE** file, char* path_to_file) {
-    *file = fopen(path_to_file, "r");
+void respond_OK_and_send_file(char* full_path, int newsockfd) {
+    /* First open the file, get the information for
+       the header (size, mime type) and send the file */
+    int fd = open(full_path, O_RDONLY);
+    size_t size = get_size(fd);
+    char response[128];
+    make_response_header(response, full_path, size);
+    write(newsockfd, response, strlen(response));
+    sendfile(newsockfd, fd, NULL, size);
+    close(fd);
+}
+
+void respond_NOTFOUND(int newsockfd) {
+    /* Send a 404 NOT FOUND response to the client */
+    write(newsockfd, NOT_FOUND_RESPONSE, strlen(NOT_FOUND_RESPONSE));
+}
+
+size_t get_size(int fd) {
+    struct stat st;
+    fstat(fd, &st);
+    return st.st_size;
+}
+
+void get_mime_type(char* path, char* mime) {
+    if (strstr(path, ".jpg") != NULL) {
+		strcpy(mime, "image/jpeg");
+    } else if (strstr(path, ".html") != NULL) {
+        strcpy(mime, "text/html");
+    } else if (strstr(path, ".css") != NULL) {
+        strcpy(mime, "text/css");
+    } else if (strstr(path, ".js") != NULL) {
+        strcpy(mime, "text/javascript");
+    } else {
+        strcpy(mime, "unknown");
+    }
+}
+
+void make_response_header(char* response, char* path, size_t size) {
+    char mime[64];
+    get_mime_type(path, mime);
+    sprintf(response, "%sContent-Length: %zu\r\nContent-Type: %s\r\n\r\n", FOUND_RESPONSE, size, mime);
 }
\ No newline at end of file
diff --git a/get.h b/get.h
index 9fa75ea..8e62fe0 100644
--- a/get.h
+++ b/get.h
@@ -5,8 +5,12 @@
 #include <stdio.h>
 
 /* Prototypes for the functions */
-void get(char* req, char* root, FILE** content); // means everything incl header
-int find_file(char* path_to_file);
-void open_file(FILE** file, char* path_to_file);
+void parse_request_and_send_response(char* root, char* buffer, int newsockfd);
+int file_found(char* path_to_file);
+void respond_OK_and_send_file(char* full_path, int newsockfd);
+void respond_NOTFOUND(int newsockfd);
+void get_mime_type(char* path, char* mime);
+void make_response_header(char* response, char* full_path, size_t size);
+size_t get_size(int fd);
 
 #endif
\ No newline at end of file
diff --git a/server.c b/server.c
index a71fbd3..dc2e82a 100644
--- a/server.c
+++ b/server.c
@@ -4,11 +4,13 @@
 
 #define FOUND_RESPONSE "HTTP/1.0 200 OK\r\n" /* add \n*/
 #define NOT_FOUND_RESPONSE "HTTP/1.0 404\r\n\r\n"
+#define FOUND 0
 #define BUF 100000
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <pthread.h>
 #include <sys/types.h> 
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -27,7 +29,7 @@ int main(int argc, char *argv[])
 	socklen_t clilen;
 	int n;
 
-	if (argc < 2) {
+	if (argc < 2) { // change this
 		fprintf(stderr,"ERROR, no port provided\n");
 		exit(1);
 	}
@@ -41,9 +43,7 @@ int main(int argc, char *argv[])
 
 	
 	bzero((char *) &serv_addr, sizeof(serv_addr));
-
 	portno = atoi(argv[1]);
-	
 	/* Create address we're going to listen on (given port number)
 	 - converted to network byte order & any IP address for 
 	 this machine */
@@ -51,7 +51,7 @@ int main(int argc, char *argv[])
 	serv_addr.sin_addr.s_addr = INADDR_ANY;
 	serv_addr.sin_port = htons(portno);  // store in machine-neutral format
 
-	 /* Bind address to the socket */
+	/* Bind address to the socket */
 	if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
 		perror("ERROR on binding");
 		exit(1);
@@ -66,7 +66,6 @@ int main(int argc, char *argv[])
 	 be accepted. Get back a new file descriptor to communicate on. */
 	newsockfd = accept(	sockfd, (struct sockaddr *) &cli_addr, 
 						&clilen);
-
 	if (newsockfd < 0) {
 		perror("ERROR on accept");
 		exit(1);
@@ -77,38 +76,16 @@ int main(int argc, char *argv[])
 		then process */
 	n = read(newsockfd,buffer,BUF-1);
 	
-    /* *************** using the get.c functionality here: */
+    /* ******************************************************************************** */
+	/* ******************************************************************************** */
+	/* ******************************************************************************** */
 	char* root = argv[2];
 	// Extract just the file path from the request message into the char array 'path'.
-    const char* path_start = strstr(buffer, "GET") + 4;
-    const char* path_end = strstr(buffer, "HTTP")-1;
-    char path[path_end - path_start];
-    strncpy(path, path_start, path_end - path_start); 
-    path[sizeof(path)] = '\0'; // null terminator
-    char full_path[sizeof(path) + sizeof(root)];
-    strcpy(full_path, root);
-	strcat(full_path, path);
-	strcpy(full_path, strchr(strchr(full_path, '/')+1, '/')+1);
-    printf("%s\n (_(_(_)_)_) \n", full_path);
-    if (find_file(full_path) == 0) { // 0 =found
-		
-		int fd = open(full_path, O_RDONLY);
-		struct stat st;
-		fstat(fd, &st);
-		size_t size = st.st_size;
-		
-		char response[256];
-		sprintf(response, "%sContent-Length: %zu\r\n\r\n", FOUND_RESPONSE, size);//
-		printf("(%zu) Hellooo\n%s", size, response);
-		write(newsockfd, response, strlen(response));
-		sendfile(newsockfd, fd, NULL, size);
-	} else{
-		n = write(newsockfd, NOT_FOUND_RESPONSE, strlen(NOT_FOUND_RESPONSE));
-	}
+    parse_request_and_send_response(root, buffer, newsockfd);
 
 
-	printf("Here is the message: %s\n",buffer);
-	printf("Here is the path calculated: %s + %s = %s\n", root, path, full_path);
+	// printf("Here is the message: %s\n",buffer);
+	// printf("Here is the path calculated: %s + %s = %s\n", root, path, full_path);
 	
 	if (n < 0) {
 		perror("ERROR writing to socket");
-- 
GitLab