changeset 543:7051034bf2ee

Irccdctl: abort in case of error
author David Demelier <markand@malikania.fr>
date Tue, 21 Nov 2017 13:40:39 +0100
parents 80c3caafe9d3
children 8d9662b2beee
files irccdctl/cli.cpp libcommon/irccd/network_errc.cpp libcommon/irccd/network_errc.hpp libirccd/irccd/transport_client.hpp libirccd/irccd/transport_server.cpp libirccd/irccd/transport_server.hpp libirccdctl/irccd/ctl/network_connection.hpp
diffstat 7 files changed, 68 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/irccdctl/cli.cpp	Tue Nov 21 12:29:50 2017 +0100
+++ b/irccdctl/cli.cpp	Tue Nov 21 13:40:39 2017 +0100
@@ -37,6 +37,11 @@
         if (code)
             throw boost::system::system_error(code);
 
+        if (message["error"].is_number_integer())
+            throw boost::system::system_error(static_cast<network_errc>(message["error"].template get<int>()));
+        if (message["error"].is_string())
+            throw std::runtime_error(message["error"].template get<std::string>());
+
         auto c = json_util::to_string(message["command"]);
 
         if (c != req["command"].get<std::string>()) {
@@ -44,11 +49,6 @@
             return;
         }
 
-        if (message["error"].is_number_integer())
-            throw boost::system::system_error(static_cast<network_errc>(message["error"].template get<int>()));
-        if (message["error"].is_string())
-            throw std::runtime_error(message["error"].template get<std::string>());
-
         if (handler)
             handler(std::move(message));
     });
--- a/libcommon/irccd/network_errc.cpp	Tue Nov 21 12:29:50 2017 +0100
+++ b/libcommon/irccd/network_errc.cpp	Tue Nov 21 13:40:39 2017 +0100
@@ -44,6 +44,8 @@
                 return "invalid message";
             case network_errc::corrupt_message:
                 return "corrupt message";
+            case network_errc::auth_required:
+                return "auth required";
             default:
                 return "unknown error";
             }
--- a/libcommon/irccd/network_errc.hpp	Tue Nov 21 12:29:50 2017 +0100
+++ b/libcommon/irccd/network_errc.hpp	Tue Nov 21 13:40:39 2017 +0100
@@ -40,6 +40,7 @@
     invalid_auth,           //!< invalid credentials in auth command
     invalid_message,        //!< the message was not JSON
     corrupt_message,        //!< error occured while sending a message
+    auth_required           //!< authentication is required and was not issued
 };
 
 /**
--- a/libirccd/irccd/transport_client.hpp	Tue Nov 21 12:29:50 2017 +0100
+++ b/libirccd/irccd/transport_client.hpp	Tue Nov 21 13:40:39 2017 +0100
@@ -230,12 +230,14 @@
      * Convenient error overload.
      *
      * \param cname the command name
+     * \pre !reason.empty()
      * \param reason the reason string
      * \param handler the optional handler
      */
     inline void error(const std::string& cname, const std::string& reason, send_t handler = nullptr)
     {
         assert(!cname.empty());
+        assert(!reason.empty());
 
         error({
             { "command",    cname   },
@@ -246,11 +248,25 @@
     /**
      * Convenient error overload.
      *
+     * \pre !reason.empty()
+     * \param reason the reason string
+     * \param handler the handler
+     */
+    inline void error(const std::string& reason, send_t handler = nullptr)
+    {
+        assert(!reason.empty());
+
+        error({{ "error", reason }}, std::move(handler));
+    }
+
+    /**
+     * Convenient error overload.
+     *
      * \param cname the command name
      * \param reason the error code
      * \param handler the optional handler
      */
-    inline void error(const std::string& cname, network_errc reason, send_t handler)
+    inline void error(const std::string& cname, network_errc reason, send_t handler = nullptr)
     {
         assert(!cname.empty());
 
@@ -259,6 +275,20 @@
             { "error",      static_cast<int>(reason)    }
         }, std::move(handler));
     }
+
+    /**
+     * Convenient error overload.
+     *
+     * \pre reason != network_errc::no_error
+     * \param reason the reason string
+     * \param handler the handler
+     */
+    inline void error(network_errc reason, send_t handler = nullptr)
+    {
+        assert(reason != network_errc::no_error);
+
+        error({{ "error", static_cast<int>(reason) }}, std::move(handler));
+    }
 };
 
 /**
--- a/libirccd/irccd/transport_server.cpp	Tue Nov 21 12:29:50 2017 +0100
+++ b/libirccd/irccd/transport_server.cpp	Tue Nov 21 13:40:39 2017 +0100
@@ -20,30 +20,11 @@
 
 #include <cassert>
 
+#include "json_util.hpp"
 #include "transport_server.hpp"
 
 namespace irccd {
 
-bool transport_server::do_auth_check(nlohmann::json message, accept_t handler)
-{
-    assert(handler);
-
-    auto command = message["command"];
-    auto password = message["password"];
-
-    if (!command.is_string() || !password.is_string()) {
-        handler(nullptr, network_errc::invalid_message);
-        return false;
-    }
-
-    if (command != "auth" || password.get<std::string>() != password_) {
-        handler(nullptr, network_errc::invalid_auth);
-        return false;
-    }
-
-    return true;
-}
-
 void transport_server::do_auth(std::shared_ptr<transport_client> client, accept_t handler)
 {
     assert(client);
@@ -52,11 +33,24 @@
     client->recv([this, client, handler] (auto message, auto code) {
         if (code)
             handler(client, code);
-        if (do_auth_check(message, handler)) {
-            clients_.insert(client);
+
+        clients_.insert(client);
+
+        auto command = json_util::to_string(message["command"]);
+        auto password = json_util::to_string(message["password"]);
+
+        if (command != "auth") {
+            client->error(network_errc::auth_required);
+            code = network_errc::auth_required;
+        } else if (password != password_) {
+            client->error(network_errc::invalid_auth);
+            code = network_errc::invalid_auth;
+        } else {
             client->set_state(transport_client::state_t::ready);
-            handler(client, code);
+            code = network_errc::no_error;
         }
+
+        handler(client, code);
     });
 }
 
--- a/libirccd/irccd/transport_server.hpp	Tue Nov 21 12:29:50 2017 +0100
+++ b/libirccd/irccd/transport_server.hpp	Tue Nov 21 13:40:39 2017 +0100
@@ -58,7 +58,6 @@
     client_set_t clients_;
     std::string password_;
 
-    bool do_auth_check(nlohmann::json, accept_t);
     void do_auth(std::shared_ptr<transport_client>, accept_t);
     void do_greetings(std::shared_ptr<transport_client>, accept_t);
 
--- a/libirccdctl/irccd/ctl/network_connection.hpp	Tue Nov 21 12:29:50 2017 +0100
+++ b/libirccdctl/irccd/ctl/network_connection.hpp	Tue Nov 21 13:40:39 2017 +0100
@@ -94,11 +94,22 @@
 
         input_.consume(xfer);
 
+        /*
+         * Only catch parse error from JSON to avoid calling the handler twice
+         * if the handler throws from itself.
+         *
+         * TODO: in json 3.0.0, you may catch nlohmann::json::parse_error
+         * instead.
+         */
+        nlohmann::json json;
+
         try {
-            handler(code, nlohmann::json::parse(command));
+            json = nlohmann::json::parse(command);
         } catch (...) {
             handler(network_errc::invalid_message, nullptr);
         }
+
+        handler(network_errc::no_error, std::move(json));
     });
 }