From a38639b2293f9e74dbd61407cf862366039fed9c Mon Sep 17 00:00:00 2001
From: Benny Baumann <BenBE@geshi.org>
Date: Fri, 1 Jan 2021 17:25:41 +0100
Subject: [PATCH] Basic work on async socket interface

---
 src/net/async_fd.hpp     | 85 ++++++++++++++++++++++++++++++++++++++++
 src/net/async_server.hpp | 40 +++++++++++++++++++
 2 files changed, 125 insertions(+)
 create mode 100644 src/net/async_fd.hpp
 create mode 100644 src/net/async_server.hpp

diff --git a/src/net/async_fd.hpp b/src/net/async_fd.hpp
new file mode 100644
index 0000000..72a42d7
--- /dev/null
+++ b/src/net/async_fd.hpp
@@ -0,0 +1,85 @@
+#pragma once
+
+#include <unistd.h>
+
+namespace rmrf::net {
+
+    class null_fd
+    {
+    public:
+        constexpr explicit null_fd() {}
+        constexpr explicit null_fd(int) {}
+        constexpr operator int() const { return -1; }
+    };
+
+    constexpr null_fd nullfd{};
+
+    class auto_fd
+    {
+    private:
+        int _fd;
+
+    public:
+        inline auto_fd(null_fd nfd = nullfd) noexcept : _fd{nfd} {}
+
+        explicit inline auto_fd(int fd) noexcept : _fd{fd} {}
+
+        inline auto_fd(auto_fd &&fd) noexcept : _fd{fd.release()} {}
+        inline auto_fd &operator=(auto_fd &&fd) noexcept {
+            reset(fd.release());
+            return *this;
+        }
+
+        auto_fd(const auto_fd &) = delete;
+        auto_fd &operator=(const auto_fd &) = delete;
+
+        inline ~auto_fd() noexcept {
+            reset();
+        }
+
+        inline int get() const noexcept { return _fd; }
+
+        int release() noexcept
+        {
+            int r(_fd);
+            _fd = -1;
+            return r;
+        }
+
+        // Close an open file descriptor. Reset the descriptor to -1.
+        inline void close() noexcept {
+            if (_fd >= 0)
+            {
+                ::close(_fd);
+
+                // If fdclose() failed then no reason to expect it to succeed the next time.
+                _fd = -1;
+            }
+        }
+
+        inline void reset(int fd = -1) noexcept {
+            if (_fd >= 0)
+                close(); // Don't check for an error as not much we can do here.
+
+            _fd = fd;
+        }
+
+    };
+
+    inline bool operator==(const auto_fd &x, const auto_fd &y) {
+        return x.get() == y.get();
+    }
+
+    inline bool operator!=(const auto_fd &x, const auto_fd &y) {
+        return !(x == y);
+    }
+
+    inline bool operator==(const auto_fd &x, null_fd) {
+        return x.get() == -1;
+    }
+
+    inline bool operator!=(const auto_fd &x, null_fd y) {
+        return !(x == y);
+    }
+
+}
diff --git a/src/net/async_server.hpp b/src/net/async_server.hpp
new file mode 100644
index 0000000..f192884
--- /dev/null
+++ b/src/net/async_server.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <functional>
+#include <memory>
+
+#include <net/async_fd.hpp>
+
+namespace rmrf::net::asio {
+
+class async_server_socket : public std::enable_shared_from_this<async_server_socket> {
+public:
+    typedef std::shared_ptr<async_server_socket> self_ptr_type;
+
+    typedef std::function<void(self_ptr_type&, const auto_fd &)> accept_handler_type;
+    typedef std::function<void(self_ptr_type&)> error_handler_type;
+
+private:
+    auto_fd socket;
+
+    accept_handler_type on_accept;
+    error_handler_type on_error;
+
+public:
+    async_server_socket(auto_fd&& fd) : socket(std::forward(fd)) {
+        // Add this socket to libev ...
+    }
+    ~async_server_socket() {
+        // Remove this socket from libev ...
+    }
+
+public:
+    accept_handler_type get_accept_handler() const {
+        return on_accept;
+    }
+    void set_accept_handler(const accept_handler_type& value) {
+        on_accept = value;
+    }
+};
+
+}
-- 
GitLab