From 210accbcb135a9551cb56e5197a3a5acf8d15f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= Date: Mon, 1 Nov 2010 15:50:17 +0100 Subject: Added JIDDiscoInfoResponder + Added "to" parameter to responder callback. diff --git a/Swiften/Disco/DiscoInfoResponder.cpp b/Swiften/Disco/DiscoInfoResponder.cpp index 2e686c7..0254ad9 100644 --- a/Swiften/Disco/DiscoInfoResponder.cpp +++ b/Swiften/Disco/DiscoInfoResponder.cpp @@ -28,7 +28,7 @@ void DiscoInfoResponder::setDiscoInfo(const String& node, const DiscoInfo& info) nodeInfo_[node] = newInfo; } -bool DiscoInfoResponder::handleGetRequest(const JID& from, const String& id, boost::shared_ptr info) { +bool DiscoInfoResponder::handleGetRequest(const JID& from, const JID&, const String& id, boost::shared_ptr info) { if (info->getNode().isEmpty()) { sendResponse(from, id, boost::shared_ptr(new DiscoInfo(info_))); } diff --git a/Swiften/Disco/DiscoInfoResponder.h b/Swiften/Disco/DiscoInfoResponder.h index 0dc1172..3861ffd 100644 --- a/Swiften/Disco/DiscoInfoResponder.h +++ b/Swiften/Disco/DiscoInfoResponder.h @@ -23,7 +23,7 @@ namespace Swift { void setDiscoInfo(const String& node, const DiscoInfo& info); private: - virtual bool handleGetRequest(const JID& from, const String& id, boost::shared_ptr payload); + virtual bool handleGetRequest(const JID& from, const JID& to, const String& id, boost::shared_ptr payload); private: DiscoInfo info_; diff --git a/Swiften/Disco/JIDDiscoInfoResponder.cpp b/Swiften/Disco/JIDDiscoInfoResponder.cpp new file mode 100644 index 0000000..311447f --- /dev/null +++ b/Swiften/Disco/JIDDiscoInfoResponder.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/Disco/JIDDiscoInfoResponder.h" +#include "Swiften/Queries/IQRouter.h" +#include "Swiften/Elements/DiscoInfo.h" + +namespace Swift { + +JIDDiscoInfoResponder::JIDDiscoInfoResponder(IQRouter* router) : GetResponder(router) { +} + +void JIDDiscoInfoResponder::clearDiscoInfo(const JID& jid) { + info.erase(jid); +} + +void JIDDiscoInfoResponder::setDiscoInfo(const JID& jid, const DiscoInfo& discoInfo) { + JIDDiscoInfoMap::iterator i = info.insert(std::make_pair(jid, JIDDiscoInfo())).first; + i->second.discoInfo = discoInfo; +} + +void JIDDiscoInfoResponder::setDiscoInfo(const JID& jid, const String& node, const DiscoInfo& discoInfo) { + JIDDiscoInfoMap::iterator i = info.insert(std::make_pair(jid, JIDDiscoInfo())).first; + DiscoInfo newInfo(discoInfo); + newInfo.setNode(node); + i->second.nodeDiscoInfo[node] = newInfo; +} + +bool JIDDiscoInfoResponder::handleGetRequest(const JID& from, const JID& to, const String& id, boost::shared_ptr discoInfo) { + JIDDiscoInfoMap::const_iterator i = info.find(to); + if (i != info.end()) { + if (discoInfo->getNode().isEmpty()) { + sendResponse(from, to, id, boost::shared_ptr(new DiscoInfo(i->second.discoInfo))); + } + else { + std::map::const_iterator j = i->second.nodeDiscoInfo.find(discoInfo->getNode()); + if (j != i->second.nodeDiscoInfo.end()) { + sendResponse(from, to, id, boost::shared_ptr(new DiscoInfo(j->second))); + } + else { + sendError(from, to, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); + } + } + } + else { + sendError(from, to, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); + } + return true; +} + +} diff --git a/Swiften/Disco/JIDDiscoInfoResponder.h b/Swiften/Disco/JIDDiscoInfoResponder.h new file mode 100644 index 0000000..aac43de --- /dev/null +++ b/Swiften/Disco/JIDDiscoInfoResponder.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include + +#include "Swiften/Queries/GetResponder.h" +#include "Swiften/Elements/DiscoInfo.h" +#include "Swiften/JID/JID.h" + +namespace Swift { + class IQRouter; + + class JIDDiscoInfoResponder : public GetResponder { + public: + JIDDiscoInfoResponder(IQRouter* router); + + void clearDiscoInfo(const JID& jid); + void setDiscoInfo(const JID& jid, const DiscoInfo& info); + void setDiscoInfo(const JID& jid, const String& node, const DiscoInfo& info); + + private: + virtual bool handleGetRequest(const JID& from, const JID& to, const String& id, boost::shared_ptr payload); + + private: + struct JIDDiscoInfo { + DiscoInfo discoInfo; + std::map nodeDiscoInfo; + }; + typedef std::map JIDDiscoInfoMap; + JIDDiscoInfoMap info; + }; +} diff --git a/Swiften/Disco/SConscript b/Swiften/Disco/SConscript index a791946..ef2bd1b 100644 --- a/Swiften/Disco/SConscript +++ b/Swiften/Disco/SConscript @@ -9,5 +9,6 @@ objects = swiften_env.StaticObject([ "CapsFileStorage.cpp", "ClientDiscoManager.cpp", "DiscoInfoResponder.cpp", + "JIDDiscoInfoResponder.cpp", ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Disco/UnitTest/DiscoInfoResponderTest.cpp b/Swiften/Disco/UnitTest/DiscoInfoResponderTest.cpp index a9e85c0..1b2e54b 100644 --- a/Swiften/Disco/UnitTest/DiscoInfoResponderTest.cpp +++ b/Swiften/Disco/UnitTest/DiscoInfoResponderTest.cpp @@ -78,14 +78,16 @@ class DiscoInfoResponderTest : public CppUnit::TestFixture { void testHandleRequest_GetInvalidNodeInfo() { DiscoInfoResponder testling(router_); - boost::shared_ptr query(new DiscoInfo()); query->setNode("bar-node"); channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); + testling.start(); CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); boost::shared_ptr payload(channel_->iqs_[0]->getPayload()); CPPUNIT_ASSERT(payload); + + testling.stop(); } private: diff --git a/Swiften/Disco/UnitTest/JIDDiscoInfoResponderTest.cpp b/Swiften/Disco/UnitTest/JIDDiscoInfoResponderTest.cpp new file mode 100644 index 0000000..03a3ee8 --- /dev/null +++ b/Swiften/Disco/UnitTest/JIDDiscoInfoResponderTest.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include +#include +#include + +#include "Swiften/Disco/JIDDiscoInfoResponder.h" +#include "Swiften/Queries/IQRouter.h" +#include "Swiften/Queries/DummyIQChannel.h" + +using namespace Swift; + +class JIDDiscoInfoResponderTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(JIDDiscoInfoResponderTest); + CPPUNIT_TEST(testHandleRequest_GetToplevelInfo); + CPPUNIT_TEST(testHandleRequest_GetNodeInfo); + CPPUNIT_TEST(testHandleRequest_GetInvalidNodeInfo); + CPPUNIT_TEST(testHandleRequest_GetUnknownJID); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + channel_ = new DummyIQChannel(); + router_ = new IQRouter(channel_); + } + + void tearDown() { + delete router_; + delete channel_; + } + + void testHandleRequest_GetToplevelInfo() { + JIDDiscoInfoResponder testling(router_); + testling.start(); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); + + boost::shared_ptr query(new DiscoInfo()); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); + boost::shared_ptr payload(channel_->iqs_[0]->getPayload()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(String(""), payload->getNode()); + CPPUNIT_ASSERT(payload->hasFeature("foo")); + + testling.stop(); + } + + void testHandleRequest_GetNodeInfo() { + JIDDiscoInfoResponder testling(router_); + testling.start(); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); + DiscoInfo discoInfoBar; + discoInfoBar.addFeature("bar"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), "bar-node", discoInfoBar); + + boost::shared_ptr query(new DiscoInfo()); + query->setNode("bar-node"); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); + boost::shared_ptr payload(channel_->iqs_[0]->getPayload()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(String("bar-node"), payload->getNode()); + CPPUNIT_ASSERT(payload->hasFeature("bar")); + + testling.stop(); + } + + void testHandleRequest_GetInvalidNodeInfo() { + JIDDiscoInfoResponder testling(router_); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); + testling.start(); + + boost::shared_ptr query(new DiscoInfo()); + query->setNode("bar-node"); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); + boost::shared_ptr payload(channel_->iqs_[0]->getPayload()); + CPPUNIT_ASSERT(payload); + + testling.stop(); + } + + void testHandleRequest_GetUnknownJID() { + JIDDiscoInfoResponder testling(router_); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); + testling.start(); + + boost::shared_ptr query(new DiscoInfo()); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/fum"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast(channel_->iqs_.size())); + boost::shared_ptr payload(channel_->iqs_[0]->getPayload()); + CPPUNIT_ASSERT(payload); + + testling.stop(); + } + + private: + IQRouter* router_; + DummyIQChannel* channel_; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(JIDDiscoInfoResponderTest); diff --git a/Swiften/Elements/IQ.cpp b/Swiften/Elements/IQ.cpp index 9df6ef4..abf32e9 100644 --- a/Swiften/Elements/IQ.cpp +++ b/Swiften/Elements/IQ.cpp @@ -21,8 +21,7 @@ boost::shared_ptr IQ::createRequest( return iq; } -boost::shared_ptr IQ::createResult( - const JID& to, const String& id, boost::shared_ptr payload) { +boost::shared_ptr IQ::createResult(const JID& to, const String& id, boost::shared_ptr payload) { boost::shared_ptr iq(new IQ(Result)); iq->setTo(to); iq->setID(id); @@ -32,6 +31,17 @@ boost::shared_ptr IQ::createResult( return iq; } +boost::shared_ptr IQ::createResult(const JID& to, const JID& from, const String& id, boost::shared_ptr payload) { + boost::shared_ptr iq(new IQ(Result)); + iq->setTo(to); + iq->setFrom(from); + iq->setID(id); + if (payload) { + iq->addPayload(payload); + } + return iq; +} + boost::shared_ptr IQ::createError(const JID& to, const String& id, ErrorPayload::Condition condition, ErrorPayload::Type type) { boost::shared_ptr iq(new IQ(IQ::Error)); iq->setTo(to); @@ -40,4 +50,13 @@ boost::shared_ptr IQ::createError(const JID& to, const String& id, ErrorPayl return iq; } +boost::shared_ptr IQ::createError(const JID& to, const JID& from, const String& id, ErrorPayload::Condition condition, ErrorPayload::Type type) { + boost::shared_ptr iq(new IQ(IQ::Error)); + iq->setTo(to); + iq->setFrom(from); + iq->setID(id); + iq->addPayload(boost::shared_ptr(new Swift::ErrorPayload(condition, type))); + return iq; +} + } diff --git a/Swiften/Elements/IQ.h b/Swiften/Elements/IQ.h index e15de24..007dda2 100644 --- a/Swiften/Elements/IQ.h +++ b/Swiften/Elements/IQ.h @@ -32,8 +32,19 @@ namespace Swift { const JID& to, const String& id, boost::shared_ptr payload = boost::shared_ptr()); + static boost::shared_ptr createResult( + const JID& to, + const JID& from, + const String& id, + boost::shared_ptr payload = boost::shared_ptr()); + static boost::shared_ptr createError( + const JID& to, + const String& id, + ErrorPayload::Condition condition = ErrorPayload::BadRequest, + ErrorPayload::Type type = ErrorPayload::Cancel); static boost::shared_ptr createError( const JID& to, + const JID& from, const String& id, ErrorPayload::Condition condition = ErrorPayload::BadRequest, ErrorPayload::Type type = ErrorPayload::Cancel); diff --git a/Swiften/Presence/PayloadAddingPresenceSender.h b/Swiften/Presence/PayloadAddingPresenceSender.h index 5602ebe..ae82970 100644 --- a/Swiften/Presence/PayloadAddingPresenceSender.h +++ b/Swiften/Presence/PayloadAddingPresenceSender.h @@ -15,7 +15,7 @@ namespace Swift { /** * This presence sender adds payloads to outgoing presences. * - * + * This class isn't meant to be used with directed presence. */ class PayloadAddingPresenceSender : public PresenceSender { public: @@ -24,6 +24,12 @@ namespace Swift { void sendPresence(Presence::ref); bool isAvailable() const; + /** + * Sets the payload to be added to outgoing presences. + * If initial presence has been sent, this will resend the last sent presence + * with an updated payload. Initial presence is reset when unavailable presence is + * sent. + */ void setPayload(Payload::ref); private: diff --git a/Swiften/Queries/GetResponder.h b/Swiften/Queries/GetResponder.h index 3324859..2201b95 100644 --- a/Swiften/Queries/GetResponder.h +++ b/Swiften/Queries/GetResponder.h @@ -15,6 +15,6 @@ namespace Swift { GetResponder(IQRouter* router) : Responder(router) {} private: - virtual bool handleSetRequest(const JID&, const String&, boost::shared_ptr) { return false; } + virtual bool handleSetRequest(const JID&, const JID&, const String&, boost::shared_ptr) { return false; } }; } diff --git a/Swiften/Queries/Responder.h b/Swiften/Queries/Responder.h index 2333b5f..322ba60 100644 --- a/Swiften/Queries/Responder.h +++ b/Swiften/Queries/Responder.h @@ -57,14 +57,14 @@ namespace Swift { * * This method is implemented in the concrete subclasses. */ - virtual bool handleGetRequest(const JID& from, const String& id, boost::shared_ptr payload) = 0; + virtual bool handleGetRequest(const JID& from, const JID& to, const String& id, boost::shared_ptr payload) = 0; /** * Handle an incoming IQ-Set request containing a payload of class PAYLOAD_TYPE. * * This method is implemented in the concrete subclasses. */ - virtual bool handleSetRequest(const JID& from, const String& id, boost::shared_ptr payload) = 0; + virtual bool handleSetRequest(const JID& from, const JID& to, const String& id, boost::shared_ptr payload) = 0; /** * Convenience function for sending an IQ response. @@ -74,12 +74,26 @@ namespace Swift { } /** + * Convenience function for sending an IQ response, with a specific from address. + */ + void sendResponse(const JID& to, const JID& from, const String& id, boost::shared_ptr payload) { + router_->sendIQ(IQ::createResult(to, from, id, payload)); + } + + /** * Convenience function for responding with an error. */ void sendError(const JID& to, const String& id, ErrorPayload::Condition condition, ErrorPayload::Type type) { router_->sendIQ(IQ::createError(to, id, condition, type)); } + /** + * Convenience function for responding with an error from a specific from address. + */ + void sendError(const JID& to, const JID& from, const String& id, ErrorPayload::Condition condition, ErrorPayload::Type type) { + router_->sendIQ(IQ::createError(to, from, id, condition, type)); + } + private: virtual bool handleIQ(boost::shared_ptr iq) { if (iq->getType() == IQ::Set || iq->getType() == IQ::Get) { @@ -87,10 +101,10 @@ namespace Swift { if (payload) { bool result; if (iq->getType() == IQ::Set) { - result = handleSetRequest(iq->getFrom(), iq->getID(), payload); + result = handleSetRequest(iq->getFrom(), iq->getTo(), iq->getID(), payload); } else { - result = handleGetRequest(iq->getFrom(), iq->getID(), payload); + result = handleGetRequest(iq->getFrom(), iq->getTo(), iq->getID(), payload); } if (!result) { router_->sendIQ(IQ::createError(iq->getFrom(), iq->getID(), ErrorPayload::NotAllowed, ErrorPayload::Cancel)); diff --git a/Swiften/Queries/Responders/SoftwareVersionResponder.cpp b/Swiften/Queries/Responders/SoftwareVersionResponder.cpp index b2e7273..cc58114 100644 --- a/Swiften/Queries/Responders/SoftwareVersionResponder.cpp +++ b/Swiften/Queries/Responders/SoftwareVersionResponder.cpp @@ -17,7 +17,7 @@ void SoftwareVersionResponder::setVersion(const String& client, const String& ve this->version = version; } -bool SoftwareVersionResponder::handleGetRequest(const JID& from, const String& id, boost::shared_ptr) { +bool SoftwareVersionResponder::handleGetRequest(const JID& from, const JID&, const String& id, boost::shared_ptr) { sendResponse(from, id, boost::shared_ptr(new SoftwareVersion(client, version))); return true; } diff --git a/Swiften/Queries/Responders/SoftwareVersionResponder.h b/Swiften/Queries/Responders/SoftwareVersionResponder.h index 7242b4b..9da82b0 100644 --- a/Swiften/Queries/Responders/SoftwareVersionResponder.h +++ b/Swiften/Queries/Responders/SoftwareVersionResponder.h @@ -19,7 +19,7 @@ namespace Swift { void setVersion(const String& client, const String& version); private: - virtual bool handleGetRequest(const JID& from, const String& id, boost::shared_ptr payload); + virtual bool handleGetRequest(const JID& from, const JID& to, const String& id, boost::shared_ptr payload); private: String client; diff --git a/Swiften/Queries/SetResponder.h b/Swiften/Queries/SetResponder.h index 345328c..a04be64 100644 --- a/Swiften/Queries/SetResponder.h +++ b/Swiften/Queries/SetResponder.h @@ -15,6 +15,6 @@ namespace Swift { SetResponder(IQRouter* router) : Responder(router) {} private: - virtual bool handleGetRequest(const JID&, const String&, boost::shared_ptr) { return false; } + virtual bool handleGetRequest(const JID&, const JID&, const String&, boost::shared_ptr) { return false; } }; } diff --git a/Swiften/Queries/UnitTest/ResponderTest.cpp b/Swiften/Queries/UnitTest/ResponderTest.cpp index 9824c98..aba2cb9 100644 --- a/Swiften/Queries/UnitTest/ResponderTest.cpp +++ b/Swiften/Queries/UnitTest/ResponderTest.cpp @@ -131,13 +131,13 @@ class ResponderTest : public CppUnit::TestFixture public: MyResponder(IQRouter* router) : Responder(router), getRequestResponse_(true), setRequestResponse_(true) {} - virtual bool handleGetRequest(const JID& from, const String& id, boost::shared_ptr payload) { + virtual bool handleGetRequest(const JID& from, const JID& to, const String& id, boost::shared_ptr payload) { CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), from); CPPUNIT_ASSERT_EQUAL(String("myid"), id); getPayloads_.push_back(payload); return getRequestResponse_; } - virtual bool handleSetRequest(const JID& from, const String& id, boost::shared_ptr payload) { + virtual bool handleSetRequest(const JID& from, const JID& to, const String& id, boost::shared_ptr payload) { CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), from); CPPUNIT_ASSERT_EQUAL(String("myid"), id); setPayloads_.push_back(payload); diff --git a/Swiften/Roster/RosterPushResponder.h b/Swiften/Roster/RosterPushResponder.h index 48111a7..ea7cff5 100644 --- a/Swiften/Roster/RosterPushResponder.h +++ b/Swiften/Roster/RosterPushResponder.h @@ -20,7 +20,7 @@ namespace Swift { boost::signal)> onRosterReceived; private: - virtual bool handleSetRequest(const JID& from, const String& id, boost::shared_ptr payload) { + virtual bool handleSetRequest(const JID& from, const JID&, const String& id, boost::shared_ptr payload) { onRosterReceived(payload); sendResponse(from, id, boost::shared_ptr()); return true; diff --git a/Swiften/SConscript b/Swiften/SConscript index 9744f45..6b889e8 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -170,6 +170,8 @@ if env["SCONS_STAGE"] == "build" : File("Disco/UnitTest/CapsInfoGeneratorTest.cpp"), File("Disco/UnitTest/CapsManagerTest.cpp"), File("Disco/UnitTest/EntityCapsManagerTest.cpp"), + File("Disco/UnitTest/JIDDiscoInfoResponderTest.cpp"), + File("Disco/UnitTest/DiscoInfoResponderTest.cpp"), File("Elements/UnitTest/IQTest.cpp"), File("Elements/UnitTest/StanzaTest.cpp"), File("Elements/UnitTest/FormTest.cpp"), @@ -221,7 +223,6 @@ if env["SCONS_STAGE"] == "build" : File("Presence/UnitTest/DirectedPresenceSenderTest.cpp"), File("Presence/UnitTest/PayloadAddingPresenceSenderTest.cpp"), File("Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp"), - File("Disco/UnitTest/DiscoInfoResponderTest.cpp"), File("Queries/UnitTest/IQRouterTest.cpp"), File("Queries/UnitTest/RequestTest.cpp"), File("Queries/UnitTest/ResponderTest.cpp"), -- cgit v0.10.2-6-g49f6