# HG changeset patch # User David Demelier # Date 1511268039 -3600 # Node ID 7051034bf2ee1ad2fbe0db20e5c1d72b1d34a5a6 # Parent 80c3caafe9d33ce1b8401038aa22d96fdb455316 Irccdctl: abort in case of error diff -r 80c3caafe9d3 -r 7051034bf2ee irccdctl/cli.cpp --- 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(message["error"].template get())); + if (message["error"].is_string()) + throw std::runtime_error(message["error"].template get()); + auto c = json_util::to_string(message["command"]); if (c != req["command"].get()) { @@ -44,11 +49,6 @@ return; } - if (message["error"].is_number_integer()) - throw boost::system::system_error(static_cast(message["error"].template get())); - if (message["error"].is_string()) - throw std::runtime_error(message["error"].template get()); - if (handler) handler(std::move(message)); }); diff -r 80c3caafe9d3 -r 7051034bf2ee libcommon/irccd/network_errc.cpp --- 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"; } diff -r 80c3caafe9d3 -r 7051034bf2ee libcommon/irccd/network_errc.hpp --- 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 }; /** diff -r 80c3caafe9d3 -r 7051034bf2ee libirccd/irccd/transport_client.hpp --- 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(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(reason) }}, std::move(handler)); + } }; /** diff -r 80c3caafe9d3 -r 7051034bf2ee libirccd/irccd/transport_server.cpp --- 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 +#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() != password_) { - handler(nullptr, network_errc::invalid_auth); - return false; - } - - return true; -} - void transport_server::do_auth(std::shared_ptr 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); }); } diff -r 80c3caafe9d3 -r 7051034bf2ee libirccd/irccd/transport_server.hpp --- 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, accept_t); void do_greetings(std::shared_ptr, accept_t); diff -r 80c3caafe9d3 -r 7051034bf2ee libirccdctl/irccd/ctl/network_connection.hpp --- 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)); }); }