Mercurial > irccd
view libirccd/irccd/daemon/transport_client.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 | 8c44bbcbbab9 |
children |
line wrap: on
line source
/* * transport_client.cpp -- server side transport clients * * 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 "transport_client.hpp" #include "transport_server.hpp" namespace irccd { void transport_client::flush() { if (queue_.empty()) return; const auto self = shared_from_this(); stream_->send(queue_.front().first, [this, self] (auto code) { if (queue_.front().second) queue_.front().second(code); queue_.pop_front(); if (code) erase(); else flush(); }); } void transport_client::erase() { state_ = state::closing; if (auto parent = parent_.lock()) parent->get_clients().erase(shared_from_this()); } transport_client::transport_client(std::weak_ptr<transport_server> server, std::shared_ptr<stream> stream) noexcept : parent_(server) , stream_(std::move(stream)) { assert(stream_); } auto transport_client::get_state() const noexcept -> state { return state_; } void transport_client::set_state(state state) noexcept { state_ = state; } void transport_client::read(stream::recv_handler handler) { assert(handler); if (state_ != state::closing) { const auto self = shared_from_this(); stream_->recv([this, self, handler] (auto code, auto msg) { handler(code, msg); if (code) erase(); }); } } void transport_client::write(nlohmann::json json, stream::send_handler handler) { const auto in_progress = queue_.size() > 0; queue_.emplace_back(std::move(json), std::move(handler)); if (!in_progress) flush(); } void transport_client::success(const std::string& cname, stream::send_handler handler) { assert(!cname.empty()); write({{ "command", cname }}, std::move(handler)); } void transport_client::error(std::error_code code, stream::send_handler handler) { error(std::move(code), "", std::move(handler)); } void transport_client::error(std::error_code code, std::string_view cname, stream::send_handler handler) { assert(code); auto json = nlohmann::json::object({ { "error", code.value() }, { "errorCategory", code.category().name() }, { "errorMessage", code.message() } }); // TODO: check newer version of JSON for string_view support. if (!cname.empty()) json["command"] = std::string(cname); const auto self = shared_from_this(); write(std::move(json), [this, handler, self] (auto code) { erase(); if (handler) handler(code); }); state_ = state::closing; } } // !irccd