aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkartofen <mladenovnasko0@gmail.com>2023-01-26 14:58:09 +0200
committerkartofen <mladenovnasko0@gmail.com>2023-01-26 14:58:09 +0200
commit5e1ae8b33873661b669eda509fcd000f8a964126 (patch)
tree6099bee318d9f0033949d23a3eeded6974d34b35
very simple work withs html based on file path
-rw-r--r--.gitignore2
-rwxr-xr-xbuild.sh47
-rw-r--r--files/404.html10
-rw-r--r--files/500.html10
-rw-r--r--files/favicon.icobin0 -> 1406 bytes
-rw-r--r--files/index.html11
-rw-r--r--files/test/test1.html12
-rw-r--r--src/log.h14
-rw-r--r--src/main.c158
-rw-r--r--src/server.c122
-rw-r--r--src/server.h17
11 files changed, 403 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cbbd0b5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+bin/
+obj/ \ No newline at end of file
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..370c378
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+cd ${0%/*} # go to project root
+
+NAME="web-server"
+FLAGS="-std=c99 -Wall -Wextra -g -pedantic -D_POSIX_C_SOURCE=200112L"
+SRCD="src"
+ODIR="obj"
+BIN="bin"
+FILES="files"
+RUN=0
+
+function __run__ {
+ RUN=1
+}
+
+function __leak__ {
+ VALGRND="valgrind --leak-check=full --show-leak-kinds=all -s"
+ RUN=1
+}
+
+function __clean__ {
+ rm -rf $BIN
+ rm -rf $ODIR
+ exit 0
+}
+
+set -xe
+
+mkdir -p $BIN
+mkdir -p $ODIR
+mkdir -p $FILES
+
+if ! { [[ $# -eq 0 ]]; } 2> /dev/null
+then
+ __$1__
+fi
+
+gcc -c $SRCD/server.c -o $ODIR/server.o $FLAGS
+gcc -c $SRCD/main.c -o $ODIR/main.o $FLAGS -DFILES=\"$FILES\"
+
+gcc -o $BIN/$NAME $ODIR/main.o $ODIR/server.o $FLAGS
+
+if ! { [[ $RUN -eq 0 ]]; } 2> /dev/null
+then
+ $VALGRND $BIN/$NAME
+fi
diff --git a/files/404.html b/files/404.html
new file mode 100644
index 0000000..89c534e
--- /dev/null
+++ b/files/404.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>404</title>
+ </head>
+ <body>
+ <h1>404</h1>
+ <p>The content you are searching for could not be found</p>
+ </body>
+</html>
diff --git a/files/500.html b/files/500.html
new file mode 100644
index 0000000..33b174c
--- /dev/null
+++ b/files/500.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>500</title>
+ </head>
+ <body>
+ <h1>500</h1>
+ <p>There has been a server error</p>
+ </body>
+</html>
diff --git a/files/favicon.ico b/files/favicon.ico
new file mode 100644
index 0000000..91a517f
--- /dev/null
+++ b/files/favicon.ico
Binary files differ
diff --git a/files/index.html b/files/index.html
new file mode 100644
index 0000000..3a1c80c
--- /dev/null
+++ b/files/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Test</title>
+ </head>
+ <body>
+ <h1>Server</h1>
+ <p>This is a paragraph</p>
+ <a href="/test/test1.html">Test 1</a>
+ </body>
+</html>
diff --git a/files/test/test1.html b/files/test/test1.html
new file mode 100644
index 0000000..54d2265
--- /dev/null
+++ b/files/test/test1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>test1</title>
+ </head>
+ <body>
+ <h1>Test Something 1</h1>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Faucibus purus in massa tempor nec feugiat nisl pretium fusce. Id volutpat lacus laoreet non curabitur. Fringilla urna porttitor rhoncus dolor purus non. Lacus sed viverra tellus in hac habitasse platea. Massa tincidunt nunc pulvinar sapien et ligula ullamcorper malesuada proin. Duis at consectetur lorem donec massa sapien faucibus. Euismod in pellentesque massa placerat. In fermentum et sollicitudin ac orci. Diam phasellus vestibulum lorem sed risus ultricies tristique nulla. Leo integer malesuada nunc vel risus commodo. Quisque egestas diam in arcu cursus euismod quis viverra. Magna etiam tempor orci eu. Purus ut faucibus pulvinar elementum integer enim neque. </p>
+ <p>Risus viverra adipiscing at in tellus integer feugiat. Venenatis lectus magna fringilla urna. Lobortis mattis aliquam faucibus purus in. Cursus risus at ultrices mi tempus imperdiet nulla. Leo a diam sollicitudin tempor id eu. Diam sit amet nisl suscipit adipiscing. Nunc mattis enim ut tellus elementum sagittis vitae et leo. Purus non enim praesent elementum facilisis leo vel fringilla. Tellus in metus vulputate eu scelerisque felis imperdiet. Volutpat sed cras ornare arcu dui vivamus. Egestas egestas fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate. Lacus sed viverra tellus in hac. Amet nisl purus in mollis nunc sed id semper risus. Sit amet risus nullam eget felis. Massa enim nec dui nunc mattis enim ut tellus elementum. A pellentesque sit amet porttitor eget dolor. Elementum curabitur vitae nunc sed velit dignissim. Eget felis eget nunc lobortis mattis aliquam faucibus purus. </p>
+ </p> Amet dictum sit amet justo donec enim diam vulputate. Et sollicitudin ac orci phasellus egestas tellus rutrum. Ornare suspendisse sed nisi lacus sed. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Suspendisse potenti nullam ac tortor vitae purus faucibus ornare suspendisse. Fringilla ut morbi tincidunt augue interdum velit euismod in. Rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar pellentesque habitant. Imperdiet sed euismod nisi porta lorem mollis aliquam ut. Pulvinar elementum integer enim neque volutpat ac. Nunc non blandit massa enim nec dui nunc mattis enim. Nunc lobortis mattis aliquam faucibus purus in.</p>
+ </body>
+</html>
diff --git a/src/log.h b/src/log.h
new file mode 100644
index 0000000..000ce95
--- /dev/null
+++ b/src/log.h
@@ -0,0 +1,14 @@
+#ifndef LOG_H
+#define LOG_H
+
+#define __RED__ "\033[0;31m"
+#define __GREEN__ "\033[0;32m"
+#define __RESET__ "\033[0m"
+
+#define STR(x) #x
+#define XSTR(x) STR(x)
+
+#define info(...) fprintf(stdout, __GREEN__"[INFO]"__RESET__" "__VA_ARGS__); fprintf(stdout, "\n")
+#define err(...) fprintf(stderr, __RED__"[ERROR]"__RESET__" "__FILE__":"XSTR(__LINE__)": "__VA_ARGS__); fprintf(stderr, "\n")
+
+#endif
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..78a1069
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,158 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "log.h"
+#include "server.h"
+
+#define BUF_CAP 80000
+#define PORT "8079"
+
+#define SEND_BUF_ADD(str) do { \
+ memcpy(&send_buf[*send_buf_sz], str, strlen(str)); \
+ *send_buf_sz += strlen(str); \
+ } while(0)
+
+#define SEND_BUF_ADD_LINE(str) do { \
+ SEND_BUF_ADD(str); \
+ SEND_BUF_ADD("\r\n"); \
+ } while(0)
+
+static int try_file(char *req_path, FILE **fp)
+{
+ char file_path[1024];
+ sprintf(file_path, "%s%s", FILES,
+ (strlen(req_path) == 1) ? "/index.html" : req_path);
+
+ *fp = fopen(file_path, "r");
+ if(!(*fp)) {
+ err("fopen: file %s: %s", file_path, strerror(errno));
+ return 1;
+ }
+ info("fopen: file %s was opened", file_path);
+ return 0;
+}
+
+static int on_get(char *send_buf, ssize_t *send_buf_sz, char *req_path)
+{
+ SEND_BUF_ADD("HTTP/1.1 ");
+
+ FILE *fp;
+ if(try_file(req_path, &fp) != 0) {
+ if(errno == 2) { // 2 is 'No such file or directory'
+ SEND_BUF_ADD_LINE("404");
+ if(try_file("/404.html", &fp) != 0) return 1;
+ } else {
+ SEND_BUF_ADD_LINE("500");
+ if(try_file("/505.html", &fp) != 0) return 1;
+ }
+ } else {
+ SEND_BUF_ADD_LINE("200");
+ }
+
+ SEND_BUF_ADD_LINE("Server: potato");
+ // SEND_BUF_ADD_LINE("Content-Type: image/x-icon");
+ SEND_BUF_ADD("\r\n");
+
+ // fseek(fp, 0, SEEK_END);
+ // size_t file_sz = ftell(fp);
+ // rewind(fp);
+
+ // fread(&send_buf[*send_buf_sz], sizeof(char), file_sz, fp);
+ // *send_buf_sz += file_sz;
+
+ char line[BUF_CAP];
+ while(fgets(line, sizeof(line), fp) != NULL)
+ {
+ if(line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0';
+ SEND_BUF_ADD_LINE(line);
+ }
+
+ fclose(fp);
+ return 0;
+}
+
+static int handle_connection(sock_t *conn)
+{
+ char recv_buf[BUF_CAP] = {0};
+ ssize_t recv_buf_len = server_recv(conn, recv_buf, BUF_CAP);
+
+ if(recv_buf_len == 0) {
+ return 0;
+ } else if(recv_buf_len < 0) {
+ err("server_recv: %s", strerror(errno));
+ return 1;
+ }
+
+ /* HANDLE REQUEST */
+
+ char send_buf[BUF_CAP];
+ ssize_t send_buf_sz = 0;
+
+ char recv_buf_cpy[BUF_CAP];
+ memcpy(recv_buf_cpy, recv_buf, recv_buf_len);
+
+ char *req_method = strtok(recv_buf_cpy, " ");
+ if(strcmp(req_method, "GET") == 0) {
+ if(on_get(send_buf, &send_buf_sz, strtok(NULL, " "))) {
+ err("on_get: failed");
+ return 1;
+ }
+ } else {
+ err("request method %s has not been implemented", req_method);
+ return 1;
+ }
+
+ // TODO: handle when the whole message is not sent
+ ssize_t sent_sz = server_send(conn, send_buf, send_buf_sz);
+ if(sent_sz < 0) {
+ err("server_send: %s", strerror(errno));
+ return 1;
+ }
+
+ info("server_send: sent %ld out of %ld bytes", sent_sz, send_buf_sz);
+ return 0;
+}
+
+int main(void)
+{
+ signal(SIGCHLD, SIG_IGN); // now i dont have to wait()
+
+ sock_t *sock = server_sock_create();
+
+ if(server_start(PORT, sock) != 0) {
+ err("server_init: failed");
+ return 1;
+ }
+
+ for(int i = 0; ; i++) {
+ sock_t *conn = server_sock_create();
+ if(server_accept(sock, conn) != 0) {
+ err("server_accept: failed");
+ }
+
+ info("server: got connection with %s", server_connection_ip(conn));
+
+ pid_t p = fork();
+ if(p == 0) {
+ server_sock_close(sock);
+ if(handle_connection(conn) != 0) {
+ err("handle_connection: failed");
+ } else {
+ info("server: got disconnected with %s", server_connection_ip(conn));
+ }
+ server_sock_close(conn);
+ return 0;
+ } else if (p < 0){
+ err("fork: %s", strerror(errno));
+ return 1;
+ }
+ server_sock_close(conn);
+ }
+
+ server_sock_close(sock);
+ return 0;
+}
diff --git a/src/server.c b/src/server.c
new file mode 100644
index 0000000..73a8d59
--- /dev/null
+++ b/src/server.c
@@ -0,0 +1,122 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#include "log.h"
+#include "server.h"
+
+struct sock_t {
+ int sockfd;
+ char ip[INET6_ADDRSTRLEN];
+};
+
+static void *get_in_addr(struct sockaddr *sa)
+{
+ if (sa->sa_family == AF_INET) {
+ return &(((struct sockaddr_in*)sa)->sin_addr);
+ }
+
+ return &(((struct sockaddr_in6*)sa)->sin6_addr);
+}
+
+int server_start(char *port, sock_t *sock)
+{
+ struct addrinfo hints, *servinfo;
+ int rv;
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE; // use my IP
+
+ if ((rv = getaddrinfo(NULL, port, &hints, &servinfo)) != 0) {
+ err("getaddrinfo: %s", gai_strerror(rv));
+ return 1;
+ }
+
+ // loop through all the results and bind to the first we can
+ struct addrinfo *p = NULL;
+ for(p = servinfo; p != NULL; p = p->ai_next) {
+ if ((sock->sockfd = socket(p->ai_family, p->ai_socktype,
+ p->ai_protocol)) == -1) {
+ err("socker: %s", strerror(errno));
+ continue;
+ }
+
+ int yes=1;
+ if (setsockopt(sock->sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
+ sizeof(int)) == -1) {
+ err("setsockopt: %s", strerror(errno));
+ return 1;
+ }
+
+ if (bind(sock->sockfd, p->ai_addr, p->ai_addrlen) == -1) {
+ close(sock->sockfd);
+ err("bind: %s", strerror(errno));
+ continue;
+ }
+
+ break;
+ }
+
+ if (p == NULL) {
+ err("server: failed to bind");
+ return 1;
+ }
+
+ freeaddrinfo(servinfo);
+
+ if(listen(sock->sockfd, 10) == -1) {
+ err("listen: %s", strerror(errno));
+ return 1;
+ }
+ return 0;
+}
+
+int server_accept(sock_t *sock, sock_t *conn)
+{
+ struct sockaddr_storage conn_addr;
+ socklen_t sz = sizeof(conn_addr);
+ conn->sockfd = accept(sock->sockfd, (struct sockaddr *)&conn_addr, &sz);
+ if(conn->sockfd == -1) {
+ err("accept: %s", strerror(errno));
+ return 1;
+ }
+
+ inet_ntop(conn_addr.ss_family,
+ get_in_addr((struct sockaddr *)&conn_addr),
+ conn->ip, sizeof(conn->ip));
+
+ return 0;
+}
+
+ssize_t server_send(sock_t *sock, char *buf, size_t sz)
+{
+ return send(sock->sockfd, buf, sz, 0);
+}
+
+ssize_t server_recv(sock_t *sock, char *buf, size_t sz)
+{
+ return recv(sock->sockfd, buf, sz, 0);
+}
+
+char *server_connection_ip(sock_t *conn)
+{
+ return conn->ip;
+}
+
+sock_t *server_sock_create()
+{
+ return (sock_t *)malloc(sizeof(sock_t));
+}
+
+void server_sock_close(sock_t *s)
+{
+ close(s->sockfd);
+ free(s);
+}
diff --git a/src/server.h b/src/server.h
new file mode 100644
index 0000000..f5107b5
--- /dev/null
+++ b/src/server.h
@@ -0,0 +1,17 @@
+#ifndef SERVER_H
+#define SERVER_H
+
+typedef struct sock_t sock_t;
+struct sock_t;
+
+int server_start(char *port, sock_t *sock);
+int server_accept(sock_t *sock, sock_t *conn);
+
+ssize_t server_send(sock_t *sock, char *buf, size_t sz);
+ssize_t server_recv(sock_t *sock, char *buf, size_t sz);
+char *server_connection_ip(sock_t *conn);
+
+sock_t *server_sock_create();
+void server_sock_close(sock_t *s);
+
+#endif