From 76e6c3d690caac3faa664b7b8b79cbc7c6a58394 Mon Sep 17 00:00:00 2001 From: cflip Date: Thu, 7 Jul 2022 09:50:38 -0600 Subject: Initial commit --- .gitignore | 2 ++ Makefile | 12 ++++++++++++ src/ClientConnection.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ClientConnection.h | 16 ++++++++++++++++ src/HttpResponse.cpp | 16 ++++++++++++++++ src/HttpResponse.h | 18 ++++++++++++++++++ src/ServerConnection.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++ src/ServerConnection.h | 12 ++++++++++++ src/main.cpp | 25 ++++++++++++++++++++++++ 9 files changed, 193 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 src/ClientConnection.cpp create mode 100644 src/ClientConnection.h create mode 100644 src/HttpResponse.cpp create mode 100644 src/HttpResponse.h create mode 100644 src/ServerConnection.cpp create mode 100644 src/ServerConnection.h create mode 100644 src/main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..512d52b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Ignore executable binary +cfws diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8a44899 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +CC=clang++ +CFLAGS=-pedantic -Wall --std=c++11 + +SRC=src/main.cpp \ + src/ClientConnection.cpp \ + src/ServerConnection.cpp \ + src/HttpResponse.cpp + +OUT=cfws + +$(OUT): $(SRC) + $(CC) $(CFLAGS) -o $(OUT) $(SRC) diff --git a/src/ClientConnection.cpp b/src/ClientConnection.cpp new file mode 100644 index 0000000..3bf93c3 --- /dev/null +++ b/src/ClientConnection.cpp @@ -0,0 +1,49 @@ +#include "ClientConnection.h" + +#include +#include +#include + +ClientConnection::ClientConnection(int socket) + : m_socket_fd(socket) +{ +} + +void ClientConnection::dump_request_data() +{ + constexpr int BUFFER_SIZE = 4096; + char buffer[BUFFER_SIZE+1]; + int n; + + memset(buffer, 0, BUFFER_SIZE); + while ((n = read(m_socket_fd, buffer, BUFFER_SIZE-1)) > 0) { + std::cout << buffer; + + if (buffer[n-1] == '\n') + break; + + memset(buffer, 0, BUFFER_SIZE); + } +} + +bool ClientConnection::send(const HttpResponse& response, const char* message) +{ + if (!m_is_open) + return false; + + std::stringstream ss; + ss << response.to_string() + << "\r\n\r\n" + << message; + + std::string result = ss.str(); + write(m_socket_fd, result.c_str(), result.length()); + + return true; +} + +void ClientConnection::close() +{ + m_is_open = false; + ::close(m_socket_fd); +} diff --git a/src/ClientConnection.h b/src/ClientConnection.h new file mode 100644 index 0000000..6fdf99e --- /dev/null +++ b/src/ClientConnection.h @@ -0,0 +1,16 @@ +#pragma once + +#include "HttpResponse.h" + +class ClientConnection { +public: + ClientConnection(int socket); + + void dump_request_data(); + + bool send(const HttpResponse&, const char*); + void close(); +private: + int m_socket_fd; + bool m_is_open { true }; +}; diff --git a/src/HttpResponse.cpp b/src/HttpResponse.cpp new file mode 100644 index 0000000..c9c5ff4 --- /dev/null +++ b/src/HttpResponse.cpp @@ -0,0 +1,16 @@ +#include "HttpResponse.h" + +HttpResponse::HttpResponse(ResponseCode response_code) +{ + m_string_stream << "HTTP/1.0 200 OK"; +} + +void HttpResponse::add_header(std::string header) +{ + m_string_stream << '\n' << header; +} + +std::string HttpResponse::to_string() const +{ + return m_string_stream.str(); +} diff --git a/src/HttpResponse.h b/src/HttpResponse.h new file mode 100644 index 0000000..33148da --- /dev/null +++ b/src/HttpResponse.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +enum class ResponseCode { + OK = 200 +}; + +class HttpResponse { +public: + HttpResponse(ResponseCode); + + void add_header(std::string header); + std::string to_string() const; +private: + std::stringstream m_string_stream; +}; diff --git a/src/ServerConnection.cpp b/src/ServerConnection.cpp new file mode 100644 index 0000000..dd4fe86 --- /dev/null +++ b/src/ServerConnection.cpp @@ -0,0 +1,43 @@ +#include "ServerConnection.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ClientConnection.h" + +static void error_and_die(const char* message) +{ + perror(message); + exit(1); +} + +ServerConnection::ServerConnection(int port) +{ + sockaddr_in address; + + if ((m_socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + error_and_die("Failed to create socket"); + + bzero(&address, sizeof(address)); + address.sin_family = AF_INET; + address.sin_addr.s_addr = htonl(INADDR_ANY); + address.sin_port = htons(port); + + if ((bind(m_socket_fd, (sockaddr*)&address, sizeof(address))) < 0) + error_and_die("bind"); + + if ((listen(m_socket_fd, 10)) < 0) + error_and_die("listen"); +} + +ClientConnection ServerConnection::accept_client_connection() +{ + int client_socket = accept(m_socket_fd, (sockaddr*)nullptr, nullptr); + return ClientConnection(client_socket); +} diff --git a/src/ServerConnection.h b/src/ServerConnection.h new file mode 100644 index 0000000..0359b5e --- /dev/null +++ b/src/ServerConnection.h @@ -0,0 +1,12 @@ +#pragma once + +class ClientConnection; + +class ServerConnection { +public: + ServerConnection(int port); + + ClientConnection accept_client_connection(); +private: + int m_socket_fd; +}; diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..60c7b4f --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,25 @@ +#include + +#include "ClientConnection.h" +#include "HttpResponse.h" +#include "ServerConnection.h" + +int main(int argc, char** argv) +{ + ServerConnection server(8080); + + std::cout << "cfws v0.1.0]\n"; + + while (true) { + std::cout << "Waiting for connections on port 8080" << std::endl; + ClientConnection client = server.accept_client_connection(); + client.dump_request_data(); + + HttpResponse http_response(ResponseCode::OK); + http_response.add_header("Server: cfws"); + + const char* message = "Welcome to the page."; + client.send(http_response, message); + client.close(); + } +} -- cgit v1.2.3