Mercurial > irccd
view libirccd-ctl/irccd/ctl/controller.cpp @ 780:560b62f6b0a7
Core: rework socket layer, closes #939 @6h
Rework the ip_connector and ip_acceptor to be more easy to use. Also,
ip_connector will now use a resolver to find appropriate endpoints.
Bring back full support for IPv6/IPv4 with all possible combinations.
The tls_stream class now owns a shared ssl::context that is copied from the
acceptor or the connector. The tls_connector and tls_acceptor wraps basic ones
for convenience and simplicity.
Irccd and irccdctl now support local SSL sockets.
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 04 Nov 2018 17:26:05 +0100 |
parents | dc9af75c609c |
children | f26bb089232d |
line wrap: on
line source
/* * controller.cpp -- main irccdctl interface * * Copyright (c) 2013-2018 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <cassert> #include <irccd/sysconfig.hpp> #include <irccd/json_util.hpp> #include <irccd/daemon/irccd.hpp> #include <irccd/daemon/server.hpp> #include <irccd/daemon/plugin.hpp> #include <irccd/daemon/rule.hpp> #include "controller.hpp" using irccd::json_util::deserializer; namespace irccd::ctl { void controller::authenticate(connect_handler handler, nlohmann::json info) { const auto cmd = nlohmann::json::object({ { "command", "auth" }, { "password", password_ } }); write(cmd, [handler, info, this] (auto code) { if (code) { handler(std::move(code), nullptr); return; } read([handler, info] (auto code, auto) { handler(std::move(code), std::move(info)); }); }); } void controller::verify(connect_handler handler) { read([handler, this] (auto code, auto message) { if (code) { handler(std::move(code), std::move(message)); return; } const deserializer doc(message); const auto program = doc.get<std::string>("program"); const auto major = doc.get<int>("major"); if (!program && *program != "irccd") handler(irccd_error::not_irccd, std::move(message)); else if (major && *major != IRCCD_VERSION_MAJOR) handler(irccd_error::incompatible_version, std::move(message)); else { if (!password_.empty()) authenticate(std::move(handler), message); else handler(code, std::move(message)); } }); } controller::controller(std::unique_ptr<connector> connector) noexcept : connector_(std::move(connector)) { assert(connector_); } auto controller::get_password() const noexcept -> const std::string& { return password_; } void controller::set_password(std::string password) noexcept { password_ = std::move(password); } void controller::connect(connect_handler handler) { assert(handler); connector_->connect([handler, this] (auto code, auto stream) { if (code) handler(std::move(code), nullptr); else { stream_ = std::move(stream); verify(std::move(handler)); } }); } void controller::read(stream::recv_handler handler) { assert(handler); assert(stream_); auto stream = stream_; stream_->recv([this, handler, stream] (auto code, auto msg) { if (code) { stream_ = nullptr; handler(std::move(code), std::move(msg)); return; } const deserializer doc(msg); const auto e = doc.get<int>("error"); const auto c = doc.get<std::string>("errorCategory"); if (e && c) { if (*c == "irccd") code = make_error_code(static_cast<irccd_error::error>(*e)); else if (*c == "server") code = make_error_code(static_cast<server_error::error>(*e)); else if (*c == "plugin") code = make_error_code(static_cast<plugin_error::error>(*e)); else if (*c == "rule") code = make_error_code(static_cast<rule_error::error>(*e)); } handler(std::move(code), std::move(msg)); }); } void controller::write(nlohmann::json message, stream::send_handler handler) { assert(message.is_object()); assert(stream_); auto stream = stream_; stream_->send(std::move(message), [this, stream, handler] (auto code) { if (code) stream_ = nullptr; if (handler) handler(std::move(code)); }); } } // !irccd::ctl