From d872c2b49214c0a4db40a9e2d860802d9eedc563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 15 Nov 2016 00:23:19 +0100 Subject: Support the ident protocol fix #3211 --- src/bridge/bridge.cpp | 5 +++ src/bridge/bridge.hpp | 1 + src/identd/identd_server.hpp | 38 +++++++++++++++++++++++ src/identd/identd_socket.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++ src/identd/identd_socket.hpp | 44 +++++++++++++++++++++++++++ src/main.cpp | 43 ++++++++++++++++---------- src/xmpp/biboumi_component.cpp | 1 - 7 files changed, 184 insertions(+), 17 deletions(-) create mode 100644 src/identd/identd_server.hpp create mode 100644 src/identd/identd_socket.cpp create mode 100644 src/identd/identd_socket.hpp (limited to 'src') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index a0ecc6e..6fb03bd 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -1033,6 +1033,11 @@ std::unordered_map>& Bridge::get_irc_cli return this->irc_clients; } +const std::unordered_map>& Bridge::get_irc_clients() const +{ + return this->irc_clients; +} + std::set Bridge::get_chantypes(const std::string& hostname) const { IrcClient* irc = this->find_irc_client(hostname); diff --git a/src/bridge/bridge.hpp b/src/bridge/bridge.hpp index 18ebfeb..8f2dcef 100644 --- a/src/bridge/bridge.hpp +++ b/src/bridge/bridge.hpp @@ -231,6 +231,7 @@ public: */ void trigger_on_irc_message(const std::string& irc_hostname, const IrcMessage& message); std::unordered_map>& get_irc_clients(); + const std::unordered_map>& get_irc_clients() const; std::set get_chantypes(const std::string& hostname) const; #ifdef USE_DATABASE void set_record_history(const bool val); diff --git a/src/identd/identd_server.hpp b/src/identd/identd_server.hpp new file mode 100644 index 0000000..4270749 --- /dev/null +++ b/src/identd/identd_server.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +class BiboumiComponent; + +class IdentdServer: public TcpSocketServer +{ + public: + IdentdServer(const BiboumiComponent& biboumi_component, std::shared_ptr poller, const uint16_t port): + TcpSocketServer(poller, port), + biboumi_component(biboumi_component) + {} + + const BiboumiComponent& get_biboumi_component() const + { + return this->biboumi_component; + } + void shutdown() + { + if (this->poller->is_managing_socket(this->socket)) + this->poller->remove_socket_handler(this->socket); + ::close(this->socket); + } + void clean() + { + this->sockets.erase(std::remove_if(this->sockets.begin(), this->sockets.end(), + [](const std::unique_ptr& socket) + { + return socket->get_socket() == -1; + }), + this->sockets.end()); + } + private: + const BiboumiComponent& biboumi_component; +}; diff --git a/src/identd/identd_socket.cpp b/src/identd/identd_socket.cpp new file mode 100644 index 0000000..c1ad55e --- /dev/null +++ b/src/identd/identd_socket.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include + +#include + +#include + +IdentdSocket::IdentdSocket(std::shared_ptr poller, const socket_t socket, TcpSocketServer& server): + TCPSocketHandler(poller), + server(dynamic_cast(server)) +{ + this->socket = socket; +} + +void IdentdSocket::parse_in_buffer(const std::size_t) +{ + while (true) + { + const auto line_end = this->in_buf.find('\n'); + if (line_end == std::string::npos) + break; + std::istringstream line(this->in_buf.substr(0, line_end)); + this->consume_in_buffer(line_end + 1); + + uint16_t local_port; + uint16_t remote_port; + char sep; + line >> local_port >> sep >> remote_port; + const auto& xmpp = this->server.get_biboumi_component(); + auto response = this->generate_answer(xmpp, local_port, remote_port); + + this->send_data(std::move(response)); + } +} + +static std::string hash_jid(const std::string& jid) +{ + sha1nfo sha1; + sha1_init(&sha1); + sha1_write(&sha1, jid.data(), jid.size()); + const uint8_t* res = sha1_result(&sha1); + std::ostringstream result; + for (int i = 0; i < HASH_LENGTH; i++) + result << std::hex << std::setfill('0') << std::setw(2) << static_cast(res[i]); + return result.str(); +} + +std::string IdentdSocket::generate_answer(const BiboumiComponent& biboumi, uint16_t local, uint16_t remote) +{ + for (const Bridge* bridge: biboumi.get_bridges()) + { + for (const auto& pair: bridge->get_irc_clients()) + { + if (pair.second->match_port_pairt(local, remote)) + { + std::ostringstream os; + os << local << " , " << remote << " : USERID : OTHER : " << hash_jid(bridge->get_bare_jid()); + log_debug("Identd, sending: ", os.str()); + return os.str(); + } + } + } + std::ostringstream os; + os << local << " , " << remote << " ERROR : NO-USER"; + log_debug("Identd, sending: ", os.str()); + return os.str(); +} diff --git a/src/identd/identd_socket.hpp b/src/identd/identd_socket.hpp new file mode 100644 index 0000000..6d6cc1d --- /dev/null +++ b/src/identd/identd_socket.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include + +#include +#include + +#include +#include + +class XmppComponent; +class IdentdSocket; +class IdentdServer; +template +class TcpSocketServer; + +class IdentdSocket: public TCPSocketHandler +{ + public: + IdentdSocket(std::shared_ptr poller, const socket_t socket, TcpSocketServer& server); + ~IdentdSocket() = default; + std::string generate_answer(const BiboumiComponent& biboumi, uint16_t local, uint16_t remote); + + void parse_in_buffer(const std::size_t size) override final; + void on_connection_close(const std::string& message) override final + {} + + bool is_connected() const override final + { + return true; + } + bool is_connecting() const override final + { + return false; + } + + private: + void connect() override + { assert(false); } + void on_connection_failed(const std::string&) override final + { assert(false); } + + IdentdServer& server; +}; diff --git a/src/main.cpp b/src/main.cpp index 019dff0..072345f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,8 @@ #include #include +#include + // A flag set by the SIGINT signal handler. static std::atomic stop(false); // Flag set by the SIGUSR1/2 signal handler. @@ -121,10 +123,13 @@ int main(int ac, char** av) sigaction(SIGUSR2, &on_sigusr, nullptr); auto p = std::make_shared(); + auto xmpp_component = std::make_shared(p, hostname, password); xmpp_component->start(); + IdentdServer identd(*xmpp_component, p, static_cast(Config::get_int("identd_port", 113))); + #ifdef CARES_FOUND DNSHandler::instance.watch_dns_sockets(p); #endif @@ -135,6 +140,7 @@ int main(int ac, char** av) // Check for empty irc_clients (not connected, or with no joined // channel) and remove them xmpp_component->clean(); + identd.clean(); if (stop) { log_info("Signal received, exiting..."); @@ -144,6 +150,7 @@ int main(int ac, char** av) exiting = true; stop.store(false); xmpp_component->shutdown(); + identd.shutdown(); // Cancel the timer for a potential reconnection TimedEventsManager::instance().cancel("XMPP reconnection"); } @@ -157,26 +164,30 @@ int main(int ac, char** av) // happened because we sent something invalid to it and it decided to // close the connection. This is a bug that should be fixed, but we // still reconnect automatically instead of dropping everything - if (!exiting && xmpp_component->ever_auth && + if (!exiting && !xmpp_component->is_connected() && !xmpp_component->is_connecting()) { - if (xmpp_component->first_connection_try == true) - { // immediately re-try to connect - xmpp_component->reset(); - xmpp_component->start(); - } - else - { // Re-connecting failed, we now try only each few seconds - auto reconnect_later = [xmpp_component]() + if (xmpp_component->ever_auth) { - xmpp_component->reset(); - xmpp_component->start(); - }; - TimedEvent event(std::chrono::steady_clock::now() + 2s, - reconnect_later, "XMPP reconnection"); - TimedEventsManager::instance().add_event(std::move(event)); - } + if (xmpp_component->first_connection_try == true) + { // immediately re-try to connect + xmpp_component->reset(); + xmpp_component->start(); + } + else + { // Re-connecting failed, we now try only each few seconds + auto reconnect_later = [xmpp_component]() + { + xmpp_component->reset(); + xmpp_component->start(); + }; + TimedEvent event(std::chrono::steady_clock::now() + 2s, reconnect_later, "XMPP reconnection"); + TimedEventsManager::instance().add_event(std::move(event)); + } + } + else + identd.shutdown(); } // If the only existing connection is the one to the XMPP component: // close the XMPP stream. diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index d6782e2..ca24f3a 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3