summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/Client')
-rw-r--r--Swiften/Client/Client.cpp50
-rw-r--r--Swiften/Client/Client.h12
-rw-r--r--Swiften/Client/ClientOptions.h58
-rw-r--r--Swiften/Client/ClientSession.cpp99
-rw-r--r--Swiften/Client/ClientSession.h21
-rw-r--r--Swiften/Client/ClientSessionStanzaChannel.cpp3
-rw-r--r--Swiften/Client/ClientSessionStanzaChannel.h12
-rw-r--r--Swiften/Client/ClientXMLTracer.cpp31
-rw-r--r--Swiften/Client/ClientXMLTracer.h21
-rw-r--r--Swiften/Client/CoreClient.cpp100
-rw-r--r--Swiften/Client/CoreClient.h107
-rw-r--r--Swiften/Client/DummyStanzaChannel.h18
-rw-r--r--Swiften/Client/FileStorages.cpp39
-rw-r--r--Swiften/Client/FileStorages.h50
-rw-r--r--Swiften/Client/MemoryStorages.cpp16
-rw-r--r--Swiften/Client/MemoryStorages.h4
-rw-r--r--Swiften/Client/NickResolver.cpp8
-rw-r--r--Swiften/Client/NickResolver.h6
-rw-r--r--Swiften/Client/StanzaChannel.h8
-rw-r--r--Swiften/Client/Storages.cpp12
-rw-r--r--Swiften/Client/Storages.h4
-rw-r--r--Swiften/Client/UnitTest/ClientSessionTest.cpp89
-rw-r--r--Swiften/Client/UnitTest/NickResolverTest.cpp14
23 files changed, 451 insertions, 331 deletions
diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp
index 7918c46..c53bcaf 100644
--- a/Swiften/Client/Client.cpp
+++ b/Swiften/Client/Client.cpp
@@ -4,38 +4,39 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/Client/Client.h"
-
-#include "Swiften/Queries/Responders/SoftwareVersionResponder.h"
-#include "Swiften/Roster/XMPPRosterImpl.h"
-#include "Swiften/Roster/XMPPRosterController.h"
-#include "Swiften/Presence/PresenceOracle.h"
-#include "Swiften/Presence/StanzaChannelPresenceSender.h"
-#include "Swiften/Presence/DirectedPresenceSender.h"
-#include "Swiften/MUC/MUCRegistry.h"
-#include "Swiften/MUC/MUCManager.h"
-#include "Swiften/Client/MemoryStorages.h"
-#include "Swiften/VCards/VCardManager.h"
-#include "Swiften/VCards/VCardManager.h"
-#include "Swiften/Avatars/AvatarManagerImpl.h"
-#include "Swiften/Disco/CapsManager.h"
-#include "Swiften/Disco/EntityCapsManager.h"
-#include "Swiften/Disco/ClientDiscoManager.h"
-#include "Swiften/Client/NickResolver.h"
-#include "Swiften/Presence/SubscriptionManager.h"
-#include "Swiften/TLS/BlindCertificateTrustChecker.h"
+#include <Swiften/Client/Client.h>
+
+#include <Swiften/Queries/Responders/SoftwareVersionResponder.h>
+#include <Swiften/Roster/XMPPRosterImpl.h>
+#include <Swiften/Roster/XMPPRosterController.h>
+#include <Swiften/Presence/PresenceOracle.h>
+#include <Swiften/Presence/StanzaChannelPresenceSender.h>
+#include <Swiften/Presence/DirectedPresenceSender.h>
+#include <Swiften/MUC/MUCRegistry.h>
+#include <Swiften/MUC/MUCManager.h>
+#include <Swiften/Client/MemoryStorages.h>
+#include <Swiften/VCards/VCardManager.h>
+#include <Swiften/VCards/VCardManager.h>
+#include <Swiften/Avatars/AvatarManagerImpl.h>
+#include <Swiften/Disco/CapsManager.h>
+#include <Swiften/Disco/EntityCapsManager.h>
+#include <Swiften/Disco/ClientDiscoManager.h>
+#include <Swiften/Client/NickResolver.h>
+#include <Swiften/Presence/SubscriptionManager.h>
+#include <Swiften/TLS/BlindCertificateTrustChecker.h>
#include <Swiften/Client/NickManagerImpl.h>
+#include <Swiften/Client/ClientSession.h>
namespace Swift {
-Client::Client(const JID& jid, const std::string& password, NetworkFactories* networkFactories, Storages* storages) : CoreClient(jid, password, networkFactories), storages(storages) {
+Client::Client(const JID& jid, const SafeString& password, NetworkFactories* networkFactories, Storages* storages) : CoreClient(jid, password, networkFactories), storages(storages) {
memoryStorages = new MemoryStorages();
softwareVersionResponder = new SoftwareVersionResponder(getIQRouter());
softwareVersionResponder->start();
roster = new XMPPRosterImpl();
- rosterController = new XMPPRosterController(getIQRouter(), roster);
+ rosterController = new XMPPRosterController(getIQRouter(), roster, getStorages()->getRosterStorage());
subscriptionManager = new SubscriptionManager(getStanzaChannel());
@@ -98,6 +99,11 @@ void Client::setSoftwareVersion(const std::string& name, const std::string& vers
}
void Client::requestRoster() {
+ // FIXME: We should set this once when the session is finished, but there
+ // is currently no callback for this
+ if (getSession()) {
+ rosterController->setUseVersioning(getSession()->getRosterVersioningSupported());
+ }
rosterController->requestRoster();
}
diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h
index 083b8a0..08289a5 100644
--- a/Swiften/Client/Client.h
+++ b/Swiften/Client/Client.h
@@ -6,7 +6,9 @@
#pragma once
-#include "Swiften/Client/CoreClient.h"
+#include <Swiften/Client/CoreClient.h>
+
+#include <Swiften/Base/SafeString.h>
namespace Swift {
class SoftwareVersionResponder;
@@ -47,7 +49,7 @@ namespace Swift {
* this is NULL,
* all data will be stored in memory (and be lost on shutdown)
*/
- Client(const JID& jid, const std::string& password, NetworkFactories* networkFactories, Storages* storages = NULL);
+ Client(const JID& jid, const SafeString& password, NetworkFactories* networkFactories, Storages* storages = NULL);
~Client();
@@ -85,12 +87,12 @@ namespace Swift {
/**
* Returns the last received presence for the given (full) JID.
*/
- Presence::ref getLastPresence(const JID& jid) const;
+ boost::shared_ptr<Presence> getLastPresence(const JID& jid) const;
/**
* Returns the presence with the highest priority received for the given JID.
*/
- Presence::ref getHighestPriorityPresence(const JID& bareJID) const;
+ boost::shared_ptr<Presence> getHighestPriorityPresence(const JID& bareJID) const;
PresenceOracle* getPresenceOracle() const {
return presenceOracle;
@@ -142,7 +144,7 @@ namespace Swift {
/**
* This signal is emitted when a JID changes presence.
*/
- boost::signal<void (Presence::ref)> onPresenceChange;
+ boost::signal<void (boost::shared_ptr<Presence>)> onPresenceChange;
private:
Storages* getStorages() const;
diff --git a/Swiften/Client/ClientOptions.h b/Swiften/Client/ClientOptions.h
new file mode 100644
index 0000000..0766402
--- /dev/null
+++ b/Swiften/Client/ClientOptions.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+namespace Swift {
+ struct ClientOptions {
+ enum UseTLS {
+ NeverUseTLS,
+ UseTLSWhenAvailable
+ };
+
+ ClientOptions() : useStreamCompression(true), useTLS(UseTLSWhenAvailable), allowPLAINWithoutTLS(false), useStreamResumption(false), forgetPassword(false) {
+ }
+
+ /**
+ * Whether ZLib stream compression should be used when available.
+ *
+ * Default: true
+ */
+ bool useStreamCompression;
+
+ /**
+ * Sets whether TLS encryption should be used.
+ *
+ * Default: UseTLSWhenAvailable
+ */
+ UseTLS useTLS;
+
+ /**
+ * Sets whether plaintext authentication is
+ * allowed over non-TLS-encrypted connections.
+ *
+ * Default: false
+ */
+ bool allowPLAINWithoutTLS;
+
+ /**
+ * Use XEP-196 stream resumption when available.
+ *
+ * Default: false
+ */
+ bool useStreamResumption;
+
+ /**
+ * Forget the password once it's used.
+ * This makes the Client useless after the first login attempt.
+ *
+ * FIXME: This is a temporary workaround.
+ *
+ * Default: false
+ */
+ bool forgetPassword;
+ };
+}
diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp
index e1c1d8e..8945e9a 100644
--- a/Swiften/Client/ClientSession.cpp
+++ b/Swiften/Client/ClientSession.cpp
@@ -4,41 +4,42 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/Client/ClientSession.h"
+#include <Swiften/Client/ClientSession.h>
#include <boost/bind.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid_generators.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
-#include "Swiften/Elements/ProtocolHeader.h"
-#include "Swiften/Elements/StreamFeatures.h"
-#include "Swiften/Elements/StreamError.h"
-#include "Swiften/Elements/StartTLSRequest.h"
-#include "Swiften/Elements/StartTLSFailure.h"
-#include "Swiften/Elements/TLSProceed.h"
-#include "Swiften/Elements/AuthRequest.h"
-#include "Swiften/Elements/AuthSuccess.h"
-#include "Swiften/Elements/AuthFailure.h"
-#include "Swiften/Elements/AuthChallenge.h"
-#include "Swiften/Elements/AuthResponse.h"
-#include "Swiften/Elements/Compressed.h"
-#include "Swiften/Elements/CompressFailure.h"
-#include "Swiften/Elements/CompressRequest.h"
-#include "Swiften/Elements/EnableStreamManagement.h"
-#include "Swiften/Elements/StreamManagementEnabled.h"
-#include "Swiften/Elements/StreamManagementFailed.h"
-#include "Swiften/Elements/StartSession.h"
-#include "Swiften/Elements/StanzaAck.h"
-#include "Swiften/Elements/StanzaAckRequest.h"
-#include "Swiften/Elements/IQ.h"
-#include "Swiften/Elements/ResourceBind.h"
-#include "Swiften/SASL/PLAINClientAuthenticator.h"
-#include "Swiften/SASL/SCRAMSHA1ClientAuthenticator.h"
-#include "Swiften/SASL/DIGESTMD5ClientAuthenticator.h"
-#include "Swiften/Session/SessionStream.h"
-#include "Swiften/TLS/CertificateTrustChecker.h"
-#include "Swiften/TLS/ServerIdentityVerifier.h"
+#include <Swiften/Elements/ProtocolHeader.h>
+#include <Swiften/Elements/StreamFeatures.h>
+#include <Swiften/Elements/StreamError.h>
+#include <Swiften/Elements/StartTLSRequest.h>
+#include <Swiften/Elements/StartTLSFailure.h>
+#include <Swiften/Elements/TLSProceed.h>
+#include <Swiften/Elements/AuthRequest.h>
+#include <Swiften/Elements/AuthSuccess.h>
+#include <Swiften/Elements/AuthFailure.h>
+#include <Swiften/Elements/AuthChallenge.h>
+#include <Swiften/Elements/AuthResponse.h>
+#include <Swiften/Elements/Compressed.h>
+#include <Swiften/Elements/CompressFailure.h>
+#include <Swiften/Elements/CompressRequest.h>
+#include <Swiften/Elements/EnableStreamManagement.h>
+#include <Swiften/Elements/StreamManagementEnabled.h>
+#include <Swiften/Elements/StreamManagementFailed.h>
+#include <Swiften/Elements/StartSession.h>
+#include <Swiften/Elements/StanzaAck.h>
+#include <Swiften/Elements/StanzaAckRequest.h>
+#include <Swiften/Elements/IQ.h>
+#include <Swiften/Elements/ResourceBind.h>
+#include <Swiften/SASL/PLAINClientAuthenticator.h>
+#include <Swiften/SASL/SCRAMSHA1ClientAuthenticator.h>
+#include <Swiften/SASL/DIGESTMD5ClientAuthenticator.h>
+#include <Swiften/Session/SessionStream.h>
+#include <Swiften/TLS/CertificateTrustChecker.h>
+#include <Swiften/TLS/ServerIdentityVerifier.h>
namespace Swift {
@@ -54,6 +55,7 @@ ClientSession::ClientSession(
needSessionStart(false),
needResourceBind(false),
needAcking(false),
+ rosterVersioningSupported(false),
authenticator(NULL),
certificateTrustChecker(NULL) {
}
@@ -173,17 +175,17 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
if (streamFeatures->hasStartTLS() && stream->supportsTLSEncryption() && useTLS != NeverUseTLS) {
state = WaitingForEncrypt;
- stream->writeElement(boost::shared_ptr<StartTLSRequest>(new StartTLSRequest()));
+ stream->writeElement(boost::make_shared<StartTLSRequest>());
}
else if (useStreamCompression && streamFeatures->hasCompressionMethod("zlib")) {
state = Compressing;
- stream->writeElement(boost::shared_ptr<CompressRequest>(new CompressRequest("zlib")));
+ stream->writeElement(boost::make_shared<CompressRequest>("zlib"));
}
else if (streamFeatures->hasAuthenticationMechanisms()) {
if (stream->hasTLSCertificate()) {
if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) {
state = Authenticating;
- stream->writeElement(boost::shared_ptr<Element>(new AuthRequest("EXTERNAL", "")));
+ stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray("")));
}
else {
finishSession(Error::TLSClientCertificateError);
@@ -191,7 +193,7 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
}
else if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) {
state = Authenticating;
- stream->writeElement(boost::shared_ptr<Element>(new AuthRequest("EXTERNAL", "")));
+ stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray("")));
}
else if (streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1") || streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS")) {
std::ostringstream s;
@@ -223,6 +225,7 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
}
else {
// Start the session
+ rosterVersioningSupported = streamFeatures->hasRosterVersioning();
stream->setWhitespacePingEnabled(true);
needSessionStart = streamFeatures->hasSession();
needResourceBind = streamFeatures->hasResourceBind();
@@ -247,10 +250,10 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
finishSession(Error::CompressionFailedError);
}
else if (boost::dynamic_pointer_cast<StreamManagementEnabled>(element)) {
- stanzaAckRequester_ = boost::shared_ptr<StanzaAckRequester>(new StanzaAckRequester());
+ stanzaAckRequester_ = boost::make_shared<StanzaAckRequester>();
stanzaAckRequester_->onRequestAck.connect(boost::bind(&ClientSession::requestAck, shared_from_this()));
stanzaAckRequester_->onStanzaAcked.connect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1));
- stanzaAckResponder_ = boost::shared_ptr<StanzaAckResponder>(new StanzaAckResponder());
+ stanzaAckResponder_ = boost::make_shared<StanzaAckResponder>();
stanzaAckResponder_->onAck.connect(boost::bind(&ClientSession::ack, shared_from_this(), _1));
needAcking = false;
continueSessionInitialization();
@@ -263,7 +266,7 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
checkState(Authenticating);
assert(authenticator);
if (authenticator->setChallenge(challenge->getValue())) {
- stream->writeElement(boost::shared_ptr<AuthResponse>(new AuthResponse(authenticator->getResponse())));
+ stream->writeElement(boost::make_shared<AuthResponse>(authenticator->getResponse()));
}
else {
finishSession(Error::AuthenticationFailedError);
@@ -272,6 +275,8 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
else if (AuthSuccess* authSuccess = dynamic_cast<AuthSuccess*>(element.get())) {
checkState(Authenticating);
if (authenticator && !authenticator->setChallenge(authSuccess->getValue())) {
+ delete authenticator;
+ authenticator = NULL;
finishSession(Error::ServerVerificationFailedError);
}
else {
@@ -305,7 +310,7 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
void ClientSession::continueSessionInitialization() {
if (needResourceBind) {
state = BindingResource;
- boost::shared_ptr<ResourceBind> resourceBind(new ResourceBind());
+ boost::shared_ptr<ResourceBind> resourceBind(boost::make_shared<ResourceBind>());
if (!localJID.getResource().empty()) {
resourceBind->setResource(localJID.getResource());
}
@@ -313,11 +318,11 @@ void ClientSession::continueSessionInitialization() {
}
else if (needAcking) {
state = EnablingSessionManagement;
- stream->writeElement(boost::shared_ptr<EnableStreamManagement>(new EnableStreamManagement()));
+ stream->writeElement(boost::make_shared<EnableStreamManagement>());
}
else if (needSessionStart) {
state = StartingSession;
- sendStanza(IQ::createRequest(IQ::Set, JID(), "session-start", boost::shared_ptr<StartSession>(new StartSession())));
+ sendStanza(IQ::createRequest(IQ::Set, JID(), "session-start", boost::make_shared<StartSession>()));
}
else {
state = Initialized;
@@ -333,11 +338,11 @@ bool ClientSession::checkState(State state) {
return true;
}
-void ClientSession::sendCredentials(const std::string& password) {
+void ClientSession::sendCredentials(const SafeByteArray& password) {
assert(WaitingForCredentials);
state = Authenticating;
authenticator->setCredentials(localJID.getNode(), password);
- stream->writeElement(boost::shared_ptr<AuthRequest>(new AuthRequest(authenticator->getName(), authenticator->getResponse())));
+ stream->writeElement(boost::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse()));
}
void ClientSession::handleTLSEncrypted() {
@@ -354,8 +359,7 @@ void ClientSession::handleTLSEncrypted() {
continueAfterTLSEncrypted();
}
else {
- boost::shared_ptr<CertificateVerificationError> identityError(new CertificateVerificationError(CertificateVerificationError::InvalidServerIdentity));
- checkTrustOrFinish(certificate, identityError);
+ checkTrustOrFinish(certificate, boost::make_shared<CertificateVerificationError>(CertificateVerificationError::InvalidServerIdentity));
}
}
}
@@ -407,19 +411,22 @@ void ClientSession::finish() {
}
void ClientSession::finishSession(Error::Type error) {
- finishSession(boost::shared_ptr<Swift::ClientSession::Error>(new Swift::ClientSession::Error(error)));
+ finishSession(boost::make_shared<Swift::ClientSession::Error>(error));
}
void ClientSession::finishSession(boost::shared_ptr<Swift::Error> error) {
state = Finishing;
error_ = error;
assert(stream->isOpen());
+ if (stanzaAckResponder_) {
+ stanzaAckResponder_->handleAckRequestReceived();
+ }
stream->writeFooter();
stream->close();
}
void ClientSession::requestAck() {
- stream->writeElement(boost::shared_ptr<StanzaAckRequest>(new StanzaAckRequest()));
+ stream->writeElement(boost::make_shared<StanzaAckRequest>());
}
void ClientSession::handleStanzaAcked(boost::shared_ptr<Stanza> stanza) {
@@ -427,7 +434,7 @@ void ClientSession::handleStanzaAcked(boost::shared_ptr<Stanza> stanza) {
}
void ClientSession::ack(unsigned int handledStanzasCount) {
- stream->writeElement(boost::shared_ptr<StanzaAck>(new StanzaAck(handledStanzasCount)));
+ stream->writeElement(boost::make_shared<StanzaAck>(handledStanzasCount));
}
}
diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h
index 25ee694..ace9868 100644
--- a/Swiften/Client/ClientSession.h
+++ b/Swiften/Client/ClientSession.h
@@ -6,17 +6,17 @@
#pragma once
-#include "Swiften/Base/boost_bsignals.h"
+#include <Swiften/Base/boost_bsignals.h>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
-#include "Swiften/Base/Error.h"
-#include "Swiften/Session/SessionStream.h"
+#include <Swiften/Base/Error.h>
+#include <Swiften/Session/SessionStream.h>
#include <string>
-#include "Swiften/JID/JID.h"
-#include "Swiften/Elements/Element.h"
-#include "Swiften/StreamManagement/StanzaAckRequester.h"
-#include "Swiften/StreamManagement/StanzaAckResponder.h"
+#include <Swiften/JID/JID.h>
+#include <Swiften/Elements/Element.h>
+#include <Swiften/StreamManagement/StanzaAckRequester.h>
+#include <Swiften/StreamManagement/StanzaAckResponder.h>
namespace Swift {
class ClientAuthenticator;
@@ -89,6 +89,10 @@ namespace Swift {
return stanzaAckRequester_;
}
+ bool getRosterVersioningSupported() const {
+ return rosterVersioningSupported;
+ }
+
const JID& getLocalJID() const {
return localJID;
}
@@ -100,7 +104,7 @@ namespace Swift {
return getState() == Finished;
}
- void sendCredentials(const std::string& password);
+ void sendCredentials(const SafeByteArray& password);
void sendStanza(boost::shared_ptr<Stanza>);
void setCertificateTrustChecker(CertificateTrustChecker* checker) {
@@ -153,6 +157,7 @@ namespace Swift {
bool needSessionStart;
bool needResourceBind;
bool needAcking;
+ bool rosterVersioningSupported;
ClientAuthenticator* authenticator;
boost::shared_ptr<StanzaAckRequester> stanzaAckRequester_;
boost::shared_ptr<StanzaAckResponder> stanzaAckResponder_;
diff --git a/Swiften/Client/ClientSessionStanzaChannel.cpp b/Swiften/Client/ClientSessionStanzaChannel.cpp
index 6b32b3d..5dc0a42 100644
--- a/Swiften/Client/ClientSessionStanzaChannel.cpp
+++ b/Swiften/Client/ClientSessionStanzaChannel.cpp
@@ -4,9 +4,10 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/Client/ClientSessionStanzaChannel.h"
+#include <Swiften/Client/ClientSessionStanzaChannel.h>
#include <boost/bind.hpp>
+#include <iostream>
namespace Swift {
diff --git a/Swiften/Client/ClientSessionStanzaChannel.h b/Swiften/Client/ClientSessionStanzaChannel.h
index 8a56301..47fb50e 100644
--- a/Swiften/Client/ClientSessionStanzaChannel.h
+++ b/Swiften/Client/ClientSessionStanzaChannel.h
@@ -8,12 +8,12 @@
#include <boost/shared_ptr.hpp>
-#include "Swiften/Base/IDGenerator.h"
-#include "Swiften/Client/ClientSession.h"
-#include "Swiften/Client/StanzaChannel.h"
-#include "Swiften/Elements/Message.h"
-#include "Swiften/Elements/IQ.h"
-#include "Swiften/Elements/Presence.h"
+#include <Swiften/Base/IDGenerator.h>
+#include <Swiften/Client/ClientSession.h>
+#include <Swiften/Client/StanzaChannel.h>
+#include <Swiften/Elements/Message.h>
+#include <Swiften/Elements/IQ.h>
+#include <Swiften/Elements/Presence.h>
namespace Swift {
/**
diff --git a/Swiften/Client/ClientXMLTracer.cpp b/Swiften/Client/ClientXMLTracer.cpp
new file mode 100644
index 0000000..c1e398d
--- /dev/null
+++ b/Swiften/Client/ClientXMLTracer.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Client/ClientXMLTracer.h>
+
+#include <iostream>
+#include <boost/bind.hpp>
+
+namespace Swift {
+
+ClientXMLTracer::ClientXMLTracer(CoreClient* client) {
+ client->onDataRead.connect(boost::bind(&ClientXMLTracer::printData, '<', _1));
+ client->onDataWritten.connect(boost::bind(&ClientXMLTracer::printData, '>', _1));
+}
+
+void ClientXMLTracer::printData(char direction, const SafeByteArray& data) {
+ printLine(direction);
+ std::cerr << byteArrayToString(ByteArray(data.begin(), data.end())) << std::endl;
+}
+
+void ClientXMLTracer::printLine(char c) {
+ for (unsigned int i = 0; i < 80; ++i) {
+ std::cerr << c;
+ }
+ std::cerr << std::endl;
+}
+
+}
diff --git a/Swiften/Client/ClientXMLTracer.h b/Swiften/Client/ClientXMLTracer.h
index bca2a54..dd94e0e 100644
--- a/Swiften/Client/ClientXMLTracer.h
+++ b/Swiften/Client/ClientXMLTracer.h
@@ -6,29 +6,16 @@
#pragma once
-#include <boost/bind.hpp>
-
#include <Swiften/Client/CoreClient.h>
+#include <Swiften/Base/SafeByteArray.h>
namespace Swift {
class ClientXMLTracer {
public:
- ClientXMLTracer(CoreClient* client) {
- client->onDataRead.connect(boost::bind(&ClientXMLTracer::printData, '<', _1));
- client->onDataWritten.connect(boost::bind(&ClientXMLTracer::printData, '>', _1));
- }
+ ClientXMLTracer(CoreClient* client);
private:
- static void printData(char direction, const std::string& data) {
- printLine(direction);
- std::cerr << data << std::endl;
- }
-
- static void printLine(char c) {
- for (unsigned int i = 0; i < 80; ++i) {
- std::cerr << c;
- }
- std::cerr << std::endl;
- }
+ static void printData(char direction, const SafeByteArray& data);
+ static void printLine(char c);
};
}
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index 8799d4e..9aaa66b 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -4,25 +4,31 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/Client/CoreClient.h"
+#include <Swiften/Client/CoreClient.h>
#include <boost/bind.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
-#include "Swiften/Client/ClientSession.h"
-#include "Swiften/TLS/PlatformTLSFactories.h"
-#include "Swiften/TLS/CertificateVerificationError.h"
-#include "Swiften/Network/Connector.h"
-#include "Swiften/Network/NetworkFactories.h"
-#include "Swiften/TLS/PKCS12Certificate.h"
-#include "Swiften/Session/BasicSessionStream.h"
-#include "Swiften/Queries/IQRouter.h"
-#include "Swiften/Base/IDGenerator.h"
-#include "Swiften/Client/ClientSessionStanzaChannel.h"
+#include <Swiften/Base/IDGenerator.h>
#include <Swiften/Base/Log.h>
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Base/Algorithm.h>
+#include <Swiften/Client/ClientSession.h>
+#include <Swiften/TLS/PlatformTLSFactories.h>
+#include <Swiften/TLS/CertificateVerificationError.h>
+#include <Swiften/Network/ChainedConnector.h>
+#include <Swiften/Network/NetworkFactories.h>
+#include <Swiften/TLS/PKCS12Certificate.h>
+#include <Swiften/Session/BasicSessionStream.h>
+#include <Swiften/Queries/IQRouter.h>
+#include <Swiften/Client/ClientSessionStanzaChannel.h>
+#include <Swiften/Network/PlatformProxyProvider.h>
+#include <Swiften/Network/SOCKS5ProxiedConnectionFactory.h>
+#include <Swiften/Network/HTTPConnectProxiedConnectionFactory.h>
namespace Swift {
-CoreClient::CoreClient(const JID& jid, const std::string& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), useStreamCompression(true), useTLS(UseTLSWhenAvailable), disconnectRequested_(false), certificateTrustChecker(NULL) {
+CoreClient::CoreClient(const JID& jid, const SafeByteArray& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), disconnectRequested_(false), certificateTrustChecker(NULL) {
stanzaChannel_ = new ClientSessionStanzaChannel();
stanzaChannel_->onMessageReceived.connect(boost::bind(&CoreClient::handleMessageReceived, this, _1));
stanzaChannel_->onPresenceReceived.connect(boost::bind(&CoreClient::handlePresenceReceived, this, _1));
@@ -48,8 +54,9 @@ CoreClient::~CoreClient() {
delete stanzaChannel_;
}
-void CoreClient::connect() {
+void CoreClient::connect(const ClientOptions& o) {
SWIFT_LOG(debug) << "Connecting" << std::endl;
+ options = o;
connect(jid_.getDomain());
}
@@ -57,7 +64,19 @@ void CoreClient::connect(const std::string& host) {
SWIFT_LOG(debug) << "Connecting to host " << host << std::endl;
disconnectRequested_ = false;
assert(!connector_);
- connector_ = Connector::create(host, networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory());
+
+ assert(proxyConnectionFactories.empty());
+ PlatformProxyProvider proxyProvider;
+ if(proxyProvider.getSOCKS5Proxy().isValid()) {
+ proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getSOCKS5Proxy()));
+ }
+ if(proxyProvider.getHTTPConnectProxy().isValid()) {
+ proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getHTTPConnectProxy()));
+ }
+ std::vector<ConnectionFactory*> connectionFactories(proxyConnectionFactories);
+ connectionFactories.push_back(networkFactories->getConnectionFactory());
+
+ connector_ = boost::make_shared<ChainedConnector>(host, networkFactories->getDomainNameResolver(), connectionFactories, networkFactories->getTimerFactory());
connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
connector_->setTimeoutMilliseconds(60*1000);
connector_->start();
@@ -66,7 +85,15 @@ void CoreClient::connect(const std::string& host) {
void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connection) {
connector_->onConnectFinished.disconnect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
connector_.reset();
+ foreach(ConnectionFactory* f, proxyConnectionFactories) {
+ delete f;
+ }
+ proxyConnectionFactories.clear();
+
if (!connection) {
+ if (options.forgetPassword) {
+ purgePassword();
+ }
onDisconnected(disconnectRequested_ ? boost::optional<ClientError>() : boost::optional<ClientError>(ClientError::ConnectionError));
}
else {
@@ -74,7 +101,7 @@ void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connectio
connection_ = connection;
assert(!sessionStream_);
- sessionStream_ = boost::shared_ptr<BasicSessionStream>(new BasicSessionStream(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), tlsFactories->getTLSContextFactory(), networkFactories->getTimerFactory()));
+ sessionStream_ = boost::make_shared<BasicSessionStream>(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), tlsFactories->getTLSContextFactory(), networkFactories->getTimerFactory());
if (!certificate_.empty()) {
sessionStream_->setTLSCertificate(PKCS12Certificate(certificate_, password_));
}
@@ -83,12 +110,13 @@ void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connectio
session_ = ClientSession::create(jid_, sessionStream_);
session_->setCertificateTrustChecker(certificateTrustChecker);
- session_->setUseStreamCompression(useStreamCompression);
- switch(useTLS) {
- case UseTLSWhenAvailable:
+ session_->setUseStreamCompression(options.useStreamCompression);
+ session_->setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS);
+ switch(options.useTLS) {
+ case ClientOptions::UseTLSWhenAvailable:
session_->setUseTLS(ClientSession::UseTLSWhenAvailable);
break;
- case NeverUseTLS:
+ case ClientOptions::NeverUseTLS:
session_->setUseTLS(ClientSession::NeverUseTLS);
break;
}
@@ -116,6 +144,9 @@ void CoreClient::setCertificate(const std::string& certificate) {
}
void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) {
+ if (options.forgetPassword) {
+ purgePassword();
+ }
session_->onFinished.disconnect(boost::bind(&CoreClient::handleSessionFinished, this, _1));
session_->onNeedCredentials.disconnect(boost::bind(&CoreClient::handleNeedCredentials, this));
@@ -227,13 +258,16 @@ void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) {
void CoreClient::handleNeedCredentials() {
assert(session_);
session_->sendCredentials(password_);
+ if (options.forgetPassword) {
+ purgePassword();
+ }
}
-void CoreClient::handleDataRead(const std::string& data) {
+void CoreClient::handleDataRead(const SafeByteArray& data) {
onDataRead(data);
}
-void CoreClient::handleDataWritten(const std::string& data) {
+void CoreClient::handleDataWritten(const SafeByteArray& data) {
onDataWritten(data);
}
@@ -276,13 +310,29 @@ void CoreClient::handleStanzaAcked(Stanza::ref stanza) {
onStanzaAcked(stanza);
}
-void CoreClient::setUseStreamCompression(bool b) {
- useStreamCompression = b;
+bool CoreClient::isAvailable() const {
+ return stanzaChannel_->isAvailable();
}
-void CoreClient::setUseTLS(UseTLS b) {
- useTLS = b;
+bool CoreClient::getStreamManagementEnabled() const {
+ return stanzaChannel_->getStreamManagementEnabled();
}
+StanzaChannel* CoreClient::getStanzaChannel() const {
+ return stanzaChannel_;
+}
+
+const JID& CoreClient::getJID() const {
+ if (session_) {
+ return session_->getLocalJID();
+ }
+ else {
+ return jid_;
+ }
+}
+
+void CoreClient::purgePassword() {
+ safeClear(password_);
+}
}
diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h
index eb9c42c..16813de 100644
--- a/Swiften/Client/CoreClient.h
+++ b/Swiften/Client/CoreClient.h
@@ -6,35 +6,34 @@
#pragma once
-#include "Swiften/Base/boost_bsignals.h"
+#include <string>
#include <boost/shared_ptr.hpp>
+#include <Swiften/Base/boost_bsignals.h>
-#include "Swiften/Network/PlatformDomainNameResolver.h"
-#include "Swiften/Network/Connector.h"
-#include "Swiften/Base/Error.h"
-#include "Swiften/Client/ClientSession.h"
-#include "Swiften/Client/ClientError.h"
-#include "Swiften/Elements/Presence.h"
-#include "Swiften/Elements/Message.h"
-#include "Swiften/JID/JID.h"
-#include <string>
-#include "Swiften/Client/StanzaChannel.h"
-#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
-#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
#include <Swiften/Entity/Entity.h>
-
-#include "Swiften/Client/ClientSessionStanzaChannel.h"
+#include <Swiften/JID/JID.h>
+#include <Swiften/Client/ClientError.h>
+#include <Swiften/Client/ClientOptions.h>
+#include <Swiften/Base/SafeByteArray.h>
namespace Swift {
+ class ChainedConnector;
+ class Message;
+ class Presence;
+ class Error;
class IQRouter;
class TLSContextFactory;
class ConnectionFactory;
+ class Connection;
class TimerFactory;
class ClientSession;
+ class StanzaChannel;
+ class Stanza;
class BasicSessionStream;
class PlatformTLSFactories;
class CertificateTrustChecker;
class NetworkFactories;
+ class ClientSessionStanzaChannel;
/**
* The central class for communicating with an XMPP server.
@@ -48,16 +47,11 @@ namespace Swift {
*/
class CoreClient : public Entity {
public:
- enum UseTLS {
- NeverUseTLS,
- UseTLSWhenAvailable
- };
-
/**
* Constructs a client for the given JID with the given password.
* The given eventLoop will be used to post events to.
*/
- CoreClient(const JID& jid, const std::string& password, NetworkFactories* networkFactories);
+ CoreClient(const JID& jid, const SafeByteArray& password, NetworkFactories* networkFactories);
~CoreClient();
void setCertificate(const std::string& certificate);
@@ -68,7 +62,7 @@ namespace Swift {
* After the connection is established, the client will set
* initialize the stream and authenticate.
*/
- void connect();
+ void connect(const ClientOptions& = ClientOptions());
/**
* Disconnects the client from the server.
@@ -80,12 +74,12 @@ namespace Swift {
/**
* Sends a message.
*/
- void sendMessage(Message::ref);
+ void sendMessage(boost::shared_ptr<Message>);
/**
* Sends a presence stanza.
*/
- void sendPresence(Presence::ref);
+ void sendPresence(boost::shared_ptr<Presence>);
/**
* Sends raw, unchecked data.
@@ -103,9 +97,7 @@ namespace Swift {
* Checks whether the client is connected to the server,
* and stanzas can be sent.
*/
- bool isAvailable() const {
- return stanzaChannel_->isAvailable();
- }
+ bool isAvailable() const;
/**
* Checks whether the client is active.
@@ -118,14 +110,7 @@ namespace Swift {
* Returns the JID of the client.
* After the session was initialized, this returns the bound JID.
*/
- const JID& getJID() const {
- if (session_) {
- return session_->getLocalJID();
- }
- else {
- return jid_;
- }
- }
+ const JID& getJID() const;
/**
* Checks whether stream management is enabled.
@@ -135,13 +120,9 @@ namespace Swift {
*
* \see onStanzaAcked
*/
- bool getStreamManagementEnabled() const {
- return stanzaChannel_->getStreamManagementEnabled();
- }
+ bool getStreamManagementEnabled() const;
- StanzaChannel* getStanzaChannel() const {
- return stanzaChannel_;
- }
+ StanzaChannel* getStanzaChannel() const;
/**
* Sets the certificate trust checker.
@@ -153,16 +134,6 @@ namespace Swift {
*/
void setCertificateTrustChecker(CertificateTrustChecker*);
- /**
- * Sets whether ZLib stream compression should be used when available.
- */
- void setUseStreamCompression(bool b);
-
- /**
- * Sets whether TLS encryption should be used.
- */
- void setUseTLS(UseTLS useTLS);
-
public:
/**
* Emitted when the client was disconnected from the network.
@@ -184,7 +155,7 @@ namespace Swift {
* This signal is emitted before the XML data is parsed,
* so this data is unformatted.
*/
- boost::signal<void (const std::string&)> onDataRead;
+ boost::signal<void (const SafeByteArray&)> onDataRead;
/**
* Emitted when the client sends data.
@@ -192,17 +163,17 @@ namespace Swift {
* This signal is emitted after the XML was serialized, and
* is unformatted.
*/
- boost::signal<void (const std::string&)> onDataWritten;
+ boost::signal<void (const SafeByteArray&)> onDataWritten;
/**
* Emitted when a message is received.
*/
- boost::signal<void (Message::ref)> onMessageReceived;
+ boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived;
/**
* Emitted when a presence stanza is received.
*/
- boost::signal<void (Presence::ref) > onPresenceReceived;
+ boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived;
/**
* Emitted when the server acknowledges receipt of a
@@ -210,28 +181,34 @@ namespace Swift {
*
* \see getStreamManagementEnabled()
*/
- boost::signal<void (Stanza::ref)> onStanzaAcked;
+ boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked;
+
+ protected:
+ boost::shared_ptr<ClientSession> getSession() const {
+ return session_;
+ }
private:
void handleConnectorFinished(boost::shared_ptr<Connection>);
void handleStanzaChannelAvailableChanged(bool available);
void handleSessionFinished(boost::shared_ptr<Error>);
void handleNeedCredentials();
- void handleDataRead(const std::string&);
- void handleDataWritten(const std::string&);
- void handlePresenceReceived(Presence::ref);
- void handleMessageReceived(Message::ref);
- void handleStanzaAcked(Stanza::ref);
+ void handleDataRead(const SafeByteArray&);
+ void handleDataWritten(const SafeByteArray&);
+ void handlePresenceReceived(boost::shared_ptr<Presence>);
+ void handleMessageReceived(boost::shared_ptr<Message>);
+ void handleStanzaAcked(boost::shared_ptr<Stanza>);
+ void purgePassword();
private:
JID jid_;
- std::string password_;
+ SafeByteArray password_;
NetworkFactories* networkFactories;
- bool useStreamCompression;
- UseTLS useTLS;
ClientSessionStanzaChannel* stanzaChannel_;
IQRouter* iqRouter_;
- Connector::ref connector_;
+ ClientOptions options;
+ boost::shared_ptr<ChainedConnector> connector_;
+ std::vector<ConnectionFactory*> proxyConnectionFactories;
PlatformTLSFactories* tlsFactories;
boost::shared_ptr<Connection> connection_;
boost::shared_ptr<BasicSessionStream> sessionStream_;
diff --git a/Swiften/Client/DummyStanzaChannel.h b/Swiften/Client/DummyStanzaChannel.h
index b9f05c3..c2f3919 100644
--- a/Swiften/Client/DummyStanzaChannel.h
+++ b/Swiften/Client/DummyStanzaChannel.h
@@ -8,7 +8,7 @@
#include <vector>
-#include "Swiften/Client/StanzaChannel.h"
+#include <Swiften/Client/StanzaChannel.h>
namespace Swift {
class DummyStanzaChannel : public StanzaChannel {
@@ -56,6 +56,22 @@ namespace Swift {
return iqStanza && iqStanza->getType() == type && iqStanza->getTo() == jid && iqStanza->getPayload<T>();
}
+ bool isResultAtIndex(size_t index, const std::string& id) {
+ if (index >= sentStanzas.size()) {
+ return false;
+ }
+ boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]);
+ return iqStanza && iqStanza->getType() == IQ::Result && iqStanza->getID() == id;
+ }
+
+ bool isErrorAtIndex(size_t index, const std::string& id) {
+ if (index >= sentStanzas.size()) {
+ return false;
+ }
+ boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]);
+ return iqStanza && iqStanza->getType() == IQ::Error && iqStanza->getID() == id;
+ }
+
template<typename T> boost::shared_ptr<T> getStanzaAtIndex(size_t index) {
if (sentStanzas.size() <= index) {
return boost::shared_ptr<T>();
diff --git a/Swiften/Client/FileStorages.cpp b/Swiften/Client/FileStorages.cpp
deleted file mode 100644
index 3c76c46..0000000
--- a/Swiften/Client/FileStorages.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include "Swiften/Client/FileStorages.h"
-#include "Swiften/VCards/VCardFileStorage.h"
-#include "Swiften/Avatars/AvatarFileStorage.h"
-#include "Swiften/Disco/CapsFileStorage.h"
-
-namespace Swift {
-
-FileStorages::FileStorages(const boost::filesystem::path& baseDir, const JID& jid) {
- std::string profile = jid.toBare();
- vcardStorage = new VCardFileStorage(baseDir / profile / "vcards");
- capsStorage = new CapsFileStorage(baseDir / "caps");
- avatarStorage = new AvatarFileStorage(baseDir / "avatars", baseDir / profile / "avatars");
-}
-
-FileStorages::~FileStorages() {
- delete avatarStorage;
- delete capsStorage;
- delete vcardStorage;
-}
-
-VCardStorage* FileStorages::getVCardStorage() const {
- return vcardStorage;
-}
-
-CapsStorage* FileStorages::getCapsStorage() const {
- return capsStorage;
-}
-
-AvatarStorage* FileStorages::getAvatarStorage() const {
- return avatarStorage;
-}
-
-}
diff --git a/Swiften/Client/FileStorages.h b/Swiften/Client/FileStorages.h
deleted file mode 100644
index 451105f..0000000
--- a/Swiften/Client/FileStorages.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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 <boost/filesystem.hpp>
-
-#include "Swiften/Client/Storages.h"
-
-namespace Swift {
- class VCardFileStorage;
- class AvatarFileStorage;
- class CapsFileStorage;
- class JID;
-
- /**
- * A storages implementation that stores all controller data on disk.
- */
- class FileStorages : public Storages {
- public:
- /**
- * Creates the storages interface.
- *
- * All data will be stored relative to a base directory, and
- * for some controllers, in a subdirectory for the given profile.
- * The data is stored in the following places:
- * - Avatars: <basedir>/avatars
- * - VCards: <basedir>/<profile>/vcards
- * - Entity capabilities: <basedir>/caps
- *
- * \param baseDir the base dir to store data relative to
- * \param jid the subdir in which profile-specific data will be stored.
- * The bare JID will be used as the subdir name.
- */
- FileStorages(const boost::filesystem::path& baseDir, const JID& jid);
- ~FileStorages();
-
- virtual VCardStorage* getVCardStorage() const;
- virtual AvatarStorage* getAvatarStorage() const;
- virtual CapsStorage* getCapsStorage() const;
-
- private:
- VCardFileStorage* vcardStorage;
- AvatarFileStorage* avatarStorage;
- CapsFileStorage* capsStorage;
- };
-}
diff --git a/Swiften/Client/MemoryStorages.cpp b/Swiften/Client/MemoryStorages.cpp
index 5f6371b..fe171f7 100644
--- a/Swiften/Client/MemoryStorages.cpp
+++ b/Swiften/Client/MemoryStorages.cpp
@@ -4,10 +4,11 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/Client/MemoryStorages.h"
-#include "Swiften/VCards/VCardMemoryStorage.h"
-#include "Swiften/Avatars/AvatarMemoryStorage.h"
-#include "Swiften/Disco/CapsMemoryStorage.h"
+#include <Swiften/Client/MemoryStorages.h>
+#include <Swiften/VCards/VCardMemoryStorage.h>
+#include <Swiften/Avatars/AvatarMemoryStorage.h>
+#include <Swiften/Disco/CapsMemoryStorage.h>
+#include <Swiften/Roster/RosterMemoryStorage.h>
namespace Swift {
@@ -15,9 +16,11 @@ MemoryStorages::MemoryStorages() {
vcardStorage = new VCardMemoryStorage();
capsStorage = new CapsMemoryStorage();
avatarStorage = new AvatarMemoryStorage();
+ rosterStorage = new RosterMemoryStorage();
}
MemoryStorages::~MemoryStorages() {
+ delete rosterStorage;
delete avatarStorage;
delete capsStorage;
delete vcardStorage;
@@ -35,4 +38,9 @@ AvatarStorage* MemoryStorages::getAvatarStorage() const {
return avatarStorage;
}
+RosterStorage* MemoryStorages::getRosterStorage() const {
+ return rosterStorage;
+}
+
+
}
diff --git a/Swiften/Client/MemoryStorages.h b/Swiften/Client/MemoryStorages.h
index 67025cd..ca01a7a 100644
--- a/Swiften/Client/MemoryStorages.h
+++ b/Swiften/Client/MemoryStorages.h
@@ -6,7 +6,7 @@
#pragma once
-#include "Swiften/Client/Storages.h"
+#include <Swiften/Client/Storages.h>
namespace Swift {
class VCardMemoryStorage;
@@ -23,10 +23,12 @@ namespace Swift {
virtual VCardStorage* getVCardStorage() const;
virtual AvatarStorage* getAvatarStorage() const;
virtual CapsStorage* getCapsStorage() const;
+ virtual RosterStorage* getRosterStorage() const;
private:
VCardMemoryStorage* vcardStorage;
AvatarStorage* avatarStorage;
CapsStorage* capsStorage;
+ RosterStorage* rosterStorage;
};
}
diff --git a/Swiften/Client/NickResolver.cpp b/Swiften/Client/NickResolver.cpp
index 6d5e742..e6f2e41 100644
--- a/Swiften/Client/NickResolver.cpp
+++ b/Swiften/Client/NickResolver.cpp
@@ -4,14 +4,14 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/Client/NickResolver.h"
+#include <Swiften/Client/NickResolver.h>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
-#include "Swiften/MUC/MUCRegistry.h"
-#include "Swiften/Roster/XMPPRoster.h"
-#include "Swiften/VCards/VCardManager.h"
+#include <Swiften/MUC/MUCRegistry.h>
+#include <Swiften/Roster/XMPPRoster.h>
+#include <Swiften/VCards/VCardManager.h>
// FIXME: The NickResolver currently relies on the vcard being requested by the client on login.
// The VCardManager should get an onConnected() signal (which is signalled when the stanzachannel is available(, and each time this is emitted,
diff --git a/Swiften/Client/NickResolver.h b/Swiften/Client/NickResolver.h
index 881362a..584f2ce 100644
--- a/Swiften/Client/NickResolver.h
+++ b/Swiften/Client/NickResolver.h
@@ -5,12 +5,12 @@
*/
#include <map>
-#include <boost/signals.hpp>
#include <boost/shared_ptr.hpp>
+#include <Swiften/Base/boost_bsignals.h>
#include <string>
-#include "Swiften/JID/JID.h"
-#include "Swiften/Elements/VCard.h"
+#include <Swiften/JID/JID.h>
+#include <Swiften/Elements/VCard.h>
namespace Swift {
class XMPPRoster;
diff --git a/Swiften/Client/StanzaChannel.h b/Swiften/Client/StanzaChannel.h
index 4d6392c..f1d76e0 100644
--- a/Swiften/Client/StanzaChannel.h
+++ b/Swiften/Client/StanzaChannel.h
@@ -6,12 +6,12 @@
#pragma once
-#include "Swiften/Base/boost_bsignals.h"
+#include <Swiften/Base/boost_bsignals.h>
#include <boost/shared_ptr.hpp>
-#include "Swiften/Queries/IQChannel.h"
-#include "Swiften/Elements/Message.h"
-#include "Swiften/Elements/Presence.h"
+#include <Swiften/Queries/IQChannel.h>
+#include <Swiften/Elements/Message.h>
+#include <Swiften/Elements/Presence.h>
namespace Swift {
class StanzaChannel : public IQChannel {
diff --git a/Swiften/Client/Storages.cpp b/Swiften/Client/Storages.cpp
new file mode 100644
index 0000000..3c2dbc5
--- /dev/null
+++ b/Swiften/Client/Storages.cpp
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Client/Storages.h>
+
+using namespace Swift;
+
+Storages::~Storages() {
+}
diff --git a/Swiften/Client/Storages.h b/Swiften/Client/Storages.h
index e62f0a9..1c5bbe9 100644
--- a/Swiften/Client/Storages.h
+++ b/Swiften/Client/Storages.h
@@ -10,6 +10,7 @@ namespace Swift {
class VCardStorage;
class AvatarStorage;
class CapsStorage;
+ class RosterStorage;
/**
* An interface to hold storage classes for different
@@ -17,10 +18,11 @@ namespace Swift {
*/
class Storages {
public:
- virtual ~Storages() {}
+ virtual ~Storages();
virtual VCardStorage* getVCardStorage() const = 0;
virtual AvatarStorage* getAvatarStorage() const = 0;
virtual CapsStorage* getCapsStorage() const = 0;
+ virtual RosterStorage* getRosterStorage() const = 0;
};
}
diff --git a/Swiften/Client/UnitTest/ClientSessionTest.cpp b/Swiften/Client/UnitTest/ClientSessionTest.cpp
index 756287c..57e53e4 100644
--- a/Swiften/Client/UnitTest/ClientSessionTest.cpp
+++ b/Swiften/Client/UnitTest/ClientSessionTest.cpp
@@ -11,23 +11,25 @@
#include <boost/optional.hpp>
#include <boost/smart_ptr/make_shared.hpp>
-#include "Swiften/Session/SessionStream.h"
-#include "Swiften/Client/ClientSession.h"
-#include "Swiften/Elements/StartTLSRequest.h"
-#include "Swiften/Elements/StreamFeatures.h"
-#include "Swiften/Elements/StreamError.h"
-#include "Swiften/Elements/TLSProceed.h"
-#include "Swiften/Elements/StartTLSFailure.h"
-#include "Swiften/Elements/AuthRequest.h"
-#include "Swiften/Elements/AuthSuccess.h"
-#include "Swiften/Elements/AuthFailure.h"
-#include "Swiften/Elements/StreamManagementEnabled.h"
-#include "Swiften/Elements/StreamManagementFailed.h"
-#include "Swiften/Elements/EnableStreamManagement.h"
-#include "Swiften/Elements/IQ.h"
-#include "Swiften/Elements/ResourceBind.h"
-#include "Swiften/TLS/SimpleCertificate.h"
-#include "Swiften/TLS/BlindCertificateTrustChecker.h"
+#include <Swiften/Session/SessionStream.h>
+#include <Swiften/Client/ClientSession.h>
+#include <Swiften/Elements/Message.h>
+#include <Swiften/Elements/StartTLSRequest.h>
+#include <Swiften/Elements/StreamFeatures.h>
+#include <Swiften/Elements/StreamError.h>
+#include <Swiften/Elements/TLSProceed.h>
+#include <Swiften/Elements/StartTLSFailure.h>
+#include <Swiften/Elements/AuthRequest.h>
+#include <Swiften/Elements/AuthSuccess.h>
+#include <Swiften/Elements/AuthFailure.h>
+#include <Swiften/Elements/StreamManagementEnabled.h>
+#include <Swiften/Elements/StreamManagementFailed.h>
+#include <Swiften/Elements/StanzaAck.h>
+#include <Swiften/Elements/EnableStreamManagement.h>
+#include <Swiften/Elements/IQ.h>
+#include <Swiften/Elements/ResourceBind.h>
+#include <Swiften/TLS/SimpleCertificate.h>
+#include <Swiften/TLS/BlindCertificateTrustChecker.h>
using namespace Swift;
@@ -45,6 +47,7 @@ class ClientSessionTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testAuthenticate_NoValidAuthMechanisms);
CPPUNIT_TEST(testStreamManagement);
CPPUNIT_TEST(testStreamManagement_Failed);
+ CPPUNIT_TEST(testFinishAcksStanzas);
/*
CPPUNIT_TEST(testResourceBind);
CPPUNIT_TEST(testResourceBind_ChangeResource);
@@ -178,7 +181,7 @@ class ClientSessionTest : public CppUnit::TestFixture {
server->sendStreamFeaturesWithPLAINAuthentication();
CPPUNIT_ASSERT(needCredentials);
CPPUNIT_ASSERT_EQUAL(ClientSession::WaitingForCredentials, session->getState());
- session->sendCredentials("mypass");
+ session->sendCredentials(createSafeByteArray("mypass"));
server->receiveAuthRequest("PLAIN");
server->sendAuthSuccess();
server->receiveStreamStart();
@@ -194,7 +197,7 @@ class ClientSessionTest : public CppUnit::TestFixture {
server->sendStreamFeaturesWithPLAINAuthentication();
CPPUNIT_ASSERT(needCredentials);
CPPUNIT_ASSERT_EQUAL(ClientSession::WaitingForCredentials, session->getState());
- session->sendCredentials("mypass");
+ session->sendCredentials(createSafeByteArray("mypass"));
server->receiveAuthRequest("PLAIN");
server->sendAuthFailure();
@@ -234,7 +237,7 @@ class ClientSessionTest : public CppUnit::TestFixture {
server->receiveStreamStart();
server->sendStreamStart();
server->sendStreamFeaturesWithPLAINAuthentication();
- session->sendCredentials("mypass");
+ session->sendCredentials(createSafeByteArray("mypass"));
server->receiveAuthRequest("PLAIN");
server->sendAuthSuccess();
server->receiveStreamStart();
@@ -258,7 +261,7 @@ class ClientSessionTest : public CppUnit::TestFixture {
server->receiveStreamStart();
server->sendStreamStart();
server->sendStreamFeaturesWithPLAINAuthentication();
- session->sendCredentials("mypass");
+ session->sendCredentials(createSafeByteArray("mypass"));
server->receiveAuthRequest("PLAIN");
server->sendAuthSuccess();
server->receiveStreamStart();
@@ -275,6 +278,17 @@ class ClientSessionTest : public CppUnit::TestFixture {
session->finish();
}
+ void testFinishAcksStanzas() {
+ boost::shared_ptr<ClientSession> session(createSession());
+ initializeSession(session);
+ server->sendMessage();
+ server->sendMessage();
+ server->sendMessage();
+
+ session->finish();
+
+ server->receiveAck(3);
+ }
private:
boost::shared_ptr<ClientSession> createSession() {
@@ -285,6 +299,23 @@ class ClientSessionTest : public CppUnit::TestFixture {
return session;
}
+ void initializeSession(boost::shared_ptr<ClientSession> session) {
+ session->start();
+ server->receiveStreamStart();
+ server->sendStreamStart();
+ server->sendStreamFeaturesWithPLAINAuthentication();
+ session->sendCredentials(createSafeByteArray("mypass"));
+ server->receiveAuthRequest("PLAIN");
+ server->sendAuthSuccess();
+ server->receiveStreamStart();
+ server->sendStreamStart();
+ server->sendStreamFeaturesWithBindAndStreamManagement();
+ server->receiveBind();
+ server->sendBindResult();
+ server->receiveStreamManagementEnable();
+ server->sendStreamManagementEnabled();
+ }
+
void handleSessionFinished(boost::shared_ptr<Error> error) {
sessionFinishedReceived = true;
sessionFinishedError = error;
@@ -447,6 +478,12 @@ class ClientSessionTest : public CppUnit::TestFixture {
onElementReceived(iq);
}
+ void sendMessage() {
+ boost::shared_ptr<Message> message = boost::make_shared<Message>();
+ message->setTo(JID("foo@bar.com/bla"));
+ onElementReceived(message);
+ }
+
void receiveStreamStart() {
Event event = popEvent();
CPPUNIT_ASSERT(event.header);
@@ -481,8 +518,16 @@ class ClientSessionTest : public CppUnit::TestFixture {
bindID = iq->getID();
}
+ void receiveAck(unsigned int n) {
+ Event event = popEvent();
+ CPPUNIT_ASSERT(event.element);
+ boost::shared_ptr<StanzaAck> ack = boost::dynamic_pointer_cast<StanzaAck>(event.element);
+ CPPUNIT_ASSERT(ack);
+ CPPUNIT_ASSERT_EQUAL(n, ack->getHandledStanzasCount());
+ }
+
Event popEvent() {
- CPPUNIT_ASSERT(receivedEvents.size() > 0);
+ CPPUNIT_ASSERT(!receivedEvents.empty());
Event event = receivedEvents.front();
receivedEvents.pop_front();
return event;
diff --git a/Swiften/Client/UnitTest/NickResolverTest.cpp b/Swiften/Client/UnitTest/NickResolverTest.cpp
index bd778d4..dfc90fe 100644
--- a/Swiften/Client/UnitTest/NickResolverTest.cpp
+++ b/Swiften/Client/UnitTest/NickResolverTest.cpp
@@ -7,13 +7,13 @@
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
-#include "Swiften/Client/NickResolver.h"
-#include "Swiften/MUC/MUCRegistry.h"
-#include "Swiften/Roster/XMPPRosterImpl.h"
-#include "Swiften/VCards/VCardManager.h"
-#include "Swiften/VCards/VCardMemoryStorage.h"
-#include "Swiften/Queries/IQRouter.h"
-#include "Swiften/Client/DummyStanzaChannel.h"
+#include <Swiften/Client/NickResolver.h>
+#include <Swiften/MUC/MUCRegistry.h>
+#include <Swiften/Roster/XMPPRosterImpl.h>
+#include <Swiften/VCards/VCardManager.h>
+#include <Swiften/VCards/VCardMemoryStorage.h>
+#include <Swiften/Queries/IQRouter.h>
+#include <Swiften/Client/DummyStanzaChannel.h>
using namespace Swift;