From 29bbb28f41869615c185acb1d7f9d0c95f406e7e Mon Sep 17 00:00:00 2001 From: rasmus Date: Mon, 10 Mar 2025 21:23:34 +0100 Subject: [PATCH] Add http server --- WebServer | Bin 17072 -> 18336 bytes include/ipaddress.h | 16 +++++++ include/server.h | 13 ++++++ makefile | 2 +- src/ipaddress.c | 60 ++++++++++++++++++++++++++ src/main.c | 26 +++++++++-- src/server.c | 103 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 216 insertions(+), 4 deletions(-) create mode 100644 include/ipaddress.h create mode 100644 include/server.h create mode 100644 src/ipaddress.c create mode 100644 src/server.c diff --git a/WebServer b/WebServer index 33d4802ef0f6f7b0b4f1fa2ea3f2587dcdcb820a..603b09ecb3a039095ec0edab42cc7e17191b6d6e 100755 GIT binary patch literal 18336 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 A@Bjb+ delta 2423 zcmZWreN0nV6u<8kMq5j13)(Vtef?00x>w4Vh#;?}!0UoeCo-a&1xu^V7$B6*5Hdyl zpvjErSr$#U3=`uL|5$1;^J5M%ApWssb4!+(ZJ93Hl4gQgrctAA-MR0>uN`vlx%YRz z?mh3^Q$`Om$-T^o&2rTw5K8h)NV4+Kl3(-@Rsu9lu39GcQjjsRyV*qp>;rsw{~6LKfY=h*j1zHjHe^kDMIcI2!m z2t=%=b3FGfRT1}2#B~=bkiHQenT$SB&an$*T+$!BCBjjQgAw5iOF`Z_3_<#GH;9Qp zQvG;}>C8`g_|r0fr>|+ldNJ`Z_1VAa^m&>9?_Du*J(!qET|fkvsSl6`!*_7${a#F5 zP94X6BDLvF-y4&@rg1IaaKrl4CzA3NF)^7siS7^VV8n1b6_e1*;@+S7^cVFs7g^L< zVut!%hRZ5fI>F$g7l4w_Vq!YSb z1v}%Bjt&wHcXaheNOw=HGae<;-bmyv(h=Jd=6k#Na?;Qk^w)-p`C`88@w%jxghE^2 z?&=Kn#@l-0p%5O6utf9tk5N_>XHZgy+(b7>eJ{pz1m&+1;*`MChdz9Pns1Wj#(9B^BiEcnuGg&DUYTZ^BaQWg#k%(_F27FI8`!oWg9cEwXNJ-ocQz}iFVV;vDL z+}61`&TWZs^xlzn4&E)St7Hl^D=W|ojdEcoogP5mIGavCLf(PA3He9Jw;_M+Ryutg z`9b7Y3B0q!$(vBL2q6;4GSQnA;aG-PCdH84I085-(Dev`=_O9~#4OBP>Z~n9^azeK zs2xU5{6^FJY`xL8PvbLkLm6zd(dILn{6;Myc_^O3A)*&M)eRU;8;#nrW12x-e$p&Z zi0o20EeuL^VCL;?iv^1L%?{BaNFco?C4mzpu9s%~8gPoQ@l7Z@8jli9FD0wYNQG07 zRw}Ml_IN~ziool!yRIp*@C|fPSUu2R%6{A-VBPjX%F{A-wde?AP#e`<>;$m3*k;I7 zu0lBlAX)6zwO9lxNGohFE-;uBmCqFwU9%!?rs8LJ&|c!6)2hfL76DGN3m{ptEvPz? z{NhBvB#WgWD9%-Ug@UUoR&lIdyj?yCKwGJYO`73wX|rxp0xe_*Z1?2C>5{zQcM>v} zXjciidO|-+OEXd1sw$bq1%pXXDK9|9HE^iR>fM9+Ifk#w7BbzE&2Gi!`A7$;bipwt-fbnGRKytbB;p*V zIM;g)S7z2kh)Yn;BC~0V<7w_YWjsTX{y_Z(Qz$iIQfUW&nr0EVuvoxKJoSkUQylND zR+01^(J&L%m0P`5R`&M%y5~XI=_P;aKQ!5tFYZ9QO@(Sdv z48pFJ3u+r8aoS>fWBu4bv9}6Ox64qZy)E9R^w(!4(O73p>A28cWjBOER8?-L@O#xp zXs`CbiE6V;>ebKMhMHE_hU(S?uO?)i8>SLD0Cd2x8vwE#0W}ngtV0>0+@!9n1 zGs4Eu@7u@B2gdKQsO>=DByFN)!0+eHYS$1QGTaA)evcX7ue2Rk(0Opl@6oHT{+a_G z_{+_YTZ2XJ_| z>XM!RO!dcF102J&z+jz6r&g>0=jxW5)o&jtlGQWdlFtrYy^RULiuxM1rwID%%k^Tb r>~+cu=j&I^)t1QGoKl`I;Wiht8 +#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 new file mode 100644 index 0000000..0483c3b --- /dev/null +++ b/include/server.h @@ -0,0 +1,13 @@ +#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 + +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); + +#endif \ No newline at end of file diff --git a/makefile b/makefile index f44e6cf..d4eb631 100644 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ # Makefile for hello.c CC = gcc # C compiler -CFLAGS = -O2 # Compiler flags (optimization level) +CFLAGS = -O2 # Compiler flags (optimization level) SRC_DIR = src BUILD_DIR = build diff --git a/src/ipaddress.c b/src/ipaddress.c new file mode 100644 index 0000000..e0cd140 --- /dev/null +++ b/src/ipaddress.c @@ -0,0 +1,60 @@ +#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 4cf920c..d36b5f1 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,27 @@ #include +#include +#include #include "../include/fileReader.h" +#include "../include/server.h" +#include "../include/ipaddress.h" -int main() { - char *file = ReadHTML("/home/skingging/Documents/Projects/C/C-Webserver/HTML/index.html"); - printf(file); +int main(int argc, char *argv[]) { + + if(argc <= 1) { + printf("Please provide options. \n"); + + return 0; + } + + char *file = NULL; + + if(strcasecmp(argv[0], "cache")) { + file = ReadHTML("/home/skingging/Documents/Projects/C/C-Webserver/HTML/index.html"); + } + + int port = 3090; + send_only(port, "address"); + exit(EXIT_SUCCESS); + + return 0; } \ No newline at end of file diff --git a/src/server.c b/src/server.c new file mode 100644 index 0000000..17b9973 --- /dev/null +++ b/src/server.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "../include/ipaddress.h" +#include "../include/server.h" + +// This code has been borrowed from this github repo https://github.com/wasmerio/c-http-server 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); +} + +int open_connection(int port) +{ + int sock; + struct sockaddr_in addr_in; + + 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; +} + +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"); +} + +void send_only(int port, char *key) +{ + int sock = open_connection(port); + + while (1) + { + accept_client(sock, key); + } + + close(sock); +}