commit 230a46c6267df18bb9b48a66399e9db3b3ece434 from: Aleksey Ryndin date: Wed Aug 09 11:38:13 2023 UTC Add socket server loop (initial code) commit - 5b8701be75c5767827e3c7e500de5980f55deb3c commit + 230a46c6267df18bb9b48a66399e9db3b3ece434 blob - bac6ee8a28ac35fd3ae1bfb912fa65b04e0e7d4d blob + ef50e08bc2f5a86b92048b4cb1f110df6803ff2c --- shared/transport.cc +++ shared/transport.cc @@ -81,5 +81,18 @@ void create_gemini_server_ctx(not_null cert_ ctx.swap(ret_ctx); } + +void accept(struct tls *server_ctx, int client_socket, context_t &ret_ctx) +{ + struct tls *client_ctx = nullptr; + if (tls_accept_socket(server_ctx, &client_ctx, client_socket) == -1) + { + error::occurred("TLS accept", error::no_error_code); + ret_ctx.reset(); + return; + } + ret_ctx.reset(client_ctx); +} + } // namespace transport } // namespace vostok blob - /dev/null blob + 91f18102c1d60cd52c7e585c92c8329e80f99ca7 (mode 644) --- /dev/null +++ shared/non_copiable @@ -0,0 +1,17 @@ +/** Non-copiable objects */ + + +#pragma once + + +namespace vostok +{ + +struct non_copiable +{ + non_copiable() = default; + non_copiable(const non_copiable &) = delete; + non_copiable &operator =(const non_copiable &) = delete; +}; + +} // namespace vostok blob - 758da8456ae8a8edca0ae2926b70bc3bf7dd34a2 blob + 674b353f1e4433e3260fd17613a369a41a292999 --- shared/transport.h +++ shared/transport.h @@ -1,6 +1,7 @@ /** Wrap libtls for gemini protocol */ -#include +#include +#include #include @@ -23,6 +24,8 @@ bool init(); /* Create new TLS context for gemini server */ void create_gemini_server_ctx(not_null cert_file, not_null key_file, context_t &ctx); +/** Accept new client */ +void accept(struct tls *server_ctx, int client_socket, context_t &ctx); } // namespace transport } // namespace vostok blob - /dev/null blob + 61c3190a7d73098284fab48113e2ea55ec0fa3ff (mode 644) --- /dev/null +++ shared/not_null @@ -0,0 +1,39 @@ +/** Restricts a pointer or smart pointer to only hold non-null values. */ + + +#pragma once + + +namespace vostok +{ + +template +class not_null +{ +public: + not_null(T p) :m_p{p} {} + + T get() const {return m_p;} + operator T() const {return m_p;} + T operator->() const {return m_p;} + + + // prevents compilation when someone attempts to assign a null pointer constant + not_null(std::nullptr_t) = delete; + not_null& operator=(std::nullptr_t) = delete; + + // unwanted operators...pointers only point to single objects! + not_null& operator++() = delete; + not_null& operator--() = delete; + not_null operator++(int) = delete; + not_null operator--(int) = delete; + not_null& operator+=(std::ptrdiff_t) = delete; + not_null& operator-=(std::ptrdiff_t) = delete; + void operator[](std::ptrdiff_t) const = delete; + +private: + T m_p; +}; + + +} // namespace vostok blob - 98c2467b729567bd41fd41dc587ce957a843551f (mode 644) blob + /dev/null --- shared/vtl +++ /dev/null @@ -1,42 +0,0 @@ -/** vostok template library */ - -#include - -#pragma once - - -namespace vostok -{ - -using czstring=const char *; - -template -class not_null -{ -public: - not_null(T p) :m_p{p} {} - - T get() const {return m_p;} - operator T() const {return m_p;} - T operator->() const {return m_p;} - - - // prevents compilation when someone attempts to assign a null pointer constant - not_null(std::nullptr_t) = delete; - not_null& operator=(std::nullptr_t) = delete; - - // unwanted operators...pointers only point to single objects! - not_null& operator++() = delete; - not_null& operator--() = delete; - not_null operator++(int) = delete; - not_null operator--(int) = delete; - not_null& operator+=(std::ptrdiff_t) = delete; - not_null& operator-=(std::ptrdiff_t) = delete; - void operator[](std::ptrdiff_t) const = delete; - -private: - T m_p; -}; - - -} // namespace vostok blob - /dev/null blob + e791df4a9bb41ae6998d77d98b0702074eda9ecc (mode 644) --- /dev/null +++ shared/unique_fd @@ -0,0 +1,40 @@ +/** Smart pointer for file descriptor */ + +#include +#include + +#pragma once + + +namespace vostok +{ + + +class unique_fd : non_copiable +{ +public: + explicit unique_fd(int fd = -1) : m_fd(fd) {} + ~unique_fd(){ reset();} + + operator bool() const {return m_fd != -1;} + + int get() const { return m_fd; } + void reset(int fd = -1) + { + if (*this) + close(m_fd); + m_fd = fd; + } + int release() + { + const auto fd = m_fd; + m_fd = -1; + return fd; + } + +private: + int m_fd; +}; + + +} // namespace vostok blob - /dev/null blob + 72f350aae70828f2d30d40217c557c58f297dba5 (mode 644) --- /dev/null +++ shared/zstring @@ -0,0 +1,14 @@ +/** C-style (null-terminated) string */ + + +#pragma once + + +namespace vostok +{ + + +using czstring=const char *; + + +} // namespace vostok blob - 61c6711f170126093bf8a2860933d30de8897990 blob + 7455e658ed0f78bb460d284f6809c819fde5b551 --- vostokd/Makefile +++ vostokd/Makefile @@ -3,7 +3,11 @@ CXXFLAGS += -I${.CURDIR}/../shared CXXFLAGS += -ltls CXXFILES = vostokd.cc -HXXFILES = ${.PATH}../shared/vtl +HXXFILES = ${.PATH}../shared/not_null +HXXFILES += ${.PATH}../shared/zstring +HXXFILES += ${.PATH}../shared/unique_fd +HXXFILES += ${.PATH}../shared/non_copiable +HXXFILES += ${.PATH}../shared/unique_fd CXXFILES += ${.PATH}../shared/transport.cc HXXFILES += ${.PATH}../shared/transport.h CXXFILES += ${.PATH}../shared/error.cc blob - cc83600a34f1662f5336c556196b1a8667c481a7 blob + 33d9148d832623c639854216d5b805f0452db1e2 --- vostokd/vostokd.cc +++ vostokd/vostokd.cc @@ -3,14 +3,18 @@ #include #include #include +#include +#include +#include +#include + namespace vostok { namespace { - struct command_line_arguments { not_null m_addr{"127.0.0.1"}; @@ -82,17 +86,41 @@ struct command_line_arguments }; -} // namespace +bool server_loop(int server_socket, struct tls *ctx) +{ + error::g_log << "Enter to server loop..." << std::endl; + for (; ; ) + { + if (listen(server_socket, 1024) == -1) + { + error::occurred("Listen socket", error::print{}); + return false; + } + struct sockaddr_in addr{}; + socklen_t addrlen = sizeof(addr); + unique_fd client_socket{accept(server_socket, (struct sockaddr *)&addr, &addrlen)}; + if (!client_socket) + { + error::occurred("Accept socket", error::print{}); + return false; + } + + transport::context_t client_ctx{nullptr, tls_free}; + transport::accept(ctx, client_socket.get(), client_ctx); + if (!client_ctx) + return false; + + error::g_log << inet_ntoa(addr.sin_addr) << " accepted" << std::endl; + } + return true; +} + + /** C++ entry point */ -bool -main(int argc, char *argv[]) +bool main(const command_line_arguments &args) { - command_line_arguments args; - if (!args.parse_command_line(argc, argv)) - return false; - if (!transport::init()) return false; @@ -101,10 +129,32 @@ main(int argc, char *argv[]) if (!ctx) return false; - return true; + const unique_fd server_socket{socket(AF_INET, SOCK_STREAM, 0)}; + if (!server_socket) + { + error::occurred("Create socket", error::print{}); + return false; + } + + struct sockaddr_in sockaddr{}; + sockaddr.sin_family = AF_INET; + sockaddr.sin_addr.s_addr = inet_addr(args.m_addr); + sockaddr.sin_port = htons(args.m_port); + + if (bind(server_socket.get(), (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == -1) + { + error::occurred( + [=](){error::g_log << "Bind to " << args.m_addr << ":" << std::dec << args.m_port;}, + error::print{} + ); + return false; + } + + return server_loop(server_socket.get(), ctx.get()); } +} // namespace } // namespace vostok @@ -112,5 +162,9 @@ extern "C" int main(int argc, char *argv[]) { - return vostok::main(argc, argv) ? 0 : 1; + vostok::command_line_arguments args; + if (!args.parse_command_line(argc, argv)) + return 1; + + return vostok::main(args) ? 0 : 1; }