added forking
This commit is contained in:
180
cmd/server.c
180
cmd/server.c
@@ -6,6 +6,8 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <errno.h>
|
||||
#include <wait.h>
|
||||
|
||||
// Local Includes
|
||||
#include "httpStruct.h"
|
||||
@@ -14,12 +16,15 @@
|
||||
#include "server.h"
|
||||
#include "utils.h"
|
||||
|
||||
//#define WEB_ROOT "/var/www/html/"
|
||||
#define WEB_ROOT "content/"
|
||||
#define BUFF_READ 1024
|
||||
|
||||
static int verbose_flag = 0;
|
||||
bool enableHTTPS = 0;
|
||||
|
||||
static int timeout = 0;
|
||||
|
||||
int printDebug(char message[]) {
|
||||
if (verbose_flag == 1) {
|
||||
printf("[Debug] %s\n", message);
|
||||
@@ -43,13 +48,14 @@ int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) {
|
||||
// Checking for newline character OR end of string
|
||||
if (((!strcmp(temp, "\n")) && (i != 0)) || (i == strlen((char *)buffer))) {
|
||||
// Config Check
|
||||
if (line == 0) {
|
||||
if (line == 0) { // Grabbing first line for type parsing
|
||||
logLine = calloc(strlen((char *)checkLine), sizeof(char));
|
||||
strcpy((char *)logLine, (char *)checkLine);
|
||||
token = strtok((char *)checkLine, " ");
|
||||
// HTTP Request Type
|
||||
if ((!strcmp(token, "GET")) || (!strcmp(token, "POST")) ||
|
||||
(!strcmp(token, "PUT")) || (!strcmp(token, "DELETE"))) {
|
||||
(!strcmp(token, "PUT")) || (!strcmp(token, "DELETE")) ||
|
||||
(!strcmp(token, "CONNECT"))) {
|
||||
// Grabbing HTTP Request Type
|
||||
r->requestType = malloc(strlen(token));
|
||||
strcpy(r->requestType, token);
|
||||
@@ -59,27 +65,24 @@ int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) {
|
||||
strcpy(r->requestDir, token);
|
||||
// Grabbing HTTP Request Version
|
||||
token = strtok(NULL, "");
|
||||
token[strlen(token) - 1] = '\0'; // Fixing version end char
|
||||
r->requestVersion = malloc(strlen(token));
|
||||
strcpy(r->requestVersion, token);
|
||||
} else {
|
||||
char *errMessage = "Unsupported request type: ";
|
||||
logLine = calloc(strlen(errMessage) + strlen(token), sizeof(unsigned char));
|
||||
sprintf((char *)logLine, "%s%s", errMessage, token);
|
||||
PrintLog(logLine);
|
||||
} else { // First line contains unsupported request
|
||||
free(logLine);
|
||||
free(checkLine);
|
||||
return 2;
|
||||
}
|
||||
// Log Request
|
||||
PrintLog(logLine);
|
||||
} else {
|
||||
} else { // Gather information on >first line
|
||||
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 {
|
||||
} else { // Information parsing !content
|
||||
if (strlen((char *)checkLine) == 1) { // Looking for blank empty line to end header info
|
||||
contentCheck = 1;
|
||||
}
|
||||
@@ -127,7 +130,7 @@ int handleGetRequest(int socket, struct HTTPRequest *r, SSL *ssl) {
|
||||
} else {
|
||||
workingReqDir = r->requestDir;
|
||||
}
|
||||
char *reqDir = calloc(strlen(WEB_ROOT) + strlen(workingReqDir), sizeof(char));
|
||||
char *reqDir = calloc((strlen(WEB_ROOT) + strlen(workingReqDir) + 1), sizeof(char));
|
||||
|
||||
sprintf(reqDir, "%s%s", WEB_ROOT, workingReqDir);
|
||||
|
||||
@@ -176,15 +179,48 @@ int handlePUTRequest(int socket, struct HTTPRequest *r, SSL *ssl) {
|
||||
if (fp == NULL) {
|
||||
sprintf(errResponse, "Error opening file: %s", workingReqDir);
|
||||
printDebug(errResponse);
|
||||
return404Request(socket, ssl);
|
||||
return -1;
|
||||
return return404Request(socket, ssl);
|
||||
}
|
||||
|
||||
fprintf(fp, "%s", r->requestBody);
|
||||
|
||||
free(reqDir);
|
||||
fclose(fp);
|
||||
return201Request(socket, r->requestBody, ssl);
|
||||
return return201Request(socket, r->requestBody, ssl);
|
||||
}
|
||||
|
||||
int handleDELETERequest(int socket, struct HTTPRequest *r, SSL *ssl) {
|
||||
char *reqDir;
|
||||
char * workingReqDir;
|
||||
char logLine[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);
|
||||
|
||||
if (remove(reqDir) == 0) {
|
||||
sprintf(logLine, "Deleted file");
|
||||
free(reqDir);
|
||||
return return200Request(socket, NULL, ssl);
|
||||
} else {
|
||||
printDebug("Failed to delete file");
|
||||
free(reqDir);
|
||||
if (errno == 1) { // Permission denided
|
||||
return return403Request(socket, ssl);
|
||||
} else { // Catch all (likely file != exist)
|
||||
return return404Request(socket, ssl);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handlePOSTRequest(int socket, struct HTTPRequest *r, SSL *ssl) {
|
||||
return501Request(socket, ssl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -196,25 +232,33 @@ int handleRequest(unsigned char buffer[], int socket, SSL *ssl) {
|
||||
checkerr = parseHTTPRequest(buffer, &r);
|
||||
if (checkerr != 0) { // Checking for HTTP parsing error
|
||||
if (checkerr == -1) {
|
||||
printDebug("Error reading request, returning empty 404");
|
||||
printDebug("Error reading request, returning empty 500");
|
||||
return500Request(socket, ssl);
|
||||
} else {
|
||||
printDebug("Error parsing, returning 500");
|
||||
printDebug("Error parsing, returning 501");
|
||||
return return501Request(socket, ssl);
|
||||
}
|
||||
return return400Request(socket, ssl);
|
||||
} else {
|
||||
checkerr = checkHTTPVersion(r.requestVersion);
|
||||
if (checkerr != 0) {
|
||||
return return505Request(socket, ssl);
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(r.requestType, "GET")) {
|
||||
handleGetRequest(socket, &r, ssl);
|
||||
return 0;
|
||||
} else if (!strcmp(r.requestType, "POST")) {
|
||||
return501Request(socket, ssl);
|
||||
handlePOSTRequest(socket, &r, ssl);
|
||||
return 0;
|
||||
} else if (!strcmp(r.requestType, "PUT")) {
|
||||
handlePUTRequest(socket, &r, ssl);
|
||||
return 0;
|
||||
} else if (!strcmp(r.requestType, "DELETE")) {
|
||||
return501Request(socket, ssl);
|
||||
handleDELETERequest(socket, &r, ssl);
|
||||
return 0;
|
||||
} else if (!strcmp(r.requestType, "CONNECT")) {
|
||||
return200Request(socket, NULL, ssl);
|
||||
return 0;
|
||||
} else {
|
||||
return500Request(socket, ssl);
|
||||
@@ -222,6 +266,10 @@ int handleRequest(unsigned char buffer[], int socket, SSL *ssl) {
|
||||
}
|
||||
}
|
||||
|
||||
void timeoutChild(int sig) {
|
||||
timeout = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
struct sockaddr_in address;
|
||||
int server_fd, new_socket;
|
||||
@@ -342,41 +390,75 @@ 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);
|
||||
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));
|
||||
|
||||
// Forking process
|
||||
pid_t pid;
|
||||
pid = fork();
|
||||
|
||||
if (pid == 0) {
|
||||
pid_t pid2;
|
||||
pid2 = fork();
|
||||
|
||||
if (pid2 == 0) {
|
||||
bufSize = BUFF_READ;
|
||||
if ( enableHTTPS ) {
|
||||
size_t buffCont = 1;
|
||||
SSL *ssl;
|
||||
ssl = SSL_new(ctx);
|
||||
SSL_set_fd(ssl, new_socket);
|
||||
SSL_accept(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 {
|
||||
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));
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
} else if (pid2 < 0) {
|
||||
printDebug("Error forking supervisor...");
|
||||
} else {
|
||||
printDebug("Error reading from socket");
|
||||
int status;
|
||||
signal(SIGALRM, timeoutChild);
|
||||
alarm(2);
|
||||
pause();
|
||||
if (timeout) {
|
||||
status = waitpid(pid, NULL, WNOHANG);
|
||||
if (status == 0) {
|
||||
printDebug("Killing child");
|
||||
kill(pid2, 9);
|
||||
wait(NULL);
|
||||
}
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
close(new_socket);
|
||||
} else if (pid < 0) {
|
||||
printDebug("Error forking...");
|
||||
} else {
|
||||
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));
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
close(new_socket);
|
||||
continue;
|
||||
}
|
||||
|
||||
close(new_socket);
|
||||
}
|
||||
|
||||
free(privKeyFile);
|
||||
|
||||
Reference in New Issue
Block a user