From 0c8adc85f7373a85de8b3edc6cac87d5f7389bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 11 Nov 2016 02:54:48 +0100 Subject: Move all the connect() logic from TCPSocketHandler into a subclass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way, TCPSocketHandler only deal with the message sending/receiving, not the connect() or anything else. This will be used for implementing servers (because when a client is accepted, we don’t need all the connect() and dns resolution stuff). --- louloulibs/xmpp/xmpp_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/xmpp/xmpp_component.cpp') diff --git a/louloulibs/xmpp/xmpp_component.cpp b/louloulibs/xmpp/xmpp_component.cpp index fa8b0a5..1d1c58b 100644 --- a/louloulibs/xmpp/xmpp_component.cpp +++ b/louloulibs/xmpp/xmpp_component.cpp @@ -39,7 +39,7 @@ static std::set kickable_errors{ }; XmppComponent::XmppComponent(std::shared_ptr poller, const std::string& hostname, const std::string& secret): - TCPSocketHandler(poller), + TCPClientSocketHandler(poller), ever_auth(false), first_connection_try(true), secret(secret), -- cgit v1.2.3 From 2e4a9fe4c78bb45de912d2e5b90106397d59348e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 13 Dec 2016 22:47:19 +0100 Subject: Include the optional node in the send_presence_error --- louloulibs/xmpp/xmpp_component.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'louloulibs/xmpp/xmpp_component.cpp') diff --git a/louloulibs/xmpp/xmpp_component.cpp b/louloulibs/xmpp/xmpp_component.cpp index 1d1c58b..c842701 100644 --- a/louloulibs/xmpp/xmpp_component.cpp +++ b/louloulibs/xmpp/xmpp_component.cpp @@ -524,7 +524,7 @@ void XmppComponent::send_presence_error(const std::string& muc_name, const std::string& type, const std::string& condition, const std::string& error_code, - const std::string& /* text */) + const std::string& text) { Stanza presence("presence"); presence["from"] = muc_name + "@" + this->served_hostname + "/" + nickname; @@ -536,6 +536,12 @@ void XmppComponent::send_presence_error(const std::string& muc_name, XmlNode error("error"); error["by"] = muc_name + "@" + this->served_hostname; error["type"] = type; + if (text.empty()) + { + XmlNode text_node("text"); + text_node["xmlns"] = STANZA_NS; + text_node.set_inner(text); + } if (!error_code.empty()) error["code"] = error_code; XmlNode subnode(condition); -- cgit v1.2.3 From 810c4343c72b0a5ac61155f2a71a969fc5f8ea9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 13 Dec 2016 23:01:32 +0100 Subject: Remove the useless nullptr argument for the XmlNode constructor --- louloulibs/xmpp/xmpp_component.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'louloulibs/xmpp/xmpp_component.cpp') diff --git a/louloulibs/xmpp/xmpp_component.cpp b/louloulibs/xmpp/xmpp_component.cpp index c842701..32702d1 100644 --- a/louloulibs/xmpp/xmpp_component.cpp +++ b/louloulibs/xmpp/xmpp_component.cpp @@ -172,8 +172,8 @@ void XmppComponent::on_stanza(const Stanza& stanza) void XmppComponent::send_stream_error(const std::string& name, const std::string& explanation) { - XmlNode node("stream:error", nullptr); - XmlNode error(name, nullptr); + XmlNode node("stream:error"); + XmlNode error(name); error["xmlns"] = STREAM_NS; if (!explanation.empty()) error.set_inner(explanation); -- cgit v1.2.3 From ca8618941240545f76fd8ec32e7acb31226ab2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 13 Dec 2016 23:57:19 +0100 Subject: Include the element in stanza error when there IS a text --- louloulibs/xmpp/xmpp_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/xmpp/xmpp_component.cpp') diff --git a/louloulibs/xmpp/xmpp_component.cpp b/louloulibs/xmpp/xmpp_component.cpp index 32702d1..cbd80c4 100644 --- a/louloulibs/xmpp/xmpp_component.cpp +++ b/louloulibs/xmpp/xmpp_component.cpp @@ -536,7 +536,7 @@ void XmppComponent::send_presence_error(const std::string& muc_name, XmlNode error("error"); error["by"] = muc_name + "@" + this->served_hostname; error["type"] = type; - if (text.empty()) + if (!text.empty()) { XmlNode text_node("text"); text_node["xmlns"] = STANZA_NS; -- cgit v1.2.3 From f512c9c666b2c629e8b9af29ec65c534e536e749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 14 Dec 2016 18:20:57 +0100 Subject: e2e: test connection failure --- louloulibs/xmpp/xmpp_component.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'louloulibs/xmpp/xmpp_component.cpp') diff --git a/louloulibs/xmpp/xmpp_component.cpp b/louloulibs/xmpp/xmpp_component.cpp index cbd80c4..f0b0de7 100644 --- a/louloulibs/xmpp/xmpp_component.cpp +++ b/louloulibs/xmpp/xmpp_component.cpp @@ -541,6 +541,7 @@ void XmppComponent::send_presence_error(const std::string& muc_name, XmlNode text_node("text"); text_node["xmlns"] = STANZA_NS; text_node.set_inner(text); + error.add_child(std::move(text_node)); } if (!error_code.empty()) error["code"] = error_code; -- cgit v1.2.3 From 5a5bb7f63222189ea0dcfbd387d5e34458ccefe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 14 Dec 2016 18:28:44 +0100 Subject: Introduce a XmlSubNode class that automatically adds itself into its parent --- louloulibs/xmpp/xmpp_component.cpp | 539 ++++++++++++++++++------------------- 1 file changed, 267 insertions(+), 272 deletions(-) (limited to 'louloulibs/xmpp/xmpp_component.cpp') diff --git a/louloulibs/xmpp/xmpp_component.cpp b/louloulibs/xmpp/xmpp_component.cpp index f0b0de7..e1b6131 100644 --- a/louloulibs/xmpp/xmpp_component.cpp +++ b/louloulibs/xmpp/xmpp_component.cpp @@ -172,12 +172,13 @@ void XmppComponent::on_stanza(const Stanza& stanza) void XmppComponent::send_stream_error(const std::string& name, const std::string& explanation) { - XmlNode node("stream:error"); - XmlNode error(name); - error["xmlns"] = STREAM_NS; - if (!explanation.empty()) - error.set_inner(explanation); - node.add_child(std::move(error)); + Stanza node("stream:error"); + { + XmlSubNode error(node, name); + error["xmlns"] = STREAM_NS; + if (!explanation.empty()) + error.set_inner(explanation); + } this->send_stanza(node); } @@ -187,31 +188,34 @@ void XmppComponent::send_stanza_error(const std::string& kind, const std::string const bool fulljid) { Stanza node(kind); - if (!to.empty()) - node["to"] = to; - if (!from.empty()) + { + if (!to.empty()) + node["to"] = to; + if (!from.empty()) + { + if (fulljid) + node["from"] = from; + else + node["from"] = from + "@" + this->served_hostname; + } + if (!id.empty()) + node["id"] = id; + node["type"] = "error"; { - if (fulljid) - node["from"] = from; - else - node["from"] = from + "@" + this->served_hostname; + XmlSubNode error(node, "error"); + error["type"] = error_type; + { + XmlSubNode inner_error(error, defined_condition); + inner_error["xmlns"] = STANZA_NS; + } + if (!text.empty()) + { + XmlSubNode text_node(error, "text"); + text_node["xmlns"] = STANZA_NS; + text_node.set_inner(text); + } } - if (!id.empty()) - node["id"] = id; - node["type"] = "error"; - XmlNode error("error"); - error["type"] = error_type; - XmlNode inner_error(defined_condition); - inner_error["xmlns"] = STANZA_NS; - error.add_child(std::move(inner_error)); - if (!text.empty()) - { - XmlNode text_node("text"); - text_node["xmlns"] = STANZA_NS; - text_node.set_inner(text); - error.add_child(std::move(text_node)); - } - node.add_child(std::move(error)); + } this->send_stanza(node); } @@ -264,38 +268,33 @@ void* XmppComponent::get_receive_buffer(const size_t size) const void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, const std::string& to, const std::string& type, const bool fulljid, const bool nocopy) { - XmlNode node("message"); - node["to"] = to; - if (fulljid) - node["from"] = from; - else - node["from"] = from + "@" + this->served_hostname; - if (!type.empty()) - node["type"] = type; - XmlNode body_node("body"); - body_node.set_inner(std::get<0>(body)); - node.add_child(std::move(body_node)); - if (std::get<1>(body)) - { - XmlNode html("html"); - html["xmlns"] = XHTMLIM_NS; - // Pass the ownership of the pointer to this xmlnode - html.add_child(std::move(std::get<1>(body))); - node.add_child(std::move(html)); - } - - if (nocopy) - { - XmlNode private_node("private"); - private_node["xmlns"] = "urn:xmpp:carbons:2"; - node.add_child(std::move(private_node)); - - XmlNode nocopy("no-copy"); - nocopy["xmlns"] = "urn:xmpp:hints"; - node.add_child(std::move(nocopy)); - } - - this->send_stanza(node); + Stanza message("message"); + { + message["to"] = to; + if (fulljid) + message["from"] = from; + else + message["from"] = from + "@" + this->served_hostname; + if (!type.empty()) + message["type"] = type; + XmlSubNode body_node(message, "body"); + body_node.set_inner(std::get<0>(body)); + if (std::get<1>(body)) + { + XmlSubNode html(message, "html"); + html["xmlns"] = XHTMLIM_NS; + // Pass the ownership of the pointer to this xmlnode + html.add_child(std::move(std::get<1>(body))); + } + if (nocopy) + { + XmlSubNode private_node(message, "private"); + private_node["xmlns"] = "urn:xmpp:carbons:2"; + XmlSubNode nocopy(message, "no-copy"); + nocopy["xmlns"] = "urn:xmpp:hints"; + } + } + this->send_stanza(message); } void XmppComponent::send_user_join(const std::string& from, @@ -306,34 +305,33 @@ void XmppComponent::send_user_join(const std::string& from, const std::string& to, const bool self) { - XmlNode node("presence"); - node["to"] = to; - node["from"] = from + "@" + this->served_hostname + "/" + nick; - - XmlNode x("x"); - x["xmlns"] = MUC_USER_NS; - - XmlNode item("item"); - if (!affiliation.empty()) - item["affiliation"] = affiliation; - if (!role.empty()) - item["role"] = role; - if (!realjid.empty()) - { - const std::string preped_jid = jidprep(realjid); - if (!preped_jid.empty()) - item["jid"] = preped_jid; - } - x.add_child(std::move(item)); - - if (self) - { - XmlNode status("status"); - status["code"] = "110"; - x.add_child(std::move(status)); - } - node.add_child(std::move(x)); - this->send_stanza(node); + Stanza presence("presence"); + { + presence["to"] = to; + presence["from"] = from + "@" + this->served_hostname + "/" + nick; + + XmlSubNode x(presence, "x"); + x["xmlns"] = MUC_USER_NS; + + XmlSubNode item(x, "item"); + if (!affiliation.empty()) + item["affiliation"] = affiliation; + if (!role.empty()) + item["role"] = role; + if (!realjid.empty()) + { + const std::string preped_jid = jidprep(realjid); + if (!preped_jid.empty()) + item["jid"] = preped_jid; + } + + if (self) + { + XmlSubNode status(x, "status"); + status["code"] = "110"; + } + } + this->send_stanza(presence); } void XmppComponent::send_invalid_room_error(const std::string& muc_name, @@ -341,44 +339,43 @@ void XmppComponent::send_invalid_room_error(const std::string& muc_name, const std::string& to) { Stanza presence("presence"); - if (!muc_name.empty()) - presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick; - else - presence["from"] = this->served_hostname; - presence["to"] = to; - presence["type"] = "error"; - XmlNode x("x"); - x["xmlns"] = MUC_NS; - presence.add_child(std::move(x)); - XmlNode error("error"); - error["by"] = muc_name + "@" + this->served_hostname; - error["type"] = "cancel"; - XmlNode item_not_found("item-not-found"); - item_not_found["xmlns"] = STANZA_NS; - error.add_child(std::move(item_not_found)); - XmlNode text("text"); - text["xmlns"] = STANZA_NS; - text["xml:lang"] = "en"; - text.set_inner(muc_name + - " is not a valid IRC channel name. A correct room jid is of the form: #%@" + - this->served_hostname); - error.add_child(std::move(text)); - presence.add_child(std::move(error)); + { + if (!muc_name.empty ()) + presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick; + else + presence["from"] = this->served_hostname; + presence["to"] = to; + presence["type"] = "error"; + XmlSubNode x(presence, "x"); + x["xmlns"] = MUC_NS; + XmlSubNode error(presence, "error"); + error["by"] = muc_name + "@" + this->served_hostname; + error["type"] = "cancel"; + XmlSubNode item_not_found(error, "item-not-found"); + item_not_found["xmlns"] = STANZA_NS; + XmlSubNode text(error, "text"); + text["xmlns"] = STANZA_NS; + text["xml:lang"] = "en"; + text.set_inner(muc_name + + " is not a valid IRC channel name. A correct room jid is of the form: #%@" + + this->served_hostname); + } this->send_stanza(presence); } void XmppComponent::send_topic(const std::string& from, Xmpp::body&& topic, const std::string& to, const std::string& who) { - XmlNode message("message"); - message["to"] = to; - if (who.empty()) - message["from"] = from + "@" + this->served_hostname; - else - message["from"] = from + "@" + this->served_hostname + "/" + who; - message["type"] = "groupchat"; - XmlNode subject("subject"); - subject.set_inner(std::get<0>(topic)); - message.add_child(std::move(subject)); + Stanza message("message"); + { + message["to"] = to; + if (who.empty()) + message["from"] = from + "@" + this->served_hostname; + else + message["from"] = from + "@" + this->served_hostname + "/" + who; + message["type"] = "groupchat"; + XmlSubNode subject(message, "subject"); + subject.set_inner(std::get<0>(topic)); + } this->send_stanza(message); } @@ -391,16 +388,18 @@ void XmppComponent::send_muc_message(const std::string& muc_name, const std::str else // Message from the room itself message["from"] = muc_name + "@" + this->served_hostname; message["type"] = "groupchat"; - XmlNode body("body"); - body.set_inner(std::get<0>(xmpp_body)); - message.add_child(std::move(body)); + + { + XmlSubNode body(message, "body"); + body.set_inner(std::get<0>(xmpp_body)); + } + if (std::get<1>(xmpp_body)) { - XmlNode html("html"); + XmlSubNode html(message, "html"); html["xmlns"] = XHTMLIM_NS; // Pass the ownership of the pointer to this xmlnode html.add_child(std::move(std::get<1>(xmpp_body))); - message.add_child(std::move(html)); } this->send_stanza(message); } @@ -415,41 +414,41 @@ void XmppComponent::send_history_message(const std::string& muc_name, const std: message["from"] = muc_name + "@" + this->served_hostname; message["type"] = "groupchat"; - XmlNode body("body"); - body.set_inner(body_txt); - message.add_child(std::move(body)); - - XmlNode delay("delay"); - delay["xmlns"] = DELAY_NS; - delay["from"] = muc_name + "@" + this->served_hostname; - delay["stamp"] = utils::to_string(timestamp); + { + XmlSubNode body(message, "body"); + body.set_inner(body_txt); + } + { + XmlSubNode delay(message, "delay"); + delay["xmlns"] = DELAY_NS; + delay["from"] = muc_name + "@" + this->served_hostname; + delay["stamp"] = utils::to_string(timestamp); + } - message.add_child(std::move(delay)); this->send_stanza(message); } void XmppComponent::send_muc_leave(const std::string& muc_name, std::string&& nick, Xmpp::body&& message, const std::string& jid_to, const bool self) { Stanza presence("presence"); - presence["to"] = jid_to; - presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick; - presence["type"] = "unavailable"; - const std::string message_str = std::get<0>(message); - XmlNode x("x"); - x["xmlns"] = MUC_USER_NS; - if (self) - { - XmlNode status("status"); - status["code"] = "110"; - x.add_child(std::move(status)); - } - presence.add_child(std::move(x)); - if (!message_str.empty()) - { - XmlNode status("status"); - status.set_inner(message_str); - presence.add_child(std::move(status)); - } + { + presence["to"] = jid_to; + presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick; + presence["type"] = "unavailable"; + const std::string message_str = std::get<0>(message); + XmlSubNode x(presence, "x"); + x["xmlns"] = MUC_USER_NS; + if (self) + { + XmlSubNode status(x, "status"); + status["code"] = "110"; + } + if (!message_str.empty()) + { + XmlSubNode status(presence, "status"); + status.set_inner(message_str); + } + } this->send_stanza(presence); } @@ -462,24 +461,22 @@ void XmppComponent::send_nick_change(const std::string& muc_name, const bool self) { Stanza presence("presence"); - presence["to"] = jid_to; - presence["from"] = muc_name + "@" + this->served_hostname + "/" + old_nick; - presence["type"] = "unavailable"; - XmlNode x("x"); - x["xmlns"] = MUC_USER_NS; - XmlNode item("item"); - item["nick"] = new_nick; - x.add_child(std::move(item)); - XmlNode status("status"); - status["code"] = "303"; - x.add_child(std::move(status)); - if (self) - { - XmlNode status2("status"); - status2["code"] = "110"; - x.add_child(std::move(status2)); - } - presence.add_child(std::move(x)); + { + presence["to"] = jid_to; + presence["from"] = muc_name + "@" + this->served_hostname + "/" + old_nick; + presence["type"] = "unavailable"; + XmlSubNode x(presence, "x"); + x["xmlns"] = MUC_USER_NS; + XmlSubNode item(x, "item"); + item["nick"] = new_nick; + XmlSubNode status(x, "status"); + status["code"] = "303"; + if (self) + { + XmlSubNode status(x, "status"); + status["code"] = "110"; + } + } this->send_stanza(presence); this->send_user_join(muc_name, new_nick, "", affiliation, role, jid_to, self); @@ -489,32 +486,28 @@ void XmppComponent::kick_user(const std::string& muc_name, const std::string& ta const std::string& author, const std::string& jid_to, const bool self) { Stanza presence("presence"); - presence["from"] = muc_name + "@" + this->served_hostname + "/" + target; - presence["to"] = jid_to; - presence["type"] = "unavailable"; - XmlNode x("x"); - x["xmlns"] = MUC_USER_NS; - XmlNode item("item"); - item["affiliation"] = "none"; - item["role"] = "none"; - XmlNode actor("actor"); - actor["nick"] = author; - actor["jid"] = author; // backward compatibility with old clients - item.add_child(std::move(actor)); - XmlNode reason("reason"); - reason.set_inner(txt); - item.add_child(std::move(reason)); - x.add_child(std::move(item)); - XmlNode status("status"); - status["code"] = "307"; - x.add_child(std::move(status)); - if (self) - { - XmlNode status("status"); - status["code"] = "110"; - x.add_child(std::move(status)); - } - presence.add_child(std::move(x)); + { + presence["from"] = muc_name + "@" + this->served_hostname + "/" + target; + presence["to"] = jid_to; + presence["type"] = "unavailable"; + XmlSubNode x(presence, "x"); + x["xmlns"] = MUC_USER_NS; + XmlSubNode item(x, "item"); + item["affiliation"] = "none"; + item["role"] = "none"; + XmlSubNode actor(item, "actor"); + actor["nick"] = author; + actor["jid"] = author; // backward compatibility with old clients + XmlSubNode reason(item, "reason"); + reason.set_inner(txt); + XmlSubNode status(x, "status"); + status["code"] = "307"; + if (self) + { + XmlSubNode status(x, "status"); + status["code"] = "110"; + } + } this->send_stanza(presence); } @@ -527,28 +520,26 @@ void XmppComponent::send_presence_error(const std::string& muc_name, const std::string& text) { Stanza presence("presence"); - presence["from"] = muc_name + "@" + this->served_hostname + "/" + nickname; - presence["to"] = jid_to; - presence["type"] = "error"; - XmlNode x("x"); - x["xmlns"] = MUC_NS; - presence.add_child(std::move(x)); - XmlNode error("error"); - error["by"] = muc_name + "@" + this->served_hostname; - error["type"] = type; - if (!text.empty()) - { - XmlNode text_node("text"); - text_node["xmlns"] = STANZA_NS; - text_node.set_inner(text); - error.add_child(std::move(text_node)); - } - if (!error_code.empty()) - error["code"] = error_code; - XmlNode subnode(condition); - subnode["xmlns"] = STANZA_NS; - error.add_child(std::move(subnode)); - presence.add_child(std::move(error)); + { + presence["from"] = muc_name + "@" + this->served_hostname + "/" + nickname; + presence["to"] = jid_to; + presence["type"] = "error"; + XmlSubNode x(presence, "x"); + x["xmlns"] = MUC_NS; + XmlSubNode error(presence, "error"); + error["by"] = muc_name + "@" + this->served_hostname; + error["type"] = type; + if (!text.empty()) + { + XmlSubNode text_node(error, "text"); + text_node["xmlns"] = STANZA_NS; + text_node.set_inner(text); + } + if (!error_code.empty()) + error["code"] = error_code; + XmlSubNode subnode(error, condition); + subnode["xmlns"] = STANZA_NS; + } this->send_stanza(presence); } @@ -559,15 +550,15 @@ void XmppComponent::send_affiliation_role_change(const std::string& muc_name, const std::string& jid_to) { Stanza presence("presence"); - presence["from"] = muc_name + "@" + this->served_hostname + "/" + target; - presence["to"] = jid_to; - XmlNode x("x"); - x["xmlns"] = MUC_USER_NS; - XmlNode item("item"); - item["affiliation"] = affiliation; - item["role"] = role; - x.add_child(std::move(item)); - presence.add_child(std::move(x)); + { + presence["from"] = muc_name + "@" + this->served_hostname + "/" + target; + presence["to"] = jid_to; + XmlSubNode x(presence, "x"); + x["xmlns"] = MUC_USER_NS; + XmlSubNode item(x, "item"); + item["affiliation"] = affiliation; + item["role"] = role; + } this->send_stanza(presence); } @@ -579,27 +570,30 @@ void XmppComponent::send_version(const std::string& id, const std::string& jid_t iq["id"] = id; iq["to"] = jid_to; iq["from"] = jid_from; - XmlNode query("query"); - query["xmlns"] = VERSION_NS; - if (version.empty()) - { - XmlNode name("name"); - name.set_inner("biboumi"); - query.add_child(std::move(name)); - XmlNode version("version"); - version.set_inner(SOFTWARE_VERSION); - query.add_child(std::move(version)); - XmlNode os("os"); - os.set_inner(SYSTEM_NAME); - query.add_child(std::move(os)); + { + XmlSubNode query(iq, "query"); + query["xmlns"] = VERSION_NS; + if (version.empty()) + { + { + XmlSubNode name(query, "name"); + name.set_inner("biboumi"); + } + { + XmlSubNode version(query, "version"); + version.set_inner(SOFTWARE_VERSION); + } + { + XmlSubNode os(query, "os"); + os.set_inner(SYSTEM_NAME); + } } - else + else { - XmlNode name("name"); + XmlSubNode name(query, "name"); name.set_inner(version); - query.add_child(std::move(name)); } - iq.add_child(std::move(query)); + } this->send_stanza(iq); } @@ -608,24 +602,24 @@ void XmppComponent::send_adhoc_commands_list(const std::string& id, const std::s const bool with_admin_only, const AdhocCommandsHandler& adhoc_handler) { Stanza iq("iq"); - iq["type"] = "result"; - iq["id"] = id; - iq["to"] = requester_jid; - iq["from"] = from_jid; - XmlNode query("query"); - query["xmlns"] = DISCO_ITEMS_NS; - query["node"] = ADHOC_NS; - for (const auto& kv: adhoc_handler.get_commands()) - { - if (kv.second.is_admin_only() && !with_admin_only) - continue; - XmlNode item("item"); - item["jid"] = from_jid; - item["node"] = kv.first; - item["name"] = kv.second.name; - query.add_child(std::move(item)); - } - iq.add_child(std::move(query)); + { + iq["type"] = "result"; + iq["id"] = id; + iq["to"] = requester_jid; + iq["from"] = from_jid; + XmlSubNode query(iq, "query"); + query["xmlns"] = DISCO_ITEMS_NS; + query["node"] = ADHOC_NS; + for (const auto &kv: adhoc_handler.get_commands()) + { + if (kv.second.is_admin_only() && !with_admin_only) + continue; + XmlSubNode item(query, "item"); + item["jid"] = from_jid; + item["node"] = kv.first; + item["name"] = kv.second.name; + } + } this->send_stanza(iq); } @@ -633,13 +627,14 @@ void XmppComponent::send_iq_version_request(const std::string& from, const std::string& jid_to) { Stanza iq("iq"); - iq["type"] = "get"; - iq["id"] = "version_"s + XmppComponent::next_id(); - iq["from"] = from + "@" + this->served_hostname; - iq["to"] = jid_to; - XmlNode query("query"); - query["xmlns"] = VERSION_NS; - iq.add_child(std::move(query)); + { + iq["type"] = "get"; + iq["id"] = "version_"s + XmppComponent::next_id(); + iq["from"] = from + "@" + this->served_hostname; + iq["to"] = jid_to; + XmlSubNode query(iq, "query"); + query["xmlns"] = VERSION_NS; + } this->send_stanza(iq); } -- cgit v1.2.3 From d81cbc4a33ee2c28628ccb632af9ae1b27e84d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 27 Feb 2017 18:01:20 +0100 Subject: Use uname() instead of CMAKE_SYSTEM fix #3235 --- louloulibs/xmpp/xmpp_component.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'louloulibs/xmpp/xmpp_component.cpp') diff --git a/louloulibs/xmpp/xmpp_component.cpp b/louloulibs/xmpp/xmpp_component.cpp index e1b6131..e40b1e4 100644 --- a/louloulibs/xmpp/xmpp_component.cpp +++ b/louloulibs/xmpp/xmpp_component.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -585,7 +586,7 @@ void XmppComponent::send_version(const std::string& id, const std::string& jid_t } { XmlSubNode os(query, "os"); - os.set_inner(SYSTEM_NAME); + os.set_inner(utils::get_system_name()); } } else -- cgit v1.2.3 From f0bc6c83a8eb548d0a3edbf7c16a6922bfd24ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 8 Mar 2017 19:04:15 +0100 Subject: Pass the shared_ptr by reference, to avoid useless copies --- louloulibs/xmpp/xmpp_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/xmpp/xmpp_component.cpp') diff --git a/louloulibs/xmpp/xmpp_component.cpp b/louloulibs/xmpp/xmpp_component.cpp index e40b1e4..5d98e58 100644 --- a/louloulibs/xmpp/xmpp_component.cpp +++ b/louloulibs/xmpp/xmpp_component.cpp @@ -39,7 +39,7 @@ static std::set kickable_errors{ "malformed-error" }; -XmppComponent::XmppComponent(std::shared_ptr poller, const std::string& hostname, const std::string& secret): +XmppComponent::XmppComponent(std::shared_ptr& poller, const std::string& hostname, const std::string& secret): TCPClientSocketHandler(poller), ever_auth(false), first_connection_try(true), -- cgit v1.2.3 From 0ab40dc1ab4e689921da54080b135e1d22b1c586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 14 Mar 2017 21:45:23 +0100 Subject: Refactoring louloulibs and cmake Use OBJECT libraries Remove the louloulibs directory Write FOUND variables in the cache --- louloulibs/xmpp/xmpp_component.cpp | 672 ------------------------------------- 1 file changed, 672 deletions(-) delete mode 100644 louloulibs/xmpp/xmpp_component.cpp (limited to 'louloulibs/xmpp/xmpp_component.cpp') diff --git a/louloulibs/xmpp/xmpp_component.cpp b/louloulibs/xmpp/xmpp_component.cpp deleted file mode 100644 index 5d98e58..0000000 --- a/louloulibs/xmpp/xmpp_component.cpp +++ /dev/null @@ -1,672 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -#include -#ifdef SYSTEMD_FOUND -# include -#endif - -using namespace std::string_literals; - -static std::set kickable_errors{ - "gone", - "internal-server-error", - "item-not-found", - "jid-malformed", - "recipient-unavailable", - "redirect", - "remote-server-not-found", - "remote-server-timeout", - "service-unavailable", - "malformed-error" - }; - -XmppComponent::XmppComponent(std::shared_ptr& poller, const std::string& hostname, const std::string& secret): - TCPClientSocketHandler(poller), - ever_auth(false), - first_connection_try(true), - secret(secret), - authenticated(false), - doc_open(false), - served_hostname(hostname), - stanza_handlers{}, - adhoc_commands_handler(*this) -{ - this->parser.add_stream_open_callback(std::bind(&XmppComponent::on_remote_stream_open, this, - std::placeholders::_1)); - this->parser.add_stanza_callback(std::bind(&XmppComponent::on_stanza, this, - std::placeholders::_1)); - this->parser.add_stream_close_callback(std::bind(&XmppComponent::on_remote_stream_close, this, - std::placeholders::_1)); - this->stanza_handlers.emplace("handshake", - std::bind(&XmppComponent::handle_handshake, this,std::placeholders::_1)); - this->stanza_handlers.emplace("error", - std::bind(&XmppComponent::handle_error, this,std::placeholders::_1)); -} - -void XmppComponent::start() -{ - this->connect(Config::get("xmpp_server_ip", "127.0.0.1"), Config::get("port", "5347"), false); -} - -bool XmppComponent::is_document_open() const -{ - return this->doc_open; -} - -void XmppComponent::send_stanza(const Stanza& stanza) -{ - std::string str = stanza.to_string(); - log_debug("XMPP SENDING: ", str); - this->send_data(std::move(str)); -} - -void XmppComponent::on_connection_failed(const std::string& reason) -{ - this->first_connection_try = false; - log_error("Failed to connect to the XMPP server: ", reason); -#ifdef SYSTEMD_FOUND - sd_notifyf(0, "STATUS=Failed to connect to the XMPP server: %s", reason.data()); -#endif -} - -void XmppComponent::on_connected() -{ - log_info("connected to XMPP server"); - this->first_connection_try = true; - auto data = ""; - log_debug("XMPP SENDING: ", data); - this->send_data(std::move(data)); - this->doc_open = true; - // We may have some pending data to send: this happens when we try to send - // some data before we are actually connected. We send that data right now, if any - this->send_pending_data(); -} - -void XmppComponent::on_connection_close(const std::string& error) -{ - if (error.empty()) - log_info("XMPP server closed connection"); - else - log_info("XMPP server closed connection: ", error); -} - -void XmppComponent::parse_in_buffer(const size_t size) -{ - if (!this->in_buf.empty()) - { // This may happen if the parser could not allocate enough space for - // us. We try to feed it the data that was read into our in_buf - // instead. If this fails again we are in trouble. - this->parser.feed(this->in_buf.data(), this->in_buf.size(), false); - this->in_buf.clear(); - } - else - { // Just tell the parser to parse the data that was placed into the - // buffer it provided to us with GetBuffer - this->parser.parse(size, false); - } -} - -void XmppComponent::on_remote_stream_open(const XmlNode& node) -{ - log_debug("XMPP RECEIVING: ", node.to_string()); - this->stream_id = node.get_tag("id"); - if (this->stream_id.empty()) - { - log_error("Error: no attribute 'id' found"); - this->send_stream_error("bad-format", "missing 'id' attribute"); - this->close_document(); - return ; - } - - // Try to authenticate - auto data = ""s + get_handshake_digest(this->stream_id, this->secret) + ""; - log_debug("XMPP SENDING: ", data); - this->send_data(std::move(data)); -} - -void XmppComponent::on_remote_stream_close(const XmlNode& node) -{ - log_debug("XMPP RECEIVING: ", node.to_string()); - this->doc_open = false; -} - -void XmppComponent::reset() -{ - this->parser.reset(); -} - -void XmppComponent::on_stanza(const Stanza& stanza) -{ - log_debug("XMPP RECEIVING: ", stanza.to_string()); - std::function handler; - try - { - handler = this->stanza_handlers.at(stanza.get_name()); - } - catch (const std::out_of_range& exception) - { - log_warning("No handler for stanza of type ", stanza.get_name()); - return; - } - handler(stanza); -} - -void XmppComponent::send_stream_error(const std::string& name, const std::string& explanation) -{ - Stanza node("stream:error"); - { - XmlSubNode error(node, name); - error["xmlns"] = STREAM_NS; - if (!explanation.empty()) - error.set_inner(explanation); - } - this->send_stanza(node); -} - -void XmppComponent::send_stanza_error(const std::string& kind, const std::string& to, const std::string& from, - const std::string& id, const std::string& error_type, - const std::string& defined_condition, const std::string& text, - const bool fulljid) -{ - Stanza node(kind); - { - if (!to.empty()) - node["to"] = to; - if (!from.empty()) - { - if (fulljid) - node["from"] = from; - else - node["from"] = from + "@" + this->served_hostname; - } - if (!id.empty()) - node["id"] = id; - node["type"] = "error"; - { - XmlSubNode error(node, "error"); - error["type"] = error_type; - { - XmlSubNode inner_error(error, defined_condition); - inner_error["xmlns"] = STANZA_NS; - } - if (!text.empty()) - { - XmlSubNode text_node(error, "text"); - text_node["xmlns"] = STANZA_NS; - text_node.set_inner(text); - } - } - } - this->send_stanza(node); -} - -void XmppComponent::close_document() -{ - log_debug("XMPP SENDING: "); - this->send_data(""); - this->doc_open = false; -} - -void XmppComponent::handle_handshake(const Stanza&) -{ - this->authenticated = true; - this->ever_auth = true; - log_info("Authenticated with the XMPP server"); -#ifdef SYSTEMD_FOUND - sd_notify(0, "READY=1"); - // Install an event that sends a keepalive to systemd. If biboumi crashes - // or hangs for too long, systemd will restart it. - uint64_t usec; - if (sd_watchdog_enabled(0, &usec) > 0) - { - TimedEventsManager::instance().add_event(TimedEvent( - std::chrono::duration_cast(std::chrono::microseconds(usec / 2)), - []() { sd_notify(0, "WATCHDOG=1"); })); - } -#endif - this->after_handshake(); -} - -void XmppComponent::handle_error(const Stanza& stanza) -{ - const XmlNode* text = stanza.get_child("text", STREAMS_NS); - std::string error_message("Unspecified error"); - if (text) - error_message = text->get_inner(); - log_error("Stream error received from the XMPP server: ", error_message); -#ifdef SYSTEMD_FOUND - if (!this->ever_auth) - sd_notifyf(0, "STATUS=Failed to authenticate to the XMPP server: %s", error_message.data()); -#endif - -} - -void* XmppComponent::get_receive_buffer(const size_t size) const -{ - return this->parser.get_buffer(size); -} - -void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, const std::string& to, - const std::string& type, const bool fulljid, const bool nocopy) -{ - Stanza message("message"); - { - message["to"] = to; - if (fulljid) - message["from"] = from; - else - message["from"] = from + "@" + this->served_hostname; - if (!type.empty()) - message["type"] = type; - XmlSubNode body_node(message, "body"); - body_node.set_inner(std::get<0>(body)); - if (std::get<1>(body)) - { - XmlSubNode html(message, "html"); - html["xmlns"] = XHTMLIM_NS; - // Pass the ownership of the pointer to this xmlnode - html.add_child(std::move(std::get<1>(body))); - } - if (nocopy) - { - XmlSubNode private_node(message, "private"); - private_node["xmlns"] = "urn:xmpp:carbons:2"; - XmlSubNode nocopy(message, "no-copy"); - nocopy["xmlns"] = "urn:xmpp:hints"; - } - } - this->send_stanza(message); -} - -void XmppComponent::send_user_join(const std::string& from, - const std::string& nick, - const std::string& realjid, - const std::string& affiliation, - const std::string& role, - const std::string& to, - const bool self) -{ - Stanza presence("presence"); - { - presence["to"] = to; - presence["from"] = from + "@" + this->served_hostname + "/" + nick; - - XmlSubNode x(presence, "x"); - x["xmlns"] = MUC_USER_NS; - - XmlSubNode item(x, "item"); - if (!affiliation.empty()) - item["affiliation"] = affiliation; - if (!role.empty()) - item["role"] = role; - if (!realjid.empty()) - { - const std::string preped_jid = jidprep(realjid); - if (!preped_jid.empty()) - item["jid"] = preped_jid; - } - - if (self) - { - XmlSubNode status(x, "status"); - status["code"] = "110"; - } - } - this->send_stanza(presence); -} - -void XmppComponent::send_invalid_room_error(const std::string& muc_name, - const std::string& nick, - const std::string& to) -{ - Stanza presence("presence"); - { - if (!muc_name.empty ()) - presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick; - else - presence["from"] = this->served_hostname; - presence["to"] = to; - presence["type"] = "error"; - XmlSubNode x(presence, "x"); - x["xmlns"] = MUC_NS; - XmlSubNode error(presence, "error"); - error["by"] = muc_name + "@" + this->served_hostname; - error["type"] = "cancel"; - XmlSubNode item_not_found(error, "item-not-found"); - item_not_found["xmlns"] = STANZA_NS; - XmlSubNode text(error, "text"); - text["xmlns"] = STANZA_NS; - text["xml:lang"] = "en"; - text.set_inner(muc_name + - " is not a valid IRC channel name. A correct room jid is of the form: #%@" + - this->served_hostname); - } - this->send_stanza(presence); -} - -void XmppComponent::send_topic(const std::string& from, Xmpp::body&& topic, const std::string& to, const std::string& who) -{ - Stanza message("message"); - { - message["to"] = to; - if (who.empty()) - message["from"] = from + "@" + this->served_hostname; - else - message["from"] = from + "@" + this->served_hostname + "/" + who; - message["type"] = "groupchat"; - XmlSubNode subject(message, "subject"); - subject.set_inner(std::get<0>(topic)); - } - 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) -{ - Stanza message("message"); - message["to"] = jid_to; - if (!nick.empty()) - message["from"] = muc_name + "@" + this->served_hostname + "/" + nick; - else // Message from the room itself - message["from"] = muc_name + "@" + this->served_hostname; - message["type"] = "groupchat"; - - { - XmlSubNode body(message, "body"); - body.set_inner(std::get<0>(xmpp_body)); - } - - if (std::get<1>(xmpp_body)) - { - XmlSubNode html(message, "html"); - html["xmlns"] = XHTMLIM_NS; - // Pass the ownership of the pointer to this xmlnode - html.add_child(std::move(std::get<1>(xmpp_body))); - } - this->send_stanza(message); -} - -void XmppComponent::send_history_message(const std::string& muc_name, const std::string& nick, const std::string& body_txt, const std::string& jid_to, std::time_t timestamp) -{ - Stanza message("message"); - message["to"] = jid_to; - if (!nick.empty()) - message["from"] = muc_name + "@" + this->served_hostname + "/" + nick; - else - message["from"] = muc_name + "@" + this->served_hostname; - message["type"] = "groupchat"; - - { - XmlSubNode body(message, "body"); - body.set_inner(body_txt); - } - { - XmlSubNode delay(message, "delay"); - delay["xmlns"] = DELAY_NS; - delay["from"] = muc_name + "@" + this->served_hostname; - delay["stamp"] = utils::to_string(timestamp); - } - - this->send_stanza(message); -} - -void XmppComponent::send_muc_leave(const std::string& muc_name, std::string&& nick, Xmpp::body&& message, const std::string& jid_to, const bool self) -{ - Stanza presence("presence"); - { - presence["to"] = jid_to; - presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick; - presence["type"] = "unavailable"; - const std::string message_str = std::get<0>(message); - XmlSubNode x(presence, "x"); - x["xmlns"] = MUC_USER_NS; - if (self) - { - XmlSubNode status(x, "status"); - status["code"] = "110"; - } - if (!message_str.empty()) - { - XmlSubNode status(presence, "status"); - status.set_inner(message_str); - } - } - this->send_stanza(presence); -} - -void XmppComponent::send_nick_change(const std::string& muc_name, - const std::string& old_nick, - const std::string& new_nick, - const std::string& affiliation, - const std::string& role, - const std::string& jid_to, - const bool self) -{ - Stanza presence("presence"); - { - presence["to"] = jid_to; - presence["from"] = muc_name + "@" + this->served_hostname + "/" + old_nick; - presence["type"] = "unavailable"; - XmlSubNode x(presence, "x"); - x["xmlns"] = MUC_USER_NS; - XmlSubNode item(x, "item"); - item["nick"] = new_nick; - XmlSubNode status(x, "status"); - status["code"] = "303"; - if (self) - { - XmlSubNode status(x, "status"); - status["code"] = "110"; - } - } - this->send_stanza(presence); - - this->send_user_join(muc_name, new_nick, "", affiliation, role, jid_to, self); -} - -void XmppComponent::kick_user(const std::string& muc_name, const std::string& target, const std::string& txt, - const std::string& author, const std::string& jid_to, const bool self) -{ - Stanza presence("presence"); - { - presence["from"] = muc_name + "@" + this->served_hostname + "/" + target; - presence["to"] = jid_to; - presence["type"] = "unavailable"; - XmlSubNode x(presence, "x"); - x["xmlns"] = MUC_USER_NS; - XmlSubNode item(x, "item"); - item["affiliation"] = "none"; - item["role"] = "none"; - XmlSubNode actor(item, "actor"); - actor["nick"] = author; - actor["jid"] = author; // backward compatibility with old clients - XmlSubNode reason(item, "reason"); - reason.set_inner(txt); - XmlSubNode status(x, "status"); - status["code"] = "307"; - if (self) - { - XmlSubNode status(x, "status"); - status["code"] = "110"; - } - } - this->send_stanza(presence); -} - -void XmppComponent::send_presence_error(const std::string& muc_name, - const std::string& nickname, - const std::string& jid_to, - const std::string& type, - const std::string& condition, - const std::string& error_code, - const std::string& text) -{ - Stanza presence("presence"); - { - presence["from"] = muc_name + "@" + this->served_hostname + "/" + nickname; - presence["to"] = jid_to; - presence["type"] = "error"; - XmlSubNode x(presence, "x"); - x["xmlns"] = MUC_NS; - XmlSubNode error(presence, "error"); - error["by"] = muc_name + "@" + this->served_hostname; - error["type"] = type; - if (!text.empty()) - { - XmlSubNode text_node(error, "text"); - text_node["xmlns"] = STANZA_NS; - text_node.set_inner(text); - } - if (!error_code.empty()) - error["code"] = error_code; - XmlSubNode subnode(error, condition); - subnode["xmlns"] = STANZA_NS; - } - this->send_stanza(presence); -} - -void XmppComponent::send_affiliation_role_change(const std::string& muc_name, - const std::string& target, - const std::string& affiliation, - const std::string& role, - const std::string& jid_to) -{ - Stanza presence("presence"); - { - presence["from"] = muc_name + "@" + this->served_hostname + "/" + target; - presence["to"] = jid_to; - XmlSubNode x(presence, "x"); - x["xmlns"] = MUC_USER_NS; - XmlSubNode item(x, "item"); - item["affiliation"] = affiliation; - item["role"] = role; - } - this->send_stanza(presence); -} - -void XmppComponent::send_version(const std::string& id, const std::string& jid_to, const std::string& jid_from, - const std::string& version) -{ - Stanza iq("iq"); - iq["type"] = "result"; - iq["id"] = id; - iq["to"] = jid_to; - iq["from"] = jid_from; - { - XmlSubNode query(iq, "query"); - query["xmlns"] = VERSION_NS; - if (version.empty()) - { - { - XmlSubNode name(query, "name"); - name.set_inner("biboumi"); - } - { - XmlSubNode version(query, "version"); - version.set_inner(SOFTWARE_VERSION); - } - { - XmlSubNode os(query, "os"); - os.set_inner(utils::get_system_name()); - } - } - else - { - XmlSubNode name(query, "name"); - name.set_inner(version); - } - } - this->send_stanza(iq); -} - -void XmppComponent::send_adhoc_commands_list(const std::string& id, const std::string& requester_jid, - const std::string& from_jid, - const bool with_admin_only, const AdhocCommandsHandler& adhoc_handler) -{ - Stanza iq("iq"); - { - iq["type"] = "result"; - iq["id"] = id; - iq["to"] = requester_jid; - iq["from"] = from_jid; - XmlSubNode query(iq, "query"); - query["xmlns"] = DISCO_ITEMS_NS; - query["node"] = ADHOC_NS; - for (const auto &kv: adhoc_handler.get_commands()) - { - if (kv.second.is_admin_only() && !with_admin_only) - continue; - XmlSubNode item(query, "item"); - item["jid"] = from_jid; - item["node"] = kv.first; - item["name"] = kv.second.name; - } - } - this->send_stanza(iq); -} - -void XmppComponent::send_iq_version_request(const std::string& from, - const std::string& jid_to) -{ - Stanza iq("iq"); - { - iq["type"] = "get"; - iq["id"] = "version_"s + XmppComponent::next_id(); - iq["from"] = from + "@" + this->served_hostname; - iq["to"] = jid_to; - XmlSubNode query(iq, "query"); - query["xmlns"] = VERSION_NS; - } - this->send_stanza(iq); -} - -void XmppComponent::send_iq_result_full_jid(const std::string& id, const std::string& to_jid, const std::string& from_full_jid) -{ - Stanza iq("iq"); - iq["from"] = from_full_jid; - iq["to"] = to_jid; - iq["id"] = id; - iq["type"] = "result"; - this->send_stanza(iq); -} - -void XmppComponent::send_iq_result(const std::string& id, const std::string& to_jid, const std::string& from_local_part) -{ - Stanza iq("iq"); - if (!from_local_part.empty()) - iq["from"] = from_local_part + "@" + this->served_hostname; - else - iq["from"] = this->served_hostname; - iq["to"] = to_jid; - iq["id"] = id; - iq["type"] = "result"; - this->send_stanza(iq); -} - -std::string XmppComponent::next_id() -{ - char uuid_str[37]; - uuid_t uuid; - uuid_generate(uuid); - uuid_unparse(uuid, uuid_str); - return uuid_str; -} -- cgit v1.2.3