diff --git a/http/client.c b/http/client.c
index 864a07c..2c1ed82 100644
--- a/http/client.c
+++ b/http/client.c
@@ -105,7 +105,7 @@ int main(int argc, char *argv[]) {
exit(EXIT_FAILURE);
}
- char reply[sizeof(int32_t)]; //< Set the variable to hold the server response. Set to a big length
+ char reply[__INT16_MAX__]; //< Set the variable to hold the server response. Set to a big length
if((recv(sockfd, reply, strlen(reply) - 1, 0)) < 0) { //< Receive response from the remote (-1 for the trailing terminating char)
(void) fprintf(stderr, "ERROR: Did not receive response from the remote.\n");
diff --git a/http/public/greetings.html b/http/public/greetings.html
index e69de29..6ce25b8 100644
--- a/http/public/greetings.html
+++ b/http/public/greetings.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Greetings
+
+
+
+ Hello, World!
+
+
\ No newline at end of file
diff --git a/http/public/index.html b/http/public/index.html
index e69de29..219d4c4 100644
--- a/http/public/index.html
+++ b/http/public/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Index
+
+
+
+ This is the index page
+
+
\ No newline at end of file
diff --git a/http/server.c b/http/server.c
index 5b61b9e..a7d99e2 100644
--- a/http/server.c
+++ b/http/server.c
@@ -14,7 +14,10 @@
#define LISTEN_BACKLOG 5 //< Define maximum size of the input queue
static int create_server_socket(uint16_t port, struct sockaddr_in incoming);
-static char * get_file_contents(char *dir, char *file);
+static char * setup_server_response(char* dir, char* filename, int current_session, int sockfd);
+static char * get_file_contents(char* dir, char* filename);
+static char * wday_to_string(int day);
+static char * month_to_string(int month);
int main(int argc, char *argv[]) {
check_opts_number(argc);
@@ -22,7 +25,7 @@ int main(int argc, char *argv[]) {
char *cport = "8080";
char *ifile = "index.html";
char *dir = NULL;
- char response[sizeof(int32_t)]; //< To hold the server response
+ char *response; //< To hold the server response
int c;
/// Process the options
@@ -70,46 +73,8 @@ int main(int argc, char *argv[]) {
/// Start accepting connections
int current_session = accept(sockfd, (struct sockaddr*) &incoming, &peer_addr_size); //< Save the current session
- if(current_session < 0) {
- (void) fprintf(stderr, "ERROR: Could not start accepting connections\n");
- close(sockfd);
- exit(EXIT_FAILURE);
- } else {
- char request[sizeof(int32_t)];
-
- if(recv(current_session, request, strlen(request) - 1, 0) < 0) {
- (void) fprintf(stderr, "ERROR: Could not receive connection from client\n");
- close(current_session);
- close(sockfd);
- exit(EXIT_FAILURE);
- } else {
- char method[4];
- strncpy(method, request, 4); //< Get the request type
- method[3] = 0; //< Add terminating char
-
- if(strcmp(method, "GET") == 0) {
- (void) fprintf(stdout, "Got here\n");
- close(current_session);
- close(sockfd);
- } else {
- fprintf(stderr, "ERROR: Unhandled HTTP request method received\n");
- char header[sizeof(int8_t) + 100];
- time_t t = time(NULL);
- struct tm tm = *localtime(&t);
- snprintf(
- header,
- sizeof header,
- "HTTP/1.1 501 Not Implemented\r\nDate: %d, %d %d %d %d:%d:%d %s\r\nContent-Length: 0\r\nConnection: close\r\n\r\n",
- tm.tm_wday, tm.tm_mday, tm.tm_mon, tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_zone
- ); //< Build the header
-
- puts(header);
- strncpy(response, header, sizeof(header));
- }
- close(current_session);
- close(sockfd);
- }
- }
+ /// Setup the server response
+ response = setup_server_response(dir, ifile, current_session, sockfd);
/// Send the response to the client
if(send(current_session, response, strlen(response) + 1, 0) < 0) {
@@ -185,6 +150,85 @@ static int create_server_socket(uint16_t port, struct sockaddr_in incoming) {
return sockfd;
}
+/**
+ * @brief Function to create the HTTP response
+ * @details Gets the client request
+ * If there is no current session, it exits with an error
+ * If the server could not receive a client connection, it exits with an error
+ * If a GET request is received, the function tries to open the resource:
+ * - if it could open it, it builds a 200 header and the file contents as body and adds them to response
+ * - if it could not open it, it builds a 404 header and adds it to response
+ * If anything other than a GET request is received, a 501 header is build, adds it to response and logs it
+ * At the end, it returns the server response with header and body (if available)
+ * @param dir - the directory of the file
+ * filename - the name of the file
+ * current_session - the current client session
+ * sockfd - the socket configuration
+ * @return response - A header with the status code and a body (if available)
+ **/
+static char * setup_server_response(char* dir, char* filename, int current_session, int sockfd) {
+ if(current_session < 0) {
+ (void) fprintf(stderr, "ERROR: Could not start accepting connections\n");
+ close(current_session);
+ close(sockfd);
+ exit(EXIT_FAILURE);
+ } else {
+ char request[__INT16_MAX__];
+ static char response[__INT16_MAX__];
+
+ if(recv(current_session, request, strlen(request) - 1, 0) < 0) {
+ (void) fprintf(stderr, "ERROR: Could not receive connection from client\n");
+ close(current_session);
+ close(sockfd);
+ exit(EXIT_FAILURE);
+ } else {
+ char method[4];
+ strncpy(method, request, 4); //< Get the request type
+ method[3] = 0; //< Add terminating char
+
+ char header[__INT8_MAX__ + 100];
+
+ if(strcmp(method, "GET") == 0) {
+ char *body = get_file_contents(dir, filename);
+
+ if(body != NULL) {
+ time_t t = time(NULL);
+ struct tm tm = *gmtime(&t);
+
+ char *wday = wday_to_string(tm.tm_wday);
+ char *month = month_to_string(tm.tm_mon + 1);
+
+ snprintf(
+ header,
+ sizeof header,
+ "HTTP/1.1 200 OK\r\nDate: %s, %d %s %d %d:%d:%d %s\r\nContent-Length: %ld\r\nConnection: close\r\n\r\n",
+ wday, tm.tm_mday, month, tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_zone, strlen(body)
+ ); //< Build the 200 header
+ strcat(response, header);
+ strcat(response, body);
+ } else {
+ snprintf(
+ header,
+ sizeof header,
+ "HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n"
+ ); //< Build the 404 header
+ strcat(response, header);
+ }
+ } else {
+ fprintf(stderr, "ERROR: Unhandled HTTP request method received\n");
+ snprintf(
+ header,
+ sizeof header,
+ "HTTP/1.1 501 Not ImplementedConnection: close\r\n\r\n"
+ ); //< Build 501 the header
+ strcat(response, header);
+ }
+
+ return response;
+ }
+ }
+}
+
/**
* @brief Function to take the contents of a specified file
* @details Gets the contents of the file specified
@@ -196,7 +240,8 @@ static int create_server_socket(uint16_t port, struct sockaddr_in incoming) {
* @return res - The contents of the file, formatted as a string
**/
static char * get_file_contents(char *dir, char *filename) {
- char *path = strcpy(dir, filename);
+ char path[strlen(dir) + strlen(filename) + 100]; //< set the variable for the path with a reasonable length
+ snprintf(path, sizeof path, "%s%s", dir, filename);
FILE *file = NULL;
@@ -221,3 +266,67 @@ static char * get_file_contents(char *dir, char *filename) {
return res;
}
}
+
+/**
+ * @brief Function to convert a int weekday to string weekday
+ * @details Gets the weekday as int, converts it to string and returns the string
+ * @param day - the weekday as int
+ * @return the weekday as a string
+ **/
+static char * wday_to_string(int day) {
+ switch(day) {
+ case 1:
+ return "Mon";
+ case 2:
+ return "Tue";
+ case 3:
+ return "Wed";
+ case 4:
+ return "Thu";
+ case 5:
+ return "Fri";
+ case 6:
+ return "Sat";
+ case 7:
+ return "Sun";
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * @brief Function to convert a int month to string month
+ * @details Gets the month as int, converts it to string and returns the string
+ * @param day - the month as int
+ * @return the month as a string
+ **/
+static char * month_to_string(int month) {
+ switch(month) {
+ case 1:
+ return "Jan";
+ case 2:
+ return "Feb";
+ case 3:
+ return "Mar";
+ case 4:
+ return "Apr";
+ case 5:
+ return "May";
+ case 6:
+ return "Jun";
+ case 7:
+ return "Jul";
+ case 8:
+ return "Aug";
+ case 9:
+ return "Sep";
+ case 10:
+ return "Oct";
+ case 11:
+ return "Nov";
+ case 12:
+ return "Dec";
+ default:
+ return NULL;
+ }
+}