Commit Diff


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<czstring> 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 <vtl>
+#include <zstring>
+#include <not_null>
 #include <tls.h>
 
 
@@ -23,6 +24,8 @@ bool init();
 /* Create new TLS context for gemini server */
 void create_gemini_server_ctx(not_null<czstring> cert_file, not_null<czstring> 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 T>
+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 <cstddef>
-
-#pragma once
-
-
-namespace vostok
-{
-
-using czstring=const char *;
-
-template <class T>
-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 <unistd.h>
+#include <non_copiable>
+
+#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 <error.h>
 #include <transport.h>
 #include <unistd.h>
+#include <unique_fd>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
+
 namespace vostok
 {
 namespace
 {
 
 
-
 struct command_line_arguments
 {
     not_null<czstring> m_addr{"127.0.0.1"};
@@ -82,17 +86,41 @@ struct command_line_arguments
 };
 
 
-}   // namespace <unnamed>
+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 <unnamed>
 }   // 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;
 }