diff --git a/WebServer b/WebServer index 603b09e..a95d9aa 100755 Binary files a/WebServer and b/WebServer differ diff --git a/include/arrayHelper.h b/include/arrayHelper.h new file mode 100644 index 0000000..2ff0c1b --- /dev/null +++ b/include/arrayHelper.h @@ -0,0 +1,6 @@ +#ifndef ARRAYHELPER_H +#define ARRAYHELPER_H + +char *mergeArray(char *arr1, char *arr2); + +#endif \ No newline at end of file diff --git a/include/ipaddress.h b/include/ipaddress.h deleted file mode 100644 index 7f34cc0..0000000 --- a/include/ipaddress.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef IPADDRESS_H -#define IPADDRESS_H - -#include -#include -#include -#include - -#define MAX_LINE_LENGTH (1024) - -// This code has been borrowed from this github repo https://github.com/wasmerio/c-http-server and modified by me. - -int extract_ip_address_from_header(char *line, char *address); -char *get_ip_address(FILE *f); - -#endif \ No newline at end of file diff --git a/include/server.h b/include/server.h index 0483c3b..c5a1c3a 100644 --- a/include/server.h +++ b/include/server.h @@ -1,13 +1,26 @@ #ifndef SERVER_H #define SERVER_H -// This code has been borrowed from this github repo https://github.com/wasmerio/c-http-server and modified by me. - +#include +#include #include +#include +#include +#include -void send_response(FILE *f, char *html); -int open_connection(int port); -void accept_client(int sock, char *key); -void send_only(int port, char *key); +#define BUFFER_SIZE 1024 + +// This code has been borrowed from this github repo https://bruinsslot.jp/post/simple-http-webserver-in-c/ and modified by me. + +struct setup { + struct sockaddr_in host_addr; + struct sockaddr_in client_addr; + int sockfd; + int host_addrlen; + int client_addrlen; + char *response; +}; + +void serve(struct setup s); #endif \ No newline at end of file diff --git a/src/arrayHelper.c b/src/arrayHelper.c new file mode 100644 index 0000000..3da43e8 --- /dev/null +++ b/src/arrayHelper.c @@ -0,0 +1,15 @@ +#include +#include +#include "../include/arrayHelper.h" + +char *mergeArray(char *arr1, char *arr2){ + int arrSize1 = sizeof(arr1); + int arrSize2 = sizeof(arr2); + int totalSize = arrSize1 + arrSize2; + char *total = malloc(totalSize * sizeof(char)); + + memcpy(total, arr1, arrSize1 * sizeof(char)); + memcpy(total + arrSize2, arr2, arrSize2 * sizeof(char)); + + return total; +} \ No newline at end of file diff --git a/src/ipaddress.c b/src/ipaddress.c deleted file mode 100644 index e0cd140..0000000 --- a/src/ipaddress.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include -#include -#include -#include "../include/ipaddress.h" - -// This code has been borrowed from this github repo https://github.com/wasmerio/c-http-server and modified by me. - -int extract_ip_address_from_header(char *line, char *address) { - int found = 0; - char *ptr; - char *name; - char *value; - - name = strndup(line, MAX_LINE_LENGTH); - ptr = index(name, (int)':'); - if (ptr == NULL) { - return 0; - } - // end the string at the colon - *ptr = '\0'; - - // get the value part of the header field - ptr = index(line, (int) ':'); - value = strndup(ptr + 2, MAX_LINE_LENGTH); - - // most ugly way to remove \r\n from the end of the string - value[strlen(value)-2] = '\0'; - - if (strncmp(name, "X-Forwarded-For", MAX_LINE_LENGTH) == 0) { - found = 1; - strncpy(address, value, MAX_LINE_LENGTH); - } - - free(name); - free(value); - - return found; -} - -char *get_ip_address(FILE *f) { - int address_found = 0; - char *res; - char *ip_address = malloc (sizeof (char) * MAX_LINE_LENGTH); - char header_line[MAX_LINE_LENGTH]; - - do { - res = fgets(header_line, MAX_LINE_LENGTH, f); - - if (res != NULL) { - printf("%s", res); - - if (!address_found) { - address_found = extract_ip_address_from_header(res, ip_address); - } - } - } while (res != NULL && strcmp(header_line, "\r\n") != 0); - - return ip_address; -} \ No newline at end of file diff --git a/src/main.c b/src/main.c index d36b5f1..aaff34a 100644 --- a/src/main.c +++ b/src/main.c @@ -1,27 +1,79 @@ #include #include #include +#include "../include/arrayHelper.h" #include "../include/fileReader.h" #include "../include/server.h" -#include "../include/ipaddress.h" + +#include +#include +#include +#include +#include + +#define PORT 3090 +#define BUFFER_SIZE 1024 int main(int argc, char *argv[]) { - - if(argc <= 1) { - printf("Please provide options. \n"); - - return 0; - } - char *file = NULL; + file = ReadHTML("/home/skingging/Documents/Projects/C/C-Webserver/HTML/index.html"); - if(strcasecmp(argv[0], "cache")) { - file = ReadHTML("/home/skingging/Documents/Projects/C/C-Webserver/HTML/index.html"); + char buffer[BUFFER_SIZE]; + char resp[] = "HTTP/1.0 200 OK\r\n" + "Server: webserver-c\r\n" + "Content-type: text/html\r\n\r\n" + "hello, world\r\n"; + + char *temp = mergeArray(resp, file); + + // Create a socket + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + + if (sockfd == -1) { + perror("webserver (socket)"); + return 1; } - int port = 3090; - send_only(port, "address"); - exit(EXIT_SUCCESS); + printf("socket created successfully\n"); + + // Create the address to bind the socket to + struct sockaddr_in host_addr; + int host_addrlen = sizeof(host_addr); + + host_addr.sin_family = AF_INET; + host_addr.sin_port = htons(PORT); + host_addr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Create client address + struct sockaddr_in client_addr; + int client_addrlen = sizeof(client_addr); + + // Bind the socket to the address + if (bind(sockfd, (struct sockaddr *)&host_addr, host_addrlen) != 0) { + perror("webserver (bind)"); + return 1; + } + + printf("socket successfully bound to address\n"); + + // Listen for incoming connections + if (listen(sockfd, SOMAXCONN) != 0) { + perror("webserver (listen)"); + return 1; + } + + printf("server listening for connections\n"); + + struct setup s; + + s.client_addr = client_addr; + s.client_addrlen = client_addrlen; + s.host_addr = host_addr; + s.host_addrlen = host_addrlen; + s.response = resp; + s.sockfd = sockfd; + + serve(s); return 0; } \ No newline at end of file diff --git a/src/server.c b/src/server.c index 17b9973..ea3111b 100644 --- a/src/server.c +++ b/src/server.c @@ -1,103 +1,60 @@ +#include #include -#include -#include -#include -#include -#include -#include #include -#include "../include/ipaddress.h" +#include +#include #include "../include/server.h" -// This code has been borrowed from this github repo https://github.com/wasmerio/c-http-server and modified by me. +// This code has been borrowed from this github repo https://bruinsslot.jp/post/simple-http-webserver-in-c/ and modified by me. -void send_response(FILE *f, char *html) -{ - fprintf(f, "HTTP/1.1 200 OK\r\n"); - fprintf(f, "Content-Type: application/html\r\n"); - fprintf(f, "\r\n"); - fprintf(f, "%s", html); -} +#define PORT 3090 +#define BUFFER_SIZE 1024 -int open_connection(int port) -{ - int sock; - struct sockaddr_in addr_in; +void serve(struct setup s) { + char buffer[BUFFER_SIZE]; - printf("simpleserver::Creating socket: (%d, %d, 0)\n", AF_INET, SOCK_STREAM); - sock = socket(AF_INET, SOCK_STREAM, 0); - printf("simpleserver::Socket created (%d)\n", sock); - - if (sock == -1) - { - printf("Failed to create socket (%d)\n", errno); - exit(EXIT_FAILURE); - } - - addr_in.sin_family = AF_INET; - addr_in.sin_port = htons(port); - addr_in.sin_addr.s_addr = INADDR_ANY; - - printf("simpleserver::bind (%d, (%d, %d, %d), %lu)\n", sock, addr_in.sin_family, addr_in.sin_port, addr_in.sin_addr.s_addr, sizeof(struct sockaddr_in)); - - int lol = bind(sock, (struct sockaddr *)&addr_in, sizeof(struct sockaddr_in)); - - printf("simpleserver::listen(%d, 8)\n", sock); - - if (listen(sock, 8) == -1) - { - printf("Failed to get socket to listen (%d)\n", errno); - exit(EXIT_FAILURE); - } - - return sock; -} + for (;;) { + // Accept incoming connections + int newsockfd = accept(s.sockfd, (struct sockaddr *)&s.host_addr, (socklen_t *)&s.host_addrlen); + + if (newsockfd < 0) { + perror("webserver (accept)"); + continue; + } + + printf("connection accepted\n"); -void accept_client(int sock, char *key) -{ - struct sockaddr_in client_addr; - socklen_t clientaddr_len; - FILE *f; - - printf("simpleserver::accept(%d)\n", sock); - - int client_sock = accept(sock, (struct sockaddr *)&client_addr, &clientaddr_len); - printf("simpleserver::accepted (%d)\n", client_sock); - - if (client_sock == -1) - { - printf("Failed to accept connection (%d)\n", errno); - exit(EXIT_FAILURE); - } - - printf("simpleserver::fdopen(%d)\n", client_sock); - - f = fdopen(client_sock, "w+"); - - if (f == NULL){ - printf("simpleserver::Error during fdopen\n"); - } - - printf("simpleserver::send_response(%s)\n", key); - send_response(f, "

Hello

"); - - printf("simpleserver::fclose()\n"); - fclose(f); - - printf("simpleserver::fflush\n"); - // stdout needs to be flushed in order for heroku to read the logs - fflush(stdout); - printf("simpleserver::endfflush\n"); -} + // Get client address + int sockn = getsockname(newsockfd, (struct sockaddr *)&s.client_addr, (socklen_t *)&s.client_addrlen); + + if (sockn < 0) { + perror("webserver (getsockname)"); + continue; + } -void send_only(int port, char *key) -{ - int sock = open_connection(port); - - while (1) - { - accept_client(sock, key); + // Read from the socket + int valread = read(newsockfd, buffer, BUFFER_SIZE); + + if (valread < 0) { + perror("webserver (read)"); + continue; + } + + // Read the request + char method[BUFFER_SIZE], uri[BUFFER_SIZE], version[BUFFER_SIZE]; + + sscanf(buffer, "%s %s %s", method, uri, version); + + printf("[%s:%u] %s %s %s\n", inet_ntoa(s.client_addr.sin_addr), ntohs(s.client_addr.sin_port), method, version, uri); + + // Write to the socket + int valwrite = write(newsockfd, s.response, strlen(s.response)); + + if (valwrite < 0) { + perror("webserver (write)"); + continue; + } + + close(newsockfd); } - - close(sock); -} +} \ No newline at end of file