changeset 667:133353284280

Irccd: some transport cleanups
author David Demelier <markand@malikania.fr>
date Fri, 06 Apr 2018 19:26:13 +0200
parents c99780476eb7
children 8a79b5c0ddc7
files libirccd/irccd/daemon/basic_transport_server.hpp libirccd/irccd/daemon/tls_transport_server.cpp libirccd/irccd/daemon/tls_transport_server.hpp libirccd/irccd/daemon/transport_server.cpp libirccd/irccd/daemon/transport_server.hpp
diffstat 5 files changed, 136 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/libirccd/irccd/daemon/basic_transport_server.hpp	Fri Apr 06 13:44:20 2018 +0200
+++ b/libirccd/irccd/daemon/basic_transport_server.hpp	Fri Apr 06 19:26:13 2018 +0200
@@ -60,7 +60,7 @@
     /**
      * \copydoc transport_server::accept
      */
-    void do_accept(accept_t handler) override;
+    void do_accept(accept_handler handler) override;
 
 public:
     /**
@@ -82,7 +82,7 @@
 }
 
 template <typename Protocol>
-void basic_transport_server<Protocol>::do_accept(accept_t handler)
+void basic_transport_server<Protocol>::do_accept(accept_handler handler)
 {
     auto client = std::make_shared<basic_transport_client<socket_t>>(*this, acceptor_.get_io_service());
 
--- a/libirccd/irccd/daemon/tls_transport_server.cpp	Fri Apr 06 13:44:20 2018 +0200
+++ b/libirccd/irccd/daemon/tls_transport_server.cpp	Fri Apr 06 19:26:13 2018 +0200
@@ -22,7 +22,7 @@
 
 namespace irccd {
 
-void tls_transport_server::do_handshake(std::shared_ptr<client_t> client, accept_t handler)
+void tls_transport_server::do_handshake(std::shared_ptr<client_t> client, accept_handler handler)
 {
     using boost::asio::ssl::stream_base;
 
@@ -37,7 +37,7 @@
 {
 }
 
-void tls_transport_server::do_accept(accept_t handler)
+void tls_transport_server::do_accept(accept_handler handler)
 {
     auto client = std::make_shared<client_t>(*this, acceptor_.get_io_service(), context_);
 
--- a/libirccd/irccd/daemon/tls_transport_server.hpp	Fri Apr 06 13:44:20 2018 +0200
+++ b/libirccd/irccd/daemon/tls_transport_server.hpp	Fri Apr 06 19:26:13 2018 +0200
@@ -44,7 +44,7 @@
 
     context_t context_;
 
-    void do_handshake(std::shared_ptr<client_t>, accept_t);
+    void do_handshake(std::shared_ptr<client_t>, accept_handler);
 
 protected:
     /**
@@ -53,7 +53,7 @@
      * This function does the same as tcp_transport_server::do_accept but it
      * also perform a SSL handshake after a successful accept operation.
      */
-    void do_accept(accept_t handler) override;
+    void do_accept(accept_handler handler) override;
 
 public:
     /**
--- a/libirccd/irccd/daemon/transport_server.cpp	Fri Apr 06 13:44:20 2018 +0200
+++ b/libirccd/irccd/daemon/transport_server.cpp	Fri Apr 06 19:26:13 2018 +0200
@@ -28,7 +28,7 @@
 
 namespace irccd {
 
-void transport_server::do_auth(std::shared_ptr<transport_client> client, accept_t handler)
+void transport_server::do_auth(std::shared_ptr<transport_client> client, accept_handler handler)
 {
     assert(client);
     assert(handler);
@@ -59,7 +59,7 @@
     });
 }
 
-void transport_server::do_greetings(std::shared_ptr<transport_client> client, accept_t handler)
+void transport_server::do_greetings(std::shared_ptr<transport_client> client, accept_handler handler)
 {
     assert(client);
     assert(handler);
@@ -89,7 +89,7 @@
     });
 }
 
-void transport_server::accept(accept_t handler)
+void transport_server::accept(accept_handler handler)
 {
     assert(handler);
 
--- a/libirccd/irccd/daemon/transport_server.hpp	Fri Apr 06 13:44:20 2018 +0200
+++ b/libirccd/irccd/daemon/transport_server.hpp	Fri Apr 06 19:26:13 2018 +0200
@@ -36,27 +36,114 @@
 /**
  * \brief Abstract transport server class.
  *
- * This class create asynchronous operation to accept new clients.
+ * # Synopsis
+ *
+ * The transport_server class is an abstract interface that waits for clients to
+ * connect and store them locally. It does not know the underlying
+ * implementation so derived classes may be implemented in any shape of form.
+ *
+ * As only constraint the implementation must provide an asynchronous operation
+ * to avoid blocking the daemon.
+ *
+ * The derived class only have to implement do_accept function which is only
+ * responsible of getting a client ready for I/O (receiving and sending), the
+ * transport_server does authentication and greeting by itself.
+ *
+ * # Accept procedure
+ *
+ * The connection procedure looks like this:
+ *
+ * ```
+ *            o (transport_server::accept is called)
+ *            |
+ *            v                          [error]
+ *   +-----------------------------+                  +---------------------+
+ *   | asynchronous accept process |----------------->| client is discarded |
+ *   +-----------------------------+                  +---------------------+
+ *            |                                                          ^
+ *            | [success]                                                |
+ *            v                                                          |
+ *   +-----------------------------------------+  [error while sending]  |
+ *   | sending irccd information to the client |------------------------>+
+ *   +-----------------------------------------+                         |
+ *     |              |                                                  |
+ *     |              | [authentication required]                        |
+ *     |              |                                                  |
+ *     |              v                    [error or invalid password]   |
+ *     |      +-------------------------+         +------------+         |
+ *     |      | wait for authentication |-------->| send error |-------->+
+ *     |      +-------------------------+         +------------+         ^
+ *     |              |                                                  |
+ *     |              | [correct password]                               |
+ *     v              v                                                  |
+ *   +---------------------------------------+  [incorrect]              |
+ *   | client is added to the list and ready ]-------------------------- +
+ *   +---------------------------------------+
+ * ```
+ *
+ * # I/O procedures
+ *
+ * Each client has a reference to its parent, since operations are asynchronous,
+ * they maintain their lifetime by themselve to update the parent list on
+ * errors.
+ *
+ * See the following diagram:
+ *
+ * ```
+ *       o (transport_client::recv or send is called) o
+ *       |                                            |
+ *       | [no operations in queue]                   | [operation in progress]
+ *       |                                            v
+ *       |                                    +---------------+
+ *       |                                    | push in queue |
+ *       |                                    +---------------+
+ *       |
+ *       |
+ *       |                                [pending operations in queue]
+ *       |<-----------------------------------------------+
+ *       |                                                ^
+ *       |                                                |
+ *       v                             [success]          |
+ *   +-------------------------------+           +-------------------+
+ *   | asynchronous operation starts |---------->| handler is called |
+ *   +-------------------------------+           +-------------------+
+ *       |
+ *       v [error]
+ *   +--------------------------------------+
+ *   | handler is called with an error code |
+ *   +--------------------------------------+
+ *       |
+ *       v
+ *   +----------------------------------+
+ *   | client delete itself from parent |
+ *   +----------------------------------+
+ * ```
+ *
+ * \see transport_client
+ * \see transport_service
  */
 class transport_server {
-protected:
+public:
     /**
      * Set of clients.
      */
-    using client_set_t = std::unordered_set<std::shared_ptr<transport_client>>;
+    using client_set = std::unordered_set<std::shared_ptr<transport_client>>;
 
     /**
      * Callback when a new client should be accepted.
      */
-    using accept_t = std::function<void (boost::system::error_code, std::shared_ptr<transport_client>)>;
+    using accept_handler = std::function<void (
+        boost::system::error_code,
+        std::shared_ptr<transport_client>
+    )>;
 
 private:
     boost::asio::io_service& service_;
-    client_set_t clients_;
+    client_set clients_;
     std::string password_;
 
-    void do_auth(std::shared_ptr<transport_client>, accept_t);
-    void do_greetings(std::shared_ptr<transport_client>, accept_t);
+    void do_auth(std::shared_ptr<transport_client>, accept_handler);
+    void do_greetings(std::shared_ptr<transport_client>, accept_handler);
 
 protected:
     /**
@@ -66,7 +153,7 @@
      * \pre handler must not be null
      * \param handler the handler function
      */
-    virtual void do_accept(accept_t handler) = 0;
+    virtual void do_accept(accept_handler handler) = 0;
 
 public:
     /**
@@ -83,20 +170,31 @@
     virtual ~transport_server() noexcept = default;
 
     /**
-     * Wrapper that automatically add the new client into the list.
+     * Accept a new client into the transport server.
      *
-     * If handler is not null it is called on error or on successful accept
-     * operation.
+     * Also perform greetings and authentication under the hood. On success, the
+     * client is added into the server and is ready to use.
      *
+     * \pre accept != nullptr
      * \param handler the handler
      */
-    void accept(accept_t handler);
+    void accept(accept_handler handler);
 
+    /**
+     * Get the io service.
+     *
+     * \return the service
+     */
     inline const boost::asio::io_service& get_service() const noexcept
     {
         return service_;
     }
 
+    /**
+     * Overloaded function.
+     *
+     * \return the service
+     */
     inline boost::asio::io_service& get_service() noexcept
     {
         return service_;
@@ -107,7 +205,7 @@
      *
      * \return the clients
      */
-    inline const client_set_t& get_clients() const noexcept
+    inline const client_set& get_clients() const noexcept
     {
         return clients_;
     }
@@ -117,7 +215,7 @@
      *
      * \return the clients
      */
-    inline client_set_t& get_clients() noexcept
+    inline client_set& get_clients() noexcept
     {
         return clients_;
     }
@@ -143,9 +241,18 @@
     }
 };
 
+/**
+ * \brief Transport error.
+ */
 class transport_error : public boost::system::system_error {
 public:
+    /**
+     * \brief Transport related errors.
+     */
     enum error {
+        //!< No error.
+        no_error = 0,
+
         //!< Authentication is required.
         auth_required,
 
@@ -180,7 +287,12 @@
         not_supported
     };
 
-    transport_error(error err) noexcept;
+    /**
+     * Constructor.
+     *
+     * \param code the error code
+     */
+    transport_error(error code) noexcept;
 };
 
 /**