diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bridge/bridge.cpp | 22 | ||||
-rw-r--r-- | src/bridge/bridge.hpp | 2 | ||||
-rw-r--r-- | src/identd/identd_server.hpp | 1 | ||||
-rw-r--r-- | src/identd/identd_socket.cpp | 8 | ||||
-rw-r--r-- | src/network/tcp_client_socket_handler.cpp | 6 | ||||
-rw-r--r-- | src/network/tcp_client_socket_handler.hpp | 2 | ||||
-rw-r--r-- | src/xmpp/biboumi_component.cpp | 23 | ||||
-rw-r--r-- | src/xmpp/xmpp_component.cpp | 4 | ||||
-rw-r--r-- | src/xmpp/xmpp_component.hpp | 4 |
9 files changed, 52 insertions, 20 deletions
diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index a2e2c9c..424c72a 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -184,7 +184,7 @@ bool Bridge::join_irc_channel(const Iid& iid, std::string nickname, auto res_in_chan = this->is_resource_in_chan(ChannelKey{iid.get_local(), hostname}, resource); if (!res_in_chan) this->add_resource_to_chan(ChannelKey{iid.get_local(), hostname}, resource); - if (irc->is_channel_joined(iid.get_local()) == false) + if (!irc->is_channel_joined(iid.get_local())) { irc->send_join_command(iid.get_local(), password); return true; @@ -195,7 +195,7 @@ bool Bridge::join_irc_channel(const Iid& iid, std::string nickname, return false; } -void Bridge::send_channel_message(const Iid& iid, const std::string& body, std::string id) +void Bridge::send_channel_message(const Iid& iid, const std::string& body, std::string id, std::vector<XmlNode> nodes_to_reflect) { if (iid.get_server().empty()) { @@ -233,15 +233,21 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body, std:: if (!first || id.empty()) id = utils::gen_uuid(); - MessageCallback mirror_to_all_resources = [this, iid, uuid, id](const IrcClient* irc, const IrcMessage& message) { + MessageCallback mirror_to_all_resources = [this, iid, uuid, id, nodes_to_reflect](const IrcClient* irc, const IrcMessage& message) { std::string line = message.arguments[1]; // “temporary” workaround for \01ACTION…\01 -> /me messages if ((line.size() > strlen("\01ACTION\01")) && (line.substr(0, 7) == "\01ACTION") && line[line.size() - 1] == '\01') line = "/me " + line.substr(8, line.size() - 9); for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) - this->xmpp.send_muc_message(std::to_string(iid), irc->get_own_nick(), this->make_xmpp_body(line), - this->user_jid + "/" + resource, uuid, id); + { + auto stanza = this->xmpp.make_muc_message(std::to_string(iid), irc->get_own_nick(), this->make_xmpp_body(line), + this->user_jid + "/" + + resource, uuid, id); + for (const auto& node: nodes_to_reflect) + stanza.add_child(node); + this->xmpp.send_stanza(stanza); + } }; if (line.substr(0, 5) == "/mode") @@ -858,8 +864,10 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st #endif for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) { - this->xmpp.send_muc_message(std::to_string(iid), nick, this->make_xmpp_body(body, encoding), - this->user_jid + "/" + resource, uuid, utils::gen_uuid()); + auto stanza = this->xmpp.make_muc_message(std::to_string(iid), nick, this->make_xmpp_body(body, encoding), + this->user_jid + "/" + + resource, uuid, utils::gen_uuid()); + this->xmpp.send_stanza(stanza); } } else diff --git a/src/bridge/bridge.hpp b/src/bridge/bridge.hpp index 8f474e5..6b15478 100644 --- a/src/bridge/bridge.hpp +++ b/src/bridge/bridge.hpp @@ -79,7 +79,7 @@ public: const std::string& resource, HistoryLimit history_limit); - void send_channel_message(const Iid& iid, const std::string& body, std::string id); + void send_channel_message(const Iid& iid, const std::string& body, std::string id, std::vector<XmlNode> nodes_to_reflect); void send_private_message(const Iid& iid, const std::string& body, const std::string& type="PRIVMSG"); void send_raw_message(const std::string& hostname, const std::string& body); void leave_irc_channel(Iid&& iid, const std::string& status_message, const std::string& resource); diff --git a/src/identd/identd_server.hpp b/src/identd/identd_server.hpp index b1c8ec8..55fe225 100644 --- a/src/identd/identd_server.hpp +++ b/src/identd/identd_server.hpp @@ -24,6 +24,7 @@ class IdentdServer: public TcpSocketServer<IdentdSocket> if (this->poller->is_managing_socket(this->socket)) this->poller->remove_socket_handler(this->socket); ::close(this->socket); + this->sockets.clear(); } void clean() { diff --git a/src/identd/identd_socket.cpp b/src/identd/identd_socket.cpp index 92cd80b..7688bbe 100644 --- a/src/identd/identd_socket.cpp +++ b/src/identd/identd_socket.cpp @@ -25,10 +25,12 @@ void IdentdSocket::parse_in_buffer(const std::size_t) 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; + uint16_t local_port{}; + uint16_t remote_port{}; char sep; line >> local_port >> sep >> remote_port; + if (line.fail()) // Data did not match the expected format, ignore the line entirely + continue; const auto& xmpp = this->server.get_biboumi_component(); auto response = this->generate_answer(xmpp, local_port, remote_port); @@ -47,7 +49,7 @@ std::string IdentdSocket::generate_answer(const BiboumiComponent& biboumi, uint1 { for (const auto& pair: bridge->get_irc_clients()) { - if (pair.second->match_port_pairt(local, remote)) + if (pair.second->match_port_pair(local, remote)) { std::ostringstream os; os << local << " , " << remote << " : USERID : OTHER : " << hash_jid(bridge->get_bare_jid()) << "\r\n"; diff --git a/src/network/tcp_client_socket_handler.cpp b/src/network/tcp_client_socket_handler.cpp index 6f67f02..7d1029f 100644 --- a/src/network/tcp_client_socket_handler.cpp +++ b/src/network/tcp_client_socket_handler.cpp @@ -260,8 +260,10 @@ std::string TCPClientSocketHandler::get_port() const return this->port; } -bool TCPClientSocketHandler::match_port_pairt(const uint16_t local, const uint16_t remote) const +bool TCPClientSocketHandler::match_port_pair(const uint16_t local, const uint16_t remote) const { + if (!this->is_connected()) + return false; const auto remote_port = static_cast<uint16_t>(std::stoi(this->port)); - return this->is_connected() && local == this->local_port && remote == remote_port; + return local == this->local_port && remote == remote_port; } diff --git a/src/network/tcp_client_socket_handler.hpp b/src/network/tcp_client_socket_handler.hpp index 74caca9..38d8b84 100644 --- a/src/network/tcp_client_socket_handler.hpp +++ b/src/network/tcp_client_socket_handler.hpp @@ -34,7 +34,7 @@ class TCPClientSocketHandler: public TCPSocketHandler /** * Whether or not this connection is using the two given TCP ports. */ - bool match_port_pairt(const uint16_t local, const uint16_t remote) const; + bool match_port_pair(const uint16_t local, const uint16_t remote) const; protected: bool hostname_resolution_failed; diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 91be091..f49b3b6 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -302,7 +302,26 @@ void BiboumiComponent::handle_message(const Stanza& stanza) if (body && !body->get_inner().empty()) { if (bridge->is_resource_in_chan(iid.to_tuple(), from.resource)) - bridge->send_channel_message(iid, body->get_inner(), id); + { + // Extract some XML nodes that we must include in the + // reflection (if any), because XMPP says so + std::vector<XmlNode> nodes_to_reflect; + const XmlNode* origin_id = stanza.get_child("origin-id", STABLE_ID_NS); + if (origin_id) + nodes_to_reflect.push_back(*origin_id); + const auto own_address = std::to_string(iid) + '@' + this->served_hostname; + for (const XmlNode* stanza_id: stanza.get_children("stanza-id", STABLE_ID_NS)) + { + // Stanza ID generating entities, which encounter a + // <stanza-id/> element where the 'by' attribute matches + // the 'by' attribute they would otherwise set, MUST + // delete that element even if they are not adding their + // own stanza ID. + if (stanza_id->get_tag("by") != own_address) + nodes_to_reflect.push_back(*stanza_id); + } + bridge->send_channel_message(iid, body->get_inner(), id, std::move(nodes_to_reflect)); + } else { error_type = "modify"; @@ -1008,7 +1027,7 @@ void BiboumiComponent::send_irc_channel_disco_info(const std::string& id, const identity["category"] = "conference"; identity["type"] = "irc"; identity["name"] = ""s + iid.get_local() + " on " + iid.get_server(); - for (const char *ns: {DISCO_INFO_NS, MUC_NS, ADHOC_NS, PING_NS, MAM_NS, VERSION_NS, STABLE_MUC_ID_NS, SELF_PING_FLAG, "muc_nonanonymous"}) + for (const char *ns: {DISCO_INFO_NS, MUC_NS, ADHOC_NS, PING_NS, MAM_NS, VERSION_NS, STABLE_MUC_ID_NS, SELF_PING_FLAG, "muc_nonanonymous", STABLE_ID_NS}) { XmlSubNode feature(query, "feature"); feature["var"] = ns; diff --git a/src/xmpp/xmpp_component.cpp b/src/xmpp/xmpp_component.cpp index f82f9ce..767fb2e 100644 --- a/src/xmpp/xmpp_component.cpp +++ b/src/xmpp/xmpp_component.cpp @@ -367,7 +367,7 @@ void XmppComponent::send_topic(const std::string& from, Xmpp::body&& topic, cons this->send_stanza(message); } -void XmppComponent::send_muc_message(const std::string& muc_name, const std::string& nick, Xmpp::body&& xmpp_body, const std::string& jid_to, std::string uuid, std::string id) +Stanza XmppComponent::make_muc_message(const std::string& muc_name, const std::string& nick, Xmpp::body&& xmpp_body, const std::string& jid_to, std::string uuid, std::string id) { Stanza message("message"); message["to"] = jid_to; @@ -399,7 +399,7 @@ void XmppComponent::send_muc_message(const std::string& muc_name, const std::str stanza_id["id"] = std::move(uuid); } - this->send_stanza(message); + return message; } #ifdef USE_DATABASE diff --git a/src/xmpp/xmpp_component.hpp b/src/xmpp/xmpp_component.hpp index 156e286..ee6b776 100644 --- a/src/xmpp/xmpp_component.hpp +++ b/src/xmpp/xmpp_component.hpp @@ -135,8 +135,8 @@ public: /** * Send a (non-private) message to the MUC */ - void send_muc_message(const std::string& muc_name, const std::string& nick, Xmpp::body&& body, const std::string& jid_to, - std::string uuid, std::string id); + Stanza make_muc_message(const std::string& muc_name, const std::string& nick, Xmpp::body&& xmpp_body, const std::string& jid_to, + std::string uuid, std::string id); #ifdef USE_DATABASE /** * Send a message, with a <delay/> element, part of a MUC history |