From 2f73f776f63939e527407e642f86b1ddc86364e1 Mon Sep 17 00:00:00 2001 From: Pin Date: Mon, 21 Feb 2022 15:03:26 -0500 Subject: [PATCH] Added HTTP request types --- cmd/server.c | 146 ++++++++++++++++++++++++++++++++-------- include/httpStruct.h | 1 + include/returnRequest.h | 4 +- include/utils.h | 2 + src/returnRequest.c | 21 +++++- src/utils.c | 13 ++++ 6 files changed, 155 insertions(+), 32 deletions(-) create mode 100644 include/utils.h create mode 100644 src/utils.c diff --git a/cmd/server.c b/cmd/server.c index 4e31638..a760adb 100644 --- a/cmd/server.c +++ b/cmd/server.c @@ -12,8 +12,10 @@ #include "socketHelp.h" #include "returnRequest.h" #include "server.h" +#include "utils.h" #define WEB_ROOT "content/" +#define BUFF_READ 1024 static int verbose_flag = 0; bool enableHTTPS = 0; @@ -29,16 +31,25 @@ int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) { char temp[1]; // Used to check newlines char *token = calloc(8, sizeof(char)); int line = 0; - char *checkLine = calloc(1000, sizeof(char)); + int contentCheck = 0; + unsigned char *checkLine = calloc(1000, sizeof(unsigned char)); + unsigned char *logLine = malloc(sizeof(unsigned char)); - for (int i = 0; i < strlen((char *)buffer); i++) { + // Creating empty requestBody + r->requestBody = calloc(8, sizeof(char)); + + for (int i = 0; i <= strlen((char *)buffer); i++) { temp[0] = buffer[i]; - if ((!strcmp(temp, "\n")) && (i != 0)) { + // Checking for newline character OR end of string + if (((!strcmp(temp, "\n")) && (i != 0)) || (i == strlen((char *)buffer))) { // Config Check if (line == 0) { - token = strtok(checkLine, " "); + logLine = calloc(strlen((char *)checkLine), sizeof(char)); + strcpy((char *)logLine, (char *)checkLine); + token = strtok((char *)checkLine, " "); // HTTP Request Type - if (!strcmp(token, "GET")) { + if ((!strcmp(token, "GET")) || (!strcmp(token, "POST")) || + (!strcmp(token, "PUT")) || (!strcmp(token, "DELETE"))) { // Grabbing HTTP Request Type r->requestType = malloc(strlen(token)); strcpy(r->requestType, token); @@ -50,36 +61,54 @@ int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) { token = strtok(NULL, ""); r->requestVersion = malloc(strlen(token)); strcpy(r->requestVersion, token); - } else if (!strcmp(token, "POST")) { - printDebug("POST RECEIVED"); - return 2; } else { + char *errMessage = "Unsupported request type: "; + logLine = calloc(strlen(errMessage) + strlen(token), sizeof(unsigned char)); + sprintf((char *)logLine, "%s%s", errMessage, token); + PrintLog(logLine); + free(logLine); + free(checkLine); return 2; } + // Log Request + PrintLog(logLine); } else { - token = strtok(checkLine, ":"); - // Host Check - if (!strcmp(token, "Host")) { - token = strtok(NULL, ""); - r->requestHost = malloc(strlen(token)); - strcpy(r->requestHost, token); + if (contentCheck) { // Once content check is set to one everything after is part of the body + r->requestBody = realloc(r->requestBody, + (strlen((char *)checkLine) + strlen((char *)r->requestBody) + 1)); + strcat((char *)r->requestBody, (char *)checkLine); + // Adding newline to requestBody + sprintf((char *)r->requestBody, "%s\n", r->requestBody); + } else { + if (strlen((char *)checkLine) == 1) { // Looking for blank empty line to end header info + contentCheck = 1; + } + token = strtok((char *)checkLine, ":"); + // Host Check + if (!strcmp(token, "Host")) { + token = strtok(NULL, ""); + r->requestHost = malloc(strlen(token)); + strcpy(r->requestHost, token); + } } - // Reset checkline } - if (strlen(checkLine) > 0) { + if (strlen((char *)checkLine) > 0) { // Clear checkLine - memset(checkLine,0,strlen(checkLine)); + memset(checkLine,0,strlen((char *)checkLine)); } line++; } else { - strcat(checkLine, temp); + strcat((char *)checkLine, temp); } } if (strlen(r->requestType) == 0) { + free(logLine); + free(checkLine); return -1; } + free(logLine); free(checkLine); return 0; } @@ -128,12 +157,41 @@ int handleGetRequest(int socket, struct HTTPRequest *r, SSL *ssl) { return 0; } +int handlePUTRequest(int socket, struct HTTPRequest *r, SSL *ssl) { + FILE *fp; + char *reqDir; + char * workingReqDir; + char errResponse[256]; + + if (!strcmp(r->requestDir, "/")) { + workingReqDir = "index.html"; + } else { + workingReqDir = r->requestDir; + } + + reqDir = calloc(strlen(WEB_ROOT) + strlen(workingReqDir), sizeof(char)); + sprintf(reqDir, "%s%s", WEB_ROOT, workingReqDir); + + fp = fopen(reqDir, "w"); + if (fp == NULL) { + sprintf(errResponse, "Error opening file: %s", workingReqDir); + printDebug(errResponse); + return404Request(socket, ssl); + return -1; + } + + fprintf(fp, "%s", r->requestBody); + + free(reqDir); + fclose(fp); + return201Request(socket, r->requestBody, ssl); + return 0; +} + int handleRequest(unsigned char buffer[], int socket, SSL *ssl) { struct HTTPRequest r; // Holds relevant HTTP request information int checkerr = 0; - printDebug("Received Request"); - // Grabbing relevant information out of request checkerr = parseHTTPRequest(buffer, &r); if (checkerr != 0) { // Checking for HTTP parsing error @@ -141,7 +199,7 @@ int handleRequest(unsigned char buffer[], int socket, SSL *ssl) { printDebug("Error reading request, returning empty 404"); } else { printDebug("Error parsing, returning 500"); - // return return500Request(socket, ssl); + return return501Request(socket, ssl); } return return400Request(socket, ssl); } @@ -149,10 +207,19 @@ int handleRequest(unsigned char buffer[], int socket, SSL *ssl) { if (!strcmp(r.requestType, "GET")) { handleGetRequest(socket, &r, ssl); return 0; + } else if (!strcmp(r.requestType, "POST")) { + return501Request(socket, ssl); + return 0; + } else if (!strcmp(r.requestType, "PUT")) { + handlePUTRequest(socket, &r, ssl); + return 0; + } else if (!strcmp(r.requestType, "DELETE")) { + return501Request(socket, ssl); + return 0; + } else { + return500Request(socket, ssl); + return 0; } - // Return response to socket - return200Request(socket, NULL ,ssl); - return 0; } int main(int argc, char **argv) { @@ -173,7 +240,8 @@ int main(int argc, char **argv) { SSL_CTX *ctx = NULL; - unsigned char *buffer = calloc(8096, sizeof(unsigned char)); + size_t bufSize = BUFF_READ; + unsigned char *buffer = calloc(bufSize, sizeof(unsigned char)); // Setting up options static const struct option long_options[] = { @@ -274,16 +342,38 @@ int main(int argc, char **argv) { perror("Accept connection error"); exit(EXIT_FAILURE); } + bufSize = BUFF_READ; if ( enableHTTPS ) { + size_t buffCont = 1; SSL *ssl; ssl = SSL_new(ctx); SSL_set_fd(ssl, new_socket); SSL_accept(ssl); - SSL_read(ssl, buffer, 8096); - handleRequest(buffer, new_socket, ssl); + do { + buffCont = SSL_read(ssl, buffer, BUFF_READ); + if (strlen((char *)buffer) == bufSize) { + bufSize *= 2; + buffer = realloc(buffer, bufSize); + } + } while(buffCont == 0); + if (strlen((char *)buffer) != 0) { + handleRequest(buffer, new_socket, ssl); + buffer = calloc(bufSize, sizeof(unsigned char)); + } else { + printDebug("Error reading from socket"); + } } else { - read(new_socket, buffer, 1024); + size_t buffCont = 1; + do { + buffCont = read(new_socket, buffer, BUFF_READ); + if (strlen((char *)buffer) == bufSize) { + bufSize *= 2; + buffer = realloc(buffer, bufSize); + } + } while(buffCont == 0); + handleRequest(buffer, new_socket, NULL); + buffer = calloc(bufSize, sizeof(unsigned char)); } close(new_socket); diff --git a/include/httpStruct.h b/include/httpStruct.h index 1f5e85b..e2fff74 100644 --- a/include/httpStruct.h +++ b/include/httpStruct.h @@ -7,4 +7,5 @@ struct HTTPRequest { char *requestVersion; char *requestHost; char *requestDir; + unsigned char *requestBody; }; diff --git a/include/returnRequest.h b/include/returnRequest.h index 9cc10d4..c0b551d 100644 --- a/include/returnRequest.h +++ b/include/returnRequest.h @@ -2,8 +2,8 @@ int returnRequest(int socket, char *message, int status); -int return200Request(int socket, unsigned char *content ,SSL *ssl); -int return201Request(int socket, unsigned char *content ,SSL *ssl); +int return200Request(int socket, unsigned char *content, SSL *ssl); +int return201Request(int socket, unsigned char *content, SSL *ssl); int return400Request(int socket, SSL *ssl); int return403Request(int socket, SSL *ssl); diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..bdf6f69 --- /dev/null +++ b/include/utils.h @@ -0,0 +1,2 @@ +int PrintLog(unsigned char *message); + diff --git a/src/returnRequest.c b/src/returnRequest.c index 4a6d10b..0148a34 100644 --- a/src/returnRequest.c +++ b/src/returnRequest.c @@ -18,20 +18,37 @@ int returnRequest(int socket, char *message, int status, SSL *ssl) { } int return200Request(int socket, unsigned char *content, SSL *ssl) { - char *message = "";//= "HTTP/1.1 200 OK\nContent-Length: 6\nConnection: close\n\nhello\n"; + char *message = ""; message = calloc(strlen((char *)content) + 128, sizeof(unsigned char)); sprintf(message, "HTTP/1.1 200 OK\nContent-Length: %zu\nConnection: close\n\n%s\n", strlen((char *)content), content); return returnRequest(socket, message, 200, ssl); } +int return201Request(int socket, unsigned char *content, SSL *ssl) { + char *message = ""; + message = calloc(strlen((char *)content) + 128, sizeof(unsigned char)); + sprintf(message, "HTTP/1.1 201 Created\nContent-Length: %zu\nConnection: close\n\n%s\n", + strlen((char *)content), content); + return returnRequest(socket, message, 201, ssl); +} + int return404Request(int socket, SSL *ssl) { char *message = "HTTP/1.1 404 Not Found\nContent-Length: 12\nConnection: close\n\n404 Request\n"; return returnRequest(socket, message, 404, ssl); } int return400Request(int socket, SSL *ssl) { - char *message = "HTTP/1.1 400 HTTP Request Not Valid\n Content-Length: 0\nConnection: close\n\n"; + char *message = "HTTP/1.1 400 HTTP Request Not Valid\nContent-Length: 0\nConnection: close\n\n"; return returnRequest(socket, message, 400, ssl); } +int return500Request(int socket, SSL *ssl) { + char *message = "HTTP/1.1 500 Internal Server Error\nContent-Length: 0\nConnection: close\n\n"; + return returnRequest(socket, message, 500, ssl); +} + +int return501Request(int socket, SSL *ssl) { + char *message = "HTTP/1.1 501 Not Implemented\nContent-Length: 0\nConnection: close\n\n"; + return returnRequest(socket, message, 501, ssl); +} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..2c98c2b --- /dev/null +++ b/src/utils.c @@ -0,0 +1,13 @@ +#include +#include + +int PrintLog(unsigned char *message) { + time_t UTCTime; + // Setting time in EPOC + time(&UTCTime); + struct tm *now = localtime(&UTCTime); + + printf("[Log] %02d/%02d/%d %02d:%02d:%02d - %s\n", (now->tm_mon + 1), now->tm_mday, + (now->tm_year + 1900), now->tm_hour, now->tm_min, now->tm_sec, message); + return 0; +}