From 1488ec5a03b463e5c552c0af7eebdf16d3db4113 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Thu, 20 Jun 2024 13:29:01 +0300 Subject: [PATCH] Userspace: Implement the most basic http server This server just responds with static http "hello world" to every incoming request --- userspace/CMakeLists.txt | 1 + userspace/http-server/CMakeLists.txt | 9 +++ userspace/http-server/main.cpp | 110 +++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 userspace/http-server/CMakeLists.txt create mode 100644 userspace/http-server/main.cpp diff --git a/userspace/CMakeLists.txt b/userspace/CMakeLists.txt index 8d26d958..56654dc3 100644 --- a/userspace/CMakeLists.txt +++ b/userspace/CMakeLists.txt @@ -7,6 +7,7 @@ set(USERSPACE_PROJECTS dhcp-client echo getopt + http-server id image init diff --git a/userspace/http-server/CMakeLists.txt b/userspace/http-server/CMakeLists.txt new file mode 100644 index 00000000..778ef7b0 --- /dev/null +++ b/userspace/http-server/CMakeLists.txt @@ -0,0 +1,9 @@ +set(SOURCES + main.cpp +) + +add_executable(http-server ${SOURCES}) +banan_link_library(http-server ban) +banan_link_library(http-server libc) + +install(TARGETS http-server) diff --git a/userspace/http-server/main.cpp b/userspace/http-server/main.cpp new file mode 100644 index 00000000..e938d999 --- /dev/null +++ b/userspace/http-server/main.cpp @@ -0,0 +1,110 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + int socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (socket == -1) + { + perror("socket"); + return 1; + } + + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(8080); + addr.sin_addr.s_addr = INADDR_ANY; + if (bind(socket, (sockaddr*)&addr, sizeof(addr)) == -1) + { + perror("bind"); + return 1; + } + + if (listen(socket, SOMAXCONN) == -1) + { + perror("listen"); + return 1; + } + + printf("server started\n"); + + BAN::Vector clients; + + char buffer[1024]; + while (true) + { + int max_sock = socket; + + fd_set fds; + FD_ZERO(&fds); + FD_SET(socket, &fds); + for (int client : clients) + { + FD_SET(client, &fds); + max_sock = BAN::Math::max(client, max_sock); + } + + if (select(max_sock + 1, &fds, nullptr, nullptr, nullptr) == -1) + { + perror("select"); + break; + } + + if (FD_ISSET(socket, &fds)) + { + int client = accept(socket, nullptr, nullptr); + if (client == -1) + { + perror("accept"); + continue; + } + + printf("client %d connected\n", client); + + MUST(clients.push_back(client)); + } + + for (size_t i = 0; i < clients.size();) + { + if (!FD_ISSET(clients[i], &fds)) + { + i++; + continue; + } + + ssize_t nrecv = recv(clients[i], buffer, sizeof(buffer), 0); + if (nrecv < 0) + perror("recv"); + if (nrecv <= 0) + { + printf("%d disconnected\n", clients[i]); + close(clients[i]); + clients.remove(i); + continue; + } + + write(STDOUT_FILENO, buffer, nrecv); + + strcpy(buffer, "HTTP/1.1 200 OK\r\nContent-Length: 13\r\nConnection: close\r\n\r\nHello, world!"); + ssize_t nsend = send(clients[i], buffer, strlen(buffer), 0); + if (nsend < 0) + perror("send"); + if (nsend <= 0) + { + printf("%d disconnected\n", clients[i]); + close(clients[i]); + clients.remove(i); + continue; + } + + i++; + } + } +}