summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swiften/Elements/HashElement.h42
-rw-r--r--Swiften/Elements/JingleFileTransferDescription.h24
-rw-r--r--Swiften/Elements/JingleFileTransferFileInfo.h120
-rw-r--r--Swiften/Elements/JingleFileTransferHash.h19
-rw-r--r--Swiften/FileTransfer/DefaultFileTransferTransporter.cpp8
-rw-r--r--Swiften/FileTransfer/FileTransferManagerImpl.cpp6
-rw-r--r--Swiften/FileTransfer/FileTransferOptions.h4
-rw-r--r--Swiften/FileTransfer/FileTransferTransporter.h7
-rw-r--r--Swiften/FileTransfer/IncomingFileTransfer.h6
-rw-r--r--Swiften/FileTransfer/IncomingFileTransferManager.cpp4
-rw-r--r--Swiften/FileTransfer/IncomingJingleFileTransfer.cpp61
-rw-r--r--Swiften/FileTransfer/IncomingJingleFileTransfer.h16
-rw-r--r--Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp20
-rw-r--r--Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h9
-rw-r--r--Swiften/FileTransfer/OutgoingFileTransferManager.cpp4
-rw-r--r--Swiften/FileTransfer/OutgoingFileTransferManager.h6
-rw-r--r--Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp12
-rw-r--r--Swiften/FileTransfer/OutgoingJingleFileTransfer.h8
-rw-r--r--Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp93
-rw-r--r--Swiften/Jingle/FakeJingleSession.cpp11
-rw-r--r--Swiften/Jingle/FakeJingleSession.h4
-rw-r--r--Swiften/Network/DummyConnectionServer.h44
-rw-r--r--Swiften/Network/DummyConnectionServerFactory.h35
-rw-r--r--Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp2
-rw-r--r--Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp59
-rw-r--r--Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h15
-rw-r--r--Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h8
-rw-r--r--Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.cpp79
-rw-r--r--Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h29
-rw-r--r--Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp43
-rw-r--r--Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h10
-rw-r--r--Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp8
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp257
-rw-r--r--Swiften/Parser/SConscript1
-rw-r--r--Swiften/SConscript1
-rw-r--r--Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp2
-rw-r--r--Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp35
-rw-r--r--Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp66
-rw-r--r--Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h24
-rw-r--r--Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp25
-rw-r--r--Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp144
41 files changed, 872 insertions, 499 deletions
diff --git a/Swiften/Elements/HashElement.h b/Swiften/Elements/HashElement.h
new file mode 100644
index 0000000..44d2f96
--- /dev/null
+++ b/Swiften/Elements/HashElement.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/ByteArray.h>
+
+namespace Swift {
+ /*
+ * @brief This class represents a XEP-0300 <hash/> element.
+ */
+ class HashElement {
+ public:
+ HashElement(const std::string& algorithm, const ByteArray& hash) : algorithm_(algorithm), hash_(hash) {
+ }
+
+ void setHashValue(const std::string& algorithm, const ByteArray& hash) {
+ algorithm_ = algorithm;
+ hash_ = hash;
+ }
+
+ const std::string& getAlgorithm() const {
+ return algorithm_;
+ }
+
+ const ByteArray& getHashValue() const {
+ return hash_;
+ }
+
+ bool operator==(const HashElement& rhs) const {
+ return (algorithm_ == rhs.algorithm_) && (hash_ == rhs.hash_);
+ }
+
+
+ private:
+ std::string algorithm_;
+ ByteArray hash_;
+ };
+}
diff --git a/Swiften/Elements/JingleFileTransferDescription.h b/Swiften/Elements/JingleFileTransferDescription.h
index 620f8f5..9308abf 100644
--- a/Swiften/Elements/JingleFileTransferDescription.h
+++ b/Swiften/Elements/JingleFileTransferDescription.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 Isode Limited.
+ * Copyright (c) 2011-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -10,32 +10,22 @@
#include <vector>
#include <Swiften/Elements/JingleDescription.h>
-#include <Swiften/Elements/StreamInitiationFileInfo.h>
+#include <Swiften/Elements/JingleFileTransferFileInfo.h>
namespace Swift {
class JingleFileTransferDescription : public JingleDescription {
public:
typedef boost::shared_ptr<JingleFileTransferDescription> ref;
- void addOffer(const StreamInitiationFileInfo& offer) {
- offers.push_back(offer);
+ void setFileInfo(const JingleFileTransferFileInfo& fileInfo) {
+ fileInfo_ = fileInfo;
}
-
- const std::vector<StreamInitiationFileInfo>& getOffers() const {
- return offers;
- }
-
- void addRequest(const StreamInitiationFileInfo& request) {
- reqeusts.push_back(request);
- }
-
- const std::vector<StreamInitiationFileInfo>& getRequests() const {
- return reqeusts;
+ const JingleFileTransferFileInfo& getFileInfo() {
+ return fileInfo_;
}
private:
- std::vector<StreamInitiationFileInfo> offers;
- std::vector<StreamInitiationFileInfo> reqeusts;
+ JingleFileTransferFileInfo fileInfo_;
};
}
diff --git a/Swiften/Elements/JingleFileTransferFileInfo.h b/Swiften/Elements/JingleFileTransferFileInfo.h
new file mode 100644
index 0000000..8fec59e
--- /dev/null
+++ b/Swiften/Elements/JingleFileTransferFileInfo.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include <boost/optional.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+
+#include <Swiften/Elements/HashElement.h>
+#include <Swiften/Elements/Payload.h>
+
+namespace Swift {
+
+ /**
+ * @brief This class represents the file info used in XEP-0234.
+ */
+ class JingleFileTransferFileInfo : public Payload {
+ typedef boost::shared_ptr<JingleFileTransferFileInfo> ref;
+
+ public:
+ JingleFileTransferFileInfo(const std::string& name = "", const std::string& description = "", unsigned long long size = 0, const boost::posix_time::ptime &date = boost::posix_time::ptime()) :
+ name_(name), description_(description), size_(size), date_(date), supportsRangeRequests_(false), rangeOffset_(0) {
+ }
+
+ public:
+ typedef std::map<std::string, ByteArray> HashElementMap;
+
+ public:
+ void setName(const std::string& name) {
+ name_ = name;;
+ }
+
+ const std::string& getName() const {
+ return name_;
+ }
+
+ void setDescription(const std::string& description) {
+ description_ = description;
+ }
+
+ const std::string& getDescription() const {
+ return description_;
+ }
+
+ void setMediaType(const std::string& mediaType) {
+ mediaType_ = mediaType;
+ }
+
+ const std::string& getMediaType() const {
+ return mediaType_;
+ }
+
+ void setSize(const boost::uintmax_t size) {
+ size_ = size;
+ }
+
+ boost::uintmax_t getSize() const {
+ return size_;
+ }
+
+ void setDate(const boost::posix_time::ptime& date) {
+ date_ = date;
+ }
+
+ const boost::posix_time::ptime& getDate() const {
+ return date_;
+ }
+
+ void setSupportsRangeRequests(const bool supportsIt) {
+ supportsRangeRequests_ = supportsIt;
+ }
+
+ bool getSupportsRangeRequests() const {
+ return supportsRangeRequests_;
+ }
+
+ void setRangeOffset(const boost::uintmax_t offset) {
+ supportsRangeRequests_ = true;
+ rangeOffset_ = offset;
+ }
+
+ boost::uintmax_t getRangeOffset() const {
+ return rangeOffset_;
+ }
+
+ void addHash(const HashElement& hash) {
+ hashes_[hash.getAlgorithm()] = hash.getHashValue();
+ }
+
+ const std::map<std::string, ByteArray>& getHashes() const {
+ return hashes_;
+ }
+
+ boost::optional<ByteArray> getHash(const std::string& algorithm) const {
+ boost::optional<ByteArray> ret;
+ if (hashes_.find(algorithm) != hashes_.end()) {
+ ret = boost::optional<ByteArray>(hashes_.find(algorithm)->second);
+ }
+ return ret;
+ }
+
+ private:
+ std::string name_;
+ std::string description_;
+ std::string mediaType_;
+ boost::uintmax_t size_;
+ boost::posix_time::ptime date_;
+ bool supportsRangeRequests_;
+ boost::uintmax_t rangeOffset_;
+ HashElementMap hashes_;
+ };
+}
diff --git a/Swiften/Elements/JingleFileTransferHash.h b/Swiften/Elements/JingleFileTransferHash.h
index 5603531..d34e35d 100644
--- a/Swiften/Elements/JingleFileTransferHash.h
+++ b/Swiften/Elements/JingleFileTransferHash.h
@@ -4,6 +4,12 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#pragma once
#include <boost/shared_ptr.hpp>
@@ -11,25 +17,24 @@
#include <string>
#include <Swiften/Elements/JingleDescription.h>
+#include <Swiften/Elements/JingleFileTransferFileInfo.h>
namespace Swift {
class JingleFileTransferHash : public Payload {
public:
- typedef std::map<std::string, std::string> HashesMap;
-public:
typedef boost::shared_ptr<JingleFileTransferHash> ref;
- void setHash(const std::string& algo, const std::string& hash) {
- hashes[algo] = hash;
+ void setFileInfo(const JingleFileTransferFileInfo& fileInfo) {
+ fileInfo_ = fileInfo;
}
- const HashesMap& getHashes() const {
- return hashes;
+ JingleFileTransferFileInfo& getFileInfo() {
+ return fileInfo_;
}
private:
- HashesMap hashes;
+ JingleFileTransferFileInfo fileInfo_;
};
}
diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp b/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp
index 74492b1..1a77685 100644
--- a/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp
+++ b/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Isode Limited.
+ * Copyright (c) 2013-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -242,8 +242,10 @@ boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBSen
boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBReceiveSession(
const std::string& sessionID, unsigned long long size, boost::shared_ptr<WriteBytestream> stream) {
- closeLocalSession();
- closeRemoteSession();
+ if (s5bServerManager->getServer()) {
+ closeLocalSession();
+ closeRemoteSession();
+ }
boost::shared_ptr<IBBReceiveSession> ibbSession = boost::make_shared<IBBReceiveSession>(
sessionID, initiator, responder, size, stream, router);
return boost::make_shared<IBBReceiveTransportSession>(ibbSession);
diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.cpp b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
index f248b8a..fe8bfd6 100644
--- a/Swiften/FileTransfer/FileTransferManagerImpl.cpp
+++ b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2013 Isode Limited.
+ * Copyright (c) 2013-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -21,7 +21,7 @@
#include <Swiften/Base/Path.h>
#include "Swiften/Disco/EntityCapsProvider.h"
#include <Swiften/JID/JID.h>
-#include <Swiften/Elements/StreamInitiationFileInfo.h>
+#include <Swiften/Elements/JingleFileTransferFileInfo.h>
#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h>
#include <Swiften/FileTransfer/OutgoingFileTransferManager.h>
#include <Swiften/FileTransfer/IncomingFileTransferManager.h>
@@ -146,7 +146,7 @@ OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer(
const boost::posix_time::ptime& lastModified,
boost::shared_ptr<ReadBytestream> bytestream,
const FileTransferOptions& config) {
- StreamInitiationFileInfo fileInfo;
+ JingleFileTransferFileInfo fileInfo;
fileInfo.setDate(lastModified);
fileInfo.setSize(sizeInBytes);
fileInfo.setName(filename);
diff --git a/Swiften/FileTransfer/FileTransferOptions.h b/Swiften/FileTransfer/FileTransferOptions.h
index 3a0abcb..3d00d2b 100644
--- a/Swiften/FileTransfer/FileTransferOptions.h
+++ b/Swiften/FileTransfer/FileTransferOptions.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Isode Limited.
+ * Copyright (c) 2013-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -12,7 +12,7 @@
namespace Swift {
class SWIFTEN_API FileTransferOptions {
public:
- FileTransferOptions() : allowInBand(false) {
+ FileTransferOptions() : allowInBand(true) {
}
SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(FileTransferOptions)
~FileTransferOptions();
diff --git a/Swiften/FileTransfer/FileTransferTransporter.h b/Swiften/FileTransfer/FileTransferTransporter.h
index d149722..2116f0d 100644
--- a/Swiften/FileTransfer/FileTransferTransporter.h
+++ b/Swiften/FileTransfer/FileTransferTransporter.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Isode Limited.
+ * Copyright (c) 2013-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -20,6 +20,11 @@ namespace Swift {
class ReadBytestream;
class WriteBytestream;
+ /**
+ * @brief The FileTransferTransporter class is an abstract factory definition
+ * to generate SOCKS5 bytestream transports or IBB bytestreams for use in file
+ * transfers.
+ */
class SWIFTEN_API FileTransferTransporter {
public:
virtual ~FileTransferTransporter();
diff --git a/Swiften/FileTransfer/IncomingFileTransfer.h b/Swiften/FileTransfer/IncomingFileTransfer.h
index e0cb4ad..93ecf1a 100644
--- a/Swiften/FileTransfer/IncomingFileTransfer.h
+++ b/Swiften/FileTransfer/IncomingFileTransfer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -16,6 +16,10 @@ namespace Swift {
class WriteBytestream;
class JID;
+ /**
+ * @brief The IncomingFileTransfer abstract class is the general interface in Swiften
+ * for incoming file transfers.
+ */
class IncomingFileTransfer : public FileTransfer {
public:
typedef boost::shared_ptr<IncomingFileTransfer> ref;
diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.cpp b/Swiften/FileTransfer/IncomingFileTransferManager.cpp
index 05d6259..239c4a8 100644
--- a/Swiften/FileTransfer/IncomingFileTransferManager.cpp
+++ b/Swiften/FileTransfer/IncomingFileTransferManager.cpp
@@ -44,13 +44,13 @@ bool IncomingFileTransferManager::handleIncomingJingleSession(
if (JingleContentPayload::ref content = Jingle::getContentWithDescription<JingleFileTransferDescription>(contents)) {
if (content->getTransport<JingleS5BTransportPayload>()) {
JingleFileTransferDescription::ref description = content->getDescription<JingleFileTransferDescription>();
- if (description && description->getOffers().size() == 1) {
+ if (description) {
IncomingJingleFileTransfer::ref transfer = boost::make_shared<IncomingJingleFileTransfer>(
recipient, session, content, transporterFactory, timerFactory, crypto);
onIncomingFileTransfer(transfer);
}
else {
- SWIFT_LOG(warning) << "Received a file-transfer request with no description or more than one file.";
+ SWIFT_LOG(warning) << "Received a file-transfer request with no file description.";
session->sendTerminate(JinglePayload::Reason::FailedApplication);
}
}
diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
index 66b2e53..720eefd 100644
--- a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
+++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
@@ -1,15 +1,18 @@
/*
- * Copyright (c) 2011-2013 Isode Limited.
+ * Copyright (c) 2011-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <Swiften/FileTransfer/IncomingJingleFileTransfer.h>
+#include <set>
+
#include <boost/bind.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <Swiften/Base/Log.h>
+#include <Swiften/StringCodecs/Base64.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Jingle/JingleSession.h>
#include <Swiften/Elements/JingleIBBTransportPayload.h>
@@ -43,11 +46,9 @@ IncomingJingleFileTransfer::IncomingJingleFileTransfer(
hashCalculator(NULL) {
description = initialContent->getDescription<JingleFileTransferDescription>();
assert(description);
- assert(description->getOffers().size() == 1);
- StreamInitiationFileInfo fileInfo = description->getOffers().front();
+ JingleFileTransferFileInfo fileInfo = description->getFileInfo();
setFileInfo(fileInfo.getName(), fileInfo.getSize());
- hash = fileInfo.getHash();
- hashAlgorithm = fileInfo.getAlgo();
+ hashes = fileInfo.getHashes();
waitOnHashTimer = timerFactory->createTimer(5000);
waitOnHashTimerTickedConnection = waitOnHashTimer->onTick.connect(
@@ -68,20 +69,33 @@ void IncomingJingleFileTransfer::accept(
this->options = options;
assert(!hashCalculator);
+
hashCalculator = new IncrementalBytestreamHashCalculator(
- hashAlgorithm == "md5" || hash.empty(), hashAlgorithm == "sha-1" || hash.empty(), crypto);
+ hashes.find("md5") != hashes.end(), hashes.find("sha-1") != hashes.end(), crypto);
writeStreamDataReceivedConnection = stream->onWrite.connect(
boost::bind(&IncomingJingleFileTransfer::handleWriteStreamDataReceived, this, _1));
if (JingleS5BTransportPayload::ref s5bTransport = initialContent->getTransport<JingleS5BTransportPayload>()) {
- SWIFT_LOG(debug) << "Got S5B transport payload!" << std::endl;
+ SWIFT_LOG(debug) << "Got S5B transport as initial payload." << std::endl;
setTransporter(transporterFactory->createResponderTransporter(
getInitiator(), getResponder(), s5bTransport->getSessionID()));
transporter->addRemoteCandidates(s5bTransport->getCandidates());
setState(GeneratingInitialLocalCandidates);
transporter->startGeneratingLocalCandidates();
}
+ else if (JingleIBBTransportPayload::ref ibbTransport = initialContent->getTransport<JingleIBBTransportPayload>()) {
+ SWIFT_LOG(debug) << "Got IBB transport as initial payload." << std::endl;
+ setTransporter(transporterFactory->createResponderTransporter(
+ getInitiator(), getResponder(), ibbTransport->getSessionID()));
+
+ startTransferring(transporter->createIBBReceiveSession(
+ ibbTransport->getSessionID(),
+ description->getFileInfo().getSize(),
+ stream));
+
+ session->sendAccept(getContentID(), initialContent->getDescriptions()[0], ibbTransport);
+ }
else {
// Can't happen, because the transfer would have been rejected automatically
assert(false);
@@ -121,13 +135,11 @@ void IncomingJingleFileTransfer::handleSessionInfoReceived(JinglePayload::ref ji
if (transferHash) {
SWIFT_LOG(debug) << "Received hash information." << std::endl;
waitOnHashTimer->stop();
- if (transferHash->getHashes().find("sha-1") != transferHash->getHashes().end()) {
- hashAlgorithm = "sha-1";
- hash = transferHash->getHashes().find("sha-1")->second;
+ if (transferHash->getFileInfo().getHashes().find("sha-1") != transferHash->getFileInfo().getHashes().end()) {
+ hashes["sha-1"] = transferHash->getFileInfo().getHash("sha-1").get();
}
- else if (transferHash->getHashes().find("md5") != transferHash->getHashes().end()) {
- hashAlgorithm = "md5";
- hash = transferHash->getHashes().find("md5")->second;
+ else if (transferHash->getFileInfo().getHashes().find("md5") != transferHash->getFileInfo().getHashes().end()) {
+ hashes["md5"] = transferHash->getFileInfo().getHash("md5").get();
}
if (state == WaitingForHash) {
checkHashAndTerminate();
@@ -172,7 +184,12 @@ void IncomingJingleFileTransfer::checkHashAndTerminate() {
void IncomingJingleFileTransfer::checkIfAllDataReceived() {
if (receivedBytes == getFileSizeInBytes()) {
SWIFT_LOG(debug) << "All data received." << std::endl;
- if (hash.empty()) {
+ bool hashInfoAvailable = true;
+ foreach(const JingleFileTransferFileInfo::HashElementMap::value_type& hashElement, hashes) {
+ hashInfoAvailable &= !hashElement.second.empty();
+ }
+
+ if (!hashInfoAvailable) {
SWIFT_LOG(debug) << "No hash information yet. Waiting a while on hash info." << std::endl;
setState(WaitingForHash);
waitOnHashTimer->start();
@@ -207,7 +224,7 @@ void IncomingJingleFileTransfer::handleTransportReplaceReceived(
startTransferring(transporter->createIBBReceiveSession(
ibbTransport->getSessionID(),
- description->getOffers()[0].getSize(),
+ description->getFileInfo().getSize(),
stream));
session->sendTransportAccept(content, ibbTransport);
}
@@ -222,17 +239,17 @@ JingleContentID IncomingJingleFileTransfer::getContentID() const {
}
bool IncomingJingleFileTransfer::verifyData() {
- if (hashAlgorithm.empty() || hash.empty()) {
+ if (hashes.empty()) {
SWIFT_LOG(debug) << "no verification possible, skipping" << std::endl;
return true;
}
- if (hashAlgorithm == "sha-1") {
- SWIFT_LOG(debug) << "Verify SHA-1 hash: " << (hash == hashCalculator->getSHA1String()) << std::endl;
- return hash == hashCalculator->getSHA1String();
+ if (hashes.find("sha-1") != hashes.end()) {
+ SWIFT_LOG(debug) << "Verify SHA-1 hash: " << (hashes["sha-1"] == hashCalculator->getSHA1Hash()) << std::endl;
+ return hashes["sha-1"] == hashCalculator->getSHA1Hash();
}
- else if (hashAlgorithm == "md5") {
- SWIFT_LOG(debug) << "Verify MD5 hash: " << (hash == hashCalculator->getMD5String()) << std::endl;
- return hash == hashCalculator->getMD5String();
+ else if (hashes.find("md5") != hashes.end()) {
+ SWIFT_LOG(debug) << "Verify MD5 hash: " << (hashes["md5"] == hashCalculator->getMD5Hash()) << std::endl;
+ return hashes["md5"] == hashCalculator->getMD5Hash();
}
else {
SWIFT_LOG(debug) << "Unknown hash, skipping" << std::endl;
diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.h b/Swiften/FileTransfer/IncomingJingleFileTransfer.h
index 727d278..7fc22f4 100644
--- a/Swiften/FileTransfer/IncomingJingleFileTransfer.h
+++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2013 Isode Limited.
+ * Copyright (c) 2010-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -17,6 +17,7 @@
#include <Swiften/FileTransfer/JingleFileTransfer.h>
#include <Swiften/Elements/JingleS5BTransportPayload.h>
#include <Swiften/FileTransfer/FileTransferOptions.h>
+#include <Swiften/Base/ByteArray.h>
namespace Swift {
class JID;
@@ -29,7 +30,15 @@ namespace Swift {
class CryptoProvider;
class IncrementalBytestreamHashCalculator;
class JingleFileTransferDescription;
+ class HashElement;
+ /**
+ * @brief The IncomingJingleFileTransfer class contains the business logic for managing incoming
+ * Jingle file transfers.
+ *
+ * Calling IncomingJingleFileTransfer::accept will start to negotiate possible transfer
+ * methods and after a working method has been decided among peers the trasnfer is started.
+ */
class SWIFTEN_API IncomingJingleFileTransfer : public IncomingFileTransfer, public JingleFileTransfer {
public:
typedef boost::shared_ptr<IncomingJingleFileTransfer> ref;
@@ -43,7 +52,7 @@ namespace Swift {
CryptoProvider*);
~IncomingJingleFileTransfer();
- virtual void accept(boost::shared_ptr<WriteBytestream>, const FileTransferOptions&) SWIFTEN_OVERRIDE;
+ virtual void accept(boost::shared_ptr<WriteBytestream>, const FileTransferOptions& = FileTransferOptions()) SWIFTEN_OVERRIDE;
virtual void cancel() SWIFTEN_OVERRIDE;
private:
@@ -108,8 +117,7 @@ namespace Swift {
boost::uintmax_t receivedBytes;
IncrementalBytestreamHashCalculator* hashCalculator;
boost::shared_ptr<Timer> waitOnHashTimer;
- std::string hashAlgorithm;
- std::string hash;
+ std::map<std::string, ByteArray> hashes;
FileTransferOptions options;
boost::bsignals::scoped_connection writeStreamDataReceivedConnection;
diff --git a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp
index e982fd0..7eb9560 100644
--- a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp
+++ b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2013 Isode Limited.
+ * Copyright (c) 2013-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -46,20 +46,30 @@ void IncrementalBytestreamHashCalculator::feedData(const SafeByteArray& data) {
}
}*/
-std::string IncrementalBytestreamHashCalculator::getSHA1String() {
+ByteArray IncrementalBytestreamHashCalculator::getSHA1Hash() {
assert(sha1Hasher);
if (!sha1Hash) {
- sha1Hash = Hexify::hexify(sha1Hasher->getHash());
+ sha1Hash = sha1Hasher->getHash();
}
return *sha1Hash;
}
-std::string IncrementalBytestreamHashCalculator::getMD5String() {
+ByteArray IncrementalBytestreamHashCalculator::getMD5Hash() {
assert(md5Hasher);
if (!md5Hash) {
- md5Hash = Hexify::hexify(md5Hasher->getHash());
+ md5Hash = md5Hasher->getHash();
}
return *md5Hash;
}
+std::string IncrementalBytestreamHashCalculator::getSHA1String() {
+ assert(sha1Hasher);
+ return Hexify::hexify(getSHA1Hash());;
+}
+
+std::string IncrementalBytestreamHashCalculator::getMD5String() {
+ assert(md5Hasher);
+ return Hexify::hexify(getMD5Hash());;
+}
+
}
diff --git a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h
index bb6b441..bc4ebf9 100644
--- a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h
+++ b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2013 Isode Limited.
+ * Copyright (c) 2013-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -30,14 +30,17 @@ namespace Swift {
void feedData(const ByteArray& data);
//void feedData(const SafeByteArray& data);
+ ByteArray getSHA1Hash();
+ ByteArray getMD5Hash();
+
std::string getSHA1String();
std::string getMD5String();
private:
Hash* md5Hasher;
Hash* sha1Hasher;
- boost::optional<std::string> md5Hash;
- boost::optional<std::string> sha1Hash;
+ boost::optional<ByteArray> md5Hash;
+ boost::optional<ByteArray> sha1Hash;
};
}
diff --git a/Swiften/FileTransfer/OutgoingFileTransferManager.cpp b/Swiften/FileTransfer/OutgoingFileTransferManager.cpp
index 5ed4656..5d0555f 100644
--- a/Swiften/FileTransfer/OutgoingFileTransferManager.cpp
+++ b/Swiften/FileTransfer/OutgoingFileTransferManager.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2013 Isode Limited.
+ * Copyright (c) 2013-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -43,7 +43,7 @@ boost::shared_ptr<OutgoingFileTransfer> OutgoingFileTransferManager::createOutgo
const JID& from,
const JID& recipient,
boost::shared_ptr<ReadBytestream> readBytestream,
- const StreamInitiationFileInfo& fileInfo,
+ const JingleFileTransferFileInfo& fileInfo,
const FileTransferOptions& config) {
JingleSessionImpl::ref jingleSession = boost::make_shared<JingleSessionImpl>(
from, recipient, idGenerator->generateID(), iqRouter);
diff --git a/Swiften/FileTransfer/OutgoingFileTransferManager.h b/Swiften/FileTransfer/OutgoingFileTransferManager.h
index 8dd4bbc..fd7380b 100644
--- a/Swiften/FileTransfer/OutgoingFileTransferManager.h
+++ b/Swiften/FileTransfer/OutgoingFileTransferManager.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2013 Isode Limited.
+ * Copyright (c) 2013-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -22,7 +22,7 @@ namespace Swift {
class JID;
class IDGenerator;
class ReadBytestream;
- class StreamInitiationFileInfo;
+ class JingleFileTransferFileInfo;
class CryptoProvider;
class FileTransferOptions;
@@ -39,7 +39,7 @@ namespace Swift {
const JID& from,
const JID& to,
boost::shared_ptr<ReadBytestream>,
- const StreamInitiationFileInfo&,
+ const JingleFileTransferFileInfo&,
const FileTransferOptions&);
private:
diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp
index 93214eb..369af8f 100644
--- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp
+++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2013 Isode Limited.
+ * Copyright (C) 2013-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -49,7 +49,7 @@ OutgoingJingleFileTransfer::OutgoingJingleFileTransfer(
boost::shared_ptr<ReadBytestream> stream,
FileTransferTransporterFactory* transporterFactory,
IDGenerator* idGenerator,
- const StreamInitiationFileInfo& fileInfo,
+ const JingleFileTransferFileInfo& fileInfo,
const FileTransferOptions& options,
CryptoProvider* crypto) :
JingleFileTransfer(session, toJID, transporterFactory),
@@ -149,8 +149,8 @@ void OutgoingJingleFileTransfer::sendSessionInfoHash() {
SWIFT_LOG(debug) << std::endl;
JingleFileTransferHash::ref hashElement = boost::make_shared<JingleFileTransferHash>();
- hashElement->setHash("sha-1", hashCalculator->getSHA1String());
- hashElement->setHash("md5", hashCalculator->getMD5String());
+ hashElement->getFileInfo().addHash(HashElement("sha-1", hashCalculator->getSHA1Hash()));
+ hashElement->getFileInfo().addHash(HashElement("md5", hashCalculator->getMD5Hash()));
session->sendInfo(hashElement);
}
@@ -162,7 +162,9 @@ void OutgoingJingleFileTransfer::handleLocalTransportCandidatesGenerated(
fillCandidateMap(localCandidates, candidates);
JingleFileTransferDescription::ref description = boost::make_shared<JingleFileTransferDescription>();
- description->addOffer(fileInfo);
+ fileInfo.addHash(HashElement("sha-1", ByteArray()));
+ fileInfo.addHash(HashElement("md5", ByteArray()));
+ description->setFileInfo(fileInfo);
JingleS5BTransportPayload::ref transport = boost::make_shared<JingleS5BTransportPayload>();
transport->setSessionID(s5bSessionID);
diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h
index c21c50b..f022b9f 100644
--- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h
+++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2013 Isode Limited.
+ * Copyright (c) 2013-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -18,7 +18,7 @@
#include <Swiften/Base/API.h>
#include <Swiften/Base/Override.h>
#include <Swiften/Jingle/JingleContentID.h>
-#include <Swiften/Elements/StreamInitiationFileInfo.h>
+#include <Swiften/Elements/JingleFileTransferFileInfo.h>
#include <Swiften/FileTransfer/OutgoingFileTransfer.h>
#include <Swiften/FileTransfer/JingleFileTransfer.h>
#include <Swiften/FileTransfer/FileTransferOptions.h>
@@ -40,7 +40,7 @@ namespace Swift {
boost::shared_ptr<ReadBytestream>,
FileTransferTransporterFactory*,
IDGenerator*,
- const StreamInitiationFileInfo&,
+ const JingleFileTransferFileInfo&,
const FileTransferOptions&,
CryptoProvider*);
virtual ~OutgoingJingleFileTransfer();
@@ -99,7 +99,7 @@ namespace Swift {
private:
IDGenerator* idGenerator;
boost::shared_ptr<ReadBytestream> stream;
- StreamInitiationFileInfo fileInfo;
+ JingleFileTransferFileInfo fileInfo;
FileTransferOptions options;
JingleContentID contentID;
IncrementalBytestreamHashCalculator* hashCalculator;
diff --git a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp
index a296b33..207f590 100644
--- a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp
+++ b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2013 Isode Limited.
+ * Copyright (c) 2013-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -22,14 +22,20 @@
#include <Swiften/Elements/IBB.h>
#include <Swiften/Elements/JingleIBBTransportPayload.h>
#include <Swiften/Elements/JingleS5BTransportPayload.h>
+#include <Swiften/Elements/JingleFileTransferDescription.h>
+#include <Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h>
#include <Swiften/FileTransfer/ByteArrayWriteBytestream.h>
#include <Swiften/FileTransfer/IncomingJingleFileTransfer.h>
#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h>
+#include <Swiften/Network/PlatformNetworkEnvironment.h>
#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h>
+#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h>
#include <Swiften/Jingle/FakeJingleSession.h>
+#include <Swiften/Network/NATTraverser.h>
#include <Swiften/Network/DummyTimerFactory.h>
#include <Swiften/EventLoop/DummyEventLoop.h>
#include <Swiften/Network/DummyConnectionFactory.h>
+#include <Swiften/Network/DummyConnectionServerFactory.h>
#include <Swiften/Network/PlatformNATTraversalWorker.h>
#include <Swiften/Queries/IQRouter.h>
#include <Swiften/Crypto/CryptoProvider.h>
@@ -42,53 +48,61 @@ using namespace boost;
class IncomingJingleFileTransferTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(IncomingJingleFileTransferTest);
- //CPPUNIT_TEST(test_AcceptOnyIBBSendsSessionAccept);
- //CPPUNIT_TEST(test_OnlyIBBTransferReceiveWorks);
+ CPPUNIT_TEST(test_AcceptOnyIBBSendsSessionAccept);
+ CPPUNIT_TEST(test_OnlyIBBTransferReceiveWorks);
//CPPUNIT_TEST(test_AcceptFailingS5BFallsBackToIBB);
CPPUNIT_TEST_SUITE_END();
public:
- // shared_ptr<IncomingJingleFileTransfer> createTestling() {
- // JID ourJID("our@jid.org/full");
- // return boost::shared_ptr<IncomingJingleFileTransfer>(new IncomingJingleFileTransfer(ourJID, shared_ptr<JingleSession>(session), jingleContentPayload, fakeRJTCSF.get(), fakeLJTCF.get(), iqRouter, bytestreamRegistry, bytestreamProxy, timerFactory, crypto.get()));
- // }
+ shared_ptr<IncomingJingleFileTransfer> createTestling() {
+ JID ourJID("our@jid.org/full");
+ return boost::make_shared<IncomingJingleFileTransfer>(ourJID, shared_ptr<JingleSession>(session), jingleContentPayload, ftTransporterFactory, timerFactory, crypto.get());
+ }
- // IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) {
- // IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb);
- // request->setFrom(from);
- // return request;
- // }
+ IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) {
+ IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb);
+ request->setFrom(from);
+ return request;
+ }
void setUp() {
crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
eventLoop = new DummyEventLoop();
session = boost::make_shared<FakeJingleSession>("foo@bar.com/baz", "mysession");
- // jingleContentPayload = make_shared<JingleContentPayload>();
+ jingleContentPayload = make_shared<JingleContentPayload>();
// fakeRJTCSF = make_shared<FakeRemoteJingleTransportCandidateSelectorFactory>();
// fakeLJTCF = make_shared<FakeLocalJingleTransportCandidateGeneratorFactory>();
- // stanzaChannel = new DummyStanzaChannel();
- // iqRouter = new IQRouter(stanzaChannel);
- // bytestreamRegistry = new SOCKS5BytestreamRegistry();
- // timerFactory = new DummyTimerFactory();
- // connectionFactory = new DummyConnectionFactory(eventLoop);
- // bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory);
+ stanzaChannel = new DummyStanzaChannel();
+ connectionFactory = new DummyConnectionFactory(eventLoop);
+ serverConnectionFactory = new DummyConnectionServerFactory(eventLoop);
+ iqRouter = new IQRouter(stanzaChannel);
+ bytestreamRegistry = new SOCKS5BytestreamRegistry();
+ networkEnvironment = new PlatformNetworkEnvironment();
+ natTraverser = new PlatformNATTraversalWorker(eventLoop);
+ bytestreamServerManager = new SOCKS5BytestreamServerManager(bytestreamRegistry, serverConnectionFactory, networkEnvironment, natTraverser);
+ idGenerator = new SimpleIDGenerator();
+ timerFactory = new DummyTimerFactory();
+ bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory);
+ ftTransporterFactory = new DefaultFileTransferTransporterFactory(bytestreamRegistry, bytestreamServerManager, bytestreamProxy, idGenerator, connectionFactory, timerFactory, crypto.get(), iqRouter);
}
void tearDown() {
- // delete bytestreamProxy;
- // delete connectionFactory;
- // delete timerFactory;
- // delete bytestreamRegistry;
- // delete iqRouter;
- // delete stanzaChannel;
+ delete ftTransporterFactory;
+ delete bytestreamServerManager;
+ delete bytestreamProxy;
+ delete connectionFactory;
+ delete timerFactory;
+ delete bytestreamRegistry;
+ delete iqRouter;
+ delete stanzaChannel;
delete eventLoop;
+ Log::setLogLevel(Log::error);
}
// Tests whether IncomingJingleFileTransfer would accept a IBB only file transfer.
-#if 0
void test_AcceptOnyIBBSendsSessionAccept() {
//1. create your test incoming file transfer
shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>();
- desc->addOffer(StreamInitiationFileInfo("foo.txt", "", 10));
+ desc->setFileInfo(JingleFileTransferFileInfo("foo.txt", "", 10));
jingleContentPayload->addDescription(desc);
JingleIBBTransportPayload::ref tpRef = make_shared<JingleIBBTransportPayload>();
tpRef->setSessionID("mysession");
@@ -107,7 +121,7 @@ public:
void test_OnlyIBBTransferReceiveWorks() {
//1. create your test incoming file transfer
shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>();
- desc->addOffer(StreamInitiationFileInfo("file.txt", "", 10));
+ desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10));
jingleContentPayload->addDescription(desc);
JingleIBBTransportPayload::ref tpRef = make_shared<JingleIBBTransportPayload>();
tpRef->setSessionID("mysession");
@@ -139,6 +153,8 @@ public:
shared_ptr<ByteArrayWriteBytestream> byteStream = make_shared<ByteArrayWriteBytestream>();
fileTransfer->accept(byteStream);
+ // candidates are gathered
+
// check whether accept has been called
FakeJingleSession::AcceptCall acceptCall = getCall<FakeJingleSession::AcceptCall>(0);
CPPUNIT_ASSERT_EQUAL(payLoad->getSessionID(), acceptCall.payload->getSessionID());
@@ -149,7 +165,7 @@ public:
CPPUNIT_ASSERT(s5bPayload->hasCandidateError());
// indicate transport replace (Romeo)
- session->onTransportReplaceReceived(getContentID(), addJingleIBBPayload());
+ session->handleTransportReplaceReceived(getContentID(), addJingleIBBPayload());
FakeJingleSession::AcceptTransportCall acceptTransportCall = getCall<FakeJingleSession::AcceptTransportCall>(2);
@@ -158,16 +174,16 @@ public:
stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a"));
CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData());
}
-
+#if 0
void test_S5BTransferReceiveTest() {
addFileTransferDescription();
JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload();
}
-
+#endif
private:
void addFileTransferDescription() {
shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>();
- desc->addOffer(StreamInitiationFileInfo("file.txt", "", 10));
+ desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10));
jingleContentPayload->addDescription(desc);
}
@@ -196,23 +212,26 @@ private:
CPPUNIT_ASSERT(cmd);
return *cmd;
}
-#endif
private:
EventLoop* eventLoop;
boost::shared_ptr<CryptoProvider> crypto;
boost::shared_ptr<FakeJingleSession> session;
-#if 0
shared_ptr<JingleContentPayload> jingleContentPayload;
- shared_ptr<FakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF;
- shared_ptr<FakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF;
+// shared_ptr<FakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF;
+// shared_ptr<FakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF;
+ FileTransferTransporterFactory* ftTransporterFactory;
+ SOCKS5BytestreamServerManager* bytestreamServerManager;
DummyStanzaChannel* stanzaChannel;
IQRouter* iqRouter;
SOCKS5BytestreamRegistry* bytestreamRegistry;
DummyConnectionFactory* connectionFactory;
+ DummyConnectionServerFactory* serverConnectionFactory;
SOCKS5BytestreamProxiesManager* bytestreamProxy;
DummyTimerFactory* timerFactory;
-#endif
+ NetworkEnvironment* networkEnvironment;
+ NATTraverser* natTraverser;
+ IDGenerator* idGenerator;
};
CPPUNIT_TEST_SUITE_REGISTRATION(IncomingJingleFileTransferTest);
diff --git a/Swiften/Jingle/FakeJingleSession.cpp b/Swiften/Jingle/FakeJingleSession.cpp
index 1df106a..3b94da7 100644
--- a/Swiften/Jingle/FakeJingleSession.cpp
+++ b/Swiften/Jingle/FakeJingleSession.cpp
@@ -4,7 +4,14 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#include <Swiften/Jingle/FakeJingleSession.h>
+#include <Swiften/Jingle/JingleSessionListener.h>
#include <boost/smart_ptr/make_shared.hpp>
@@ -50,4 +57,8 @@ void FakeJingleSession::sendTransportReplace(const JingleContentID& id, JingleTr
calledCommands.push_back(ReplaceTransportCall(id, payload));
}
+void FakeJingleSession::handleTransportReplaceReceived(const JingleContentID& contentID, JingleTransportPayload::ref transport) {
+ notifyListeners(&JingleSessionListener::handleTransportReplaceReceived, contentID, transport);
+}
+
}
diff --git a/Swiften/Jingle/FakeJingleSession.h b/Swiften/Jingle/FakeJingleSession.h
index 24e85d8..19028ad 100644
--- a/Swiften/Jingle/FakeJingleSession.h
+++ b/Swiften/Jingle/FakeJingleSession.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2013 Isode Limited.
+ * Copyright (c) 2013-2014 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -96,6 +96,8 @@ namespace Swift {
virtual void sendTransportReject(const JingleContentID&, JingleTransportPayload::ref) SWIFTEN_OVERRIDE;
virtual void sendTransportReplace(const JingleContentID&, JingleTransportPayload::ref) SWIFTEN_OVERRIDE;
+ void handleTransportReplaceReceived(const JingleContentID&, JingleTransportPayload::ref);
+
public:
std::vector<Command> calledCommands;
SimpleIDGenerator idGenerator;
diff --git a/Swiften/Network/DummyConnectionServer.h b/Swiften/Network/DummyConnectionServer.h
new file mode 100644
index 0000000..0cbce0e
--- /dev/null
+++ b/Swiften/Network/DummyConnectionServer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010-2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <boost/enable_shared_from_this.hpp>
+
+#include <Swiften/Base/API.h>
+#include <Swiften/Network/ConnectionServer.h>
+#include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/EventLoop/EventLoop.h>
+#include <Swiften/EventLoop/EventOwner.h>
+
+namespace Swift {
+ class SWIFTEN_API DummyConnectionServer : public ConnectionServer, public EventOwner, public boost::enable_shared_from_this<DummyConnectionServer> {
+ public:
+ DummyConnectionServer(EventLoop* eventLoop, int port) : eventLoop(eventLoop), localAddressPort(HostAddress(), port) {}
+ DummyConnectionServer(EventLoop* eventLoop, const Swift::HostAddress& hostAddress, int port) : eventLoop(eventLoop), localAddressPort(hostAddress, port) {}
+ virtual ~DummyConnectionServer() {}
+
+ virtual HostAddressPort getAddressPort() const {
+ return localAddressPort;
+ }
+
+ virtual boost::optional<Error> tryStart() {
+ return boost::optional<Error>();
+ }
+
+ virtual void start() {
+
+ }
+
+ virtual void stop() {
+
+ }
+
+ public:
+ EventLoop* eventLoop;
+ HostAddressPort localAddressPort;
+ };
+}
diff --git a/Swiften/Network/DummyConnectionServerFactory.h b/Swiften/Network/DummyConnectionServerFactory.h
new file mode 100644
index 0000000..6369452
--- /dev/null
+++ b/Swiften/Network/DummyConnectionServerFactory.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/Network/ConnectionServerFactory.h>
+#include <Swiften/Network/DummyConnectionServer.h>
+
+namespace Swift {
+
+class EventLoop;
+
+class DummyConnectionServerFactory : public ConnectionServerFactory {
+public:
+ DummyConnectionServerFactory(EventLoop* eventLoop) : eventLoop(eventLoop) {}
+ virtual ~DummyConnectionServerFactory() {}
+
+ virtual boost::shared_ptr<ConnectionServer> createConnectionServer(int port) {
+ return boost::make_shared<DummyConnectionServer>(eventLoop, port);
+ }
+
+ virtual boost::shared_ptr<ConnectionServer> createConnectionServer(const Swift::HostAddress& hostAddress, int port) {
+ return boost::make_shared<DummyConnectionServer>(eventLoop, hostAddress, port);
+ }
+
+private:
+ EventLoop* eventLoop;
+};
+
+}
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
index fe61c72..812e968 100644
--- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
+++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
@@ -78,6 +78,7 @@
#include <Swiften/Parser/PayloadParsers/StatusShowParser.h>
#include <Swiften/Parser/PayloadParsers/StorageParser.h>
#include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h>
+#include <Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h>
#include <Swiften/Parser/PayloadParsers/StreamInitiationParser.h>
#include <Swiften/Parser/PayloadParsers/SubjectParser.h>
#include <Swiften/Parser/PayloadParsers/UserLocationParser.h>
@@ -140,6 +141,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleS5BTransportMethodPayloadParser> >("transport", "urn:xmpp:jingle:transports:s5b:1"));
factories_.push_back(boost::make_shared<JingleFileTransferDescriptionParserFactory>(this));
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<StreamInitiationFileInfoParser> >("file", "http://jabber.org/protocol/si/profile/file-transfer"));
+ factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleFileTransferFileInfoParser> >("file", "urn:xmpp:jingle:apps:file-transfer:4"));
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleFileTransferReceivedParser> >("received", "urn:xmpp:jingle:apps:file-transfer:3"));
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleFileTransferHashParser> >("checksum"));
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<S5BProxyRequestParser> >("query", "http://jabber.org/protocol/bytestreams"));
diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp
index b394115..fb1836f 100644
--- a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp
+++ b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp
@@ -4,72 +4,59 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
-#include "JingleFileTransferDescriptionParser.h"
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h>
+
+#include <boost/optional.hpp>
+#include <boost/lexical_cast.hpp>
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
#include <Swiften/Parser/PayloadParserFactory.h>
-#include <Swiften/Base/Log.h>
+#include <Swiften/Base/DateTime.h>
+#include <Swiften/StringCodecs/Base64.h>
namespace Swift {
-JingleFileTransferDescriptionParser::JingleFileTransferDescriptionParser(PayloadParserFactoryCollection* factories) : factories(factories), level(0),
- currentElement(UnknownElement) {
-
+JingleFileTransferDescriptionParser::JingleFileTransferDescriptionParser(PayloadParserFactoryCollection* factories) : factories(factories), level(0) {
}
void JingleFileTransferDescriptionParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) {
- if (level == 0) {
-
- }
-
if (level == 1) {
- if (element == "offer") {
- currentElement = OfferElement;
- } else if (element == "request") {
- currentElement = RequestElement;
- } else {
- currentElement = UnknownElement;
- }
- }
-
- if (level == 2) {
PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes);
if (payloadParserFactory) {
currentPayloadParser.reset(payloadParserFactory->createPayloadParser());
}
}
- if (level >= 2 && currentPayloadParser) {
+ if (level >= 1 && currentPayloadParser) {
currentPayloadParser->handleStartElement(element, ns, attributes);
}
-
++level;
}
void JingleFileTransferDescriptionParser::handleEndElement(const std::string& element, const std::string& ns) {
--level;
- if (currentPayloadParser) {
- if (level >= 2) {
- currentPayloadParser->handleEndElement(element, ns);
- }
+ if (level >= 1 && currentPayloadParser) {
+ currentPayloadParser->handleEndElement(element, ns);
+ }
- if (level == 2) {
- boost::shared_ptr<StreamInitiationFileInfo> info = boost::dynamic_pointer_cast<StreamInitiationFileInfo>(currentPayloadParser->getPayload());
- if (info) {
- if (currentElement == OfferElement) {
- getPayloadInternal()->addOffer(*info);
- } else if (currentElement == RequestElement) {
- getPayloadInternal()->addRequest(*info);
- }
- }
+ if (level == 0) {
+ boost::shared_ptr<JingleFileTransferFileInfo> info = boost::dynamic_pointer_cast<JingleFileTransferFileInfo>(currentPayloadParser->getPayload());
+ if (info) {
+ getPayloadInternal()->setFileInfo(*info);
}
}
}
void JingleFileTransferDescriptionParser::handleCharacterData(const std::string& data) {
- if (level >= 2 && currentPayloadParser) {
+ if (level >= 1 && currentPayloadParser) {
currentPayloadParser->handleCharacterData(data);
}
}
-
+
}
diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h
index 7ea22b4..a1215c1 100644
--- a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h
+++ b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h
@@ -4,6 +4,12 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#pragma once
#include <Swiften/Elements/JingleFileTransferDescription.h>
@@ -20,18 +26,11 @@ class JingleFileTransferDescriptionParser : public GenericPayloadParser<JingleFi
virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);
virtual void handleEndElement(const std::string& element, const std::string&);
- virtual void handleCharacterData(const std::string& data);
+ virtual void handleCharacterData(const std::string& data);
private:
- enum CurrentParseElement {
- UnknownElement,
- RequestElement,
- OfferElement
- };
-
PayloadParserFactoryCollection* factories;
int level;
- CurrentParseElement currentElement;
boost::shared_ptr<PayloadParser> currentPayloadParser;
};
diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h
index b997c1d..7bd4b8a 100644
--- a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h
+++ b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h
@@ -4,6 +4,12 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#pragma once
#include <Swiften/Parser/GenericPayloadParserFactory.h>
@@ -19,7 +25,7 @@ namespace Swift {
}
virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const {
- return element == "description" && ns == "urn:xmpp:jingle:apps:file-transfer:3";
+ return element == "description" && ns == "urn:xmpp:jingle:apps:file-transfer:4";
}
virtual PayloadParser* createPayloadParser() {
diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.cpp b/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.cpp
new file mode 100644
index 0000000..2a62f23
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h>
+
+#include <boost/optional.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <Swiften/Base/DateTime.h>
+#include <Swiften/StringCodecs/Base64.h>
+
+namespace Swift {
+
+JingleFileTransferFileInfoParser::JingleFileTransferFileInfoParser() : level(0) {
+}
+
+template<typename T> boost::optional<T> safeLexicalCast(const std::string& str) {
+ boost::optional<T> ret;
+ try {
+ ret = boost::lexical_cast<T>(str);
+ } catch (boost::bad_lexical_cast &) {
+
+ }
+ return ret;
+}
+
+void JingleFileTransferFileInfoParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) {
+ charData.clear();
+ if (element == "hash") {
+ hashAlg = attributes.getAttributeValue("algo").get_value_or("");
+ }
+ else if (element == "range") {
+ rangeOffset = safeLexicalCast<boost::uintmax_t>(attributes.getAttributeValue("offset").get_value_or(""));
+ }
+
+ ++level;
+}
+
+void JingleFileTransferFileInfoParser::handleEndElement(const std::string& element, const std::string&) {
+ --level;
+ if (level == 1) {
+ if (element == "date") {
+ getPayloadInternal()->setDate(stringToDateTime(charData));
+ }
+ else if (element == "desc") {
+ getPayloadInternal()->setDescription(charData);
+ }
+ else if (element == "media-type") {
+ getPayloadInternal()->setMediaType(charData);
+ }
+ else if (element == "name") {
+ getPayloadInternal()->setName(charData);
+ }
+ else if (element == "size") {
+ boost::optional<boost::uintmax_t> size = safeLexicalCast<boost::uintmax_t>(charData);
+ if (size) {
+ getPayloadInternal()->setSize(size.get());
+ }
+ }
+ else if (element == "range") {
+ getPayloadInternal()->setSupportsRangeRequests(true);
+ if (rangeOffset) {
+ getPayloadInternal()->setRangeOffset(rangeOffset.get_value_or(0));
+ }
+ }
+ else if (element == "hash") {
+ getPayloadInternal()->addHash(HashElement(hashAlg, Base64::decode(charData)));
+ }
+ }
+}
+
+void JingleFileTransferFileInfoParser::handleCharacterData(const std::string& data) {
+ charData += data;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h b/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h
new file mode 100644
index 0000000..eb6245c
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Elements/JingleFileTransferFileInfo.h>
+#include <Swiften/Parser/GenericPayloadParser.h>
+
+namespace Swift {
+
+class JingleFileTransferFileInfoParser : public GenericPayloadParser<JingleFileTransferFileInfo> {
+ public:
+ JingleFileTransferFileInfoParser();
+
+ virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);
+ virtual void handleEndElement(const std::string& element, const std::string&);
+ virtual void handleCharacterData(const std::string& data);
+
+ private:
+ int level;
+ std::string charData;
+ std::string hashAlg;
+ boost::optional<boost::uintmax_t> rangeOffset;
+};
+
+}
diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp b/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp
index 87f8317..6a1a031 100644
--- a/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp
+++ b/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp
@@ -4,39 +4,54 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#include "JingleFileTransferHashParser.h"
#include <boost/shared_ptr.hpp>
#include <boost/algorithm/string.hpp>
-#include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h>
+#include <Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h>
#include <Swiften/Parser/GenericPayloadParserFactory.h>
#include <Swiften/Parser/PayloadParserFactory.h>
namespace Swift {
-JingleFileTransferHashParser::JingleFileTransferHashParser() {
+JingleFileTransferHashParser::JingleFileTransferHashParser() : level(0) {
}
-void JingleFileTransferHashParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) {
- if (element == "hash") {
- algo = attributes.getAttribute("algo");
+void JingleFileTransferHashParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) {
+ if (level == 1 && element == "file") {
+ currentPayloadParser = boost::make_shared<JingleFileTransferFileInfoParser>();
}
+
+ if (level >= 1 && currentPayloadParser) {
+ currentPayloadParser->handleStartElement(element, ns, attributes);
+ }
+ ++level;
}
-void JingleFileTransferHashParser::handleEndElement(const std::string& element, const std::string& ) {
- if (element == "hash" && !algo.empty() && !hash.empty()) {
- getPayloadInternal()->setHash(algo, hash);
- algo.clear();
- hash.clear();
+void JingleFileTransferHashParser::handleEndElement(const std::string& element, const std::string& ns) {
+ --level;
+ if (level >= 1 && currentPayloadParser) {
+ currentPayloadParser->handleEndElement(element, ns);
+ }
+
+ if (level == 1) {
+ boost::shared_ptr<JingleFileTransferFileInfo> info = boost::dynamic_pointer_cast<JingleFileTransferFileInfo>(currentPayloadParser->getPayload());
+ if (info) {
+ getPayloadInternal()->setFileInfo(*info);
+ }
}
}
void JingleFileTransferHashParser::handleCharacterData(const std::string& data) {
- if (!algo.empty()) {
- std::string new_data(data);
- boost::trim(new_data);
- hash += new_data;
+ if (level >= 1 && currentPayloadParser) {
+ currentPayloadParser->handleCharacterData(data);
}
}
diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h b/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h
index 35e4a05..5a7c6c5 100644
--- a/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h
+++ b/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h
@@ -4,6 +4,12 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#pragma once
#include <Swiften/Elements/JingleFileTransferHash.h>
@@ -20,8 +26,8 @@ public:
virtual void handleCharacterData(const std::string& data);
private:
- std::string algo;
- std::string hash;
+ int level;
+ boost::shared_ptr<PayloadParser> currentPayloadParser;
};
}
diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp
index cc69348..b3888d6 100644
--- a/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp
+++ b/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp
@@ -4,7 +4,13 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
-#include "StreamInitiationFileInfoParser.h"
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h>
#include <boost/optional.hpp>
#include <boost/lexical_cast.hpp>
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp
index 8c8601a..a6be599 100644
--- a/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp
+++ b/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp
@@ -16,7 +16,7 @@
#include <Swiften/Elements/JingleFileTransferReceived.h>
#include <Swiften/Elements/JingleFileTransferHash.h>
#include <Swiften/Base/DateTime.h>
-
+#include <Swiften/StringCodecs/Base64.h>
#include <Swiften/Base/Log.h>
using namespace Swift;
@@ -36,8 +36,6 @@ class JingleParserTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testParse_Xep0234_Example5);
CPPUNIT_TEST(testParse_Xep0234_Example8);
CPPUNIT_TEST(testParse_Xep0234_Example10);
- CPPUNIT_TEST(testParse_Xep0234_Example11);
- CPPUNIT_TEST(testParse_Xep0234_Example12);
CPPUNIT_TEST(testParse_Xep0260_Example1);
CPPUNIT_TEST(testParse_Xep0260_Example3);
@@ -223,40 +221,39 @@ class JingleParserTest : public CppUnit::TestFixture {
PayloadsParserTester parser;
CPPUNIT_ASSERT(parser.parse(
"<jingle xmlns='urn:xmpp:jingle:1'\n"
- " action='session-initiate'\n"
- " initiator='romeo@montague.lit/orchard'\n"
- " sid='851ba2'>\n"
- " <content creator='initiator' name='a-file-offer'>\n"
- " <description xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n"
- " <offer>\n"
- " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n"
- " date='1969-07-21T02:56:15Z'\n"
- " hash='552da749930852c69ae5d2141d3766b1'\n"
- " name='test.txt'\n"
- " size='1022'>\n"
- " <desc>This is a test. If this were a real file...</desc>\n"
- " <range/>\n"
- " </file>\n"
- " </offer>\n"
- " </description>\n"
- " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n"
- " mode='tcp'\n"
- " sid='vj3hs98y'>\n"
- " <candidate cid='hft54dqy'\n"
- " host='192.168.4.1'\n"
- " jid='romeo@montague.lit/orchard'\n"
- " port='5086'\n"
- " priority='8257636'\n"
- " type='direct'/>\n"
- " <candidate cid='hutr46fe'\n"
- " host='24.24.24.1'\n"
- " jid='romeo@montague.lit/orchard'\n"
- " port='5087'\n"
- " priority='8258636'\n"
- " type='direct'/>\n"
- " </transport>\n"
- " </content>\n"
- " </jingle>\n"
+ " action='session-initiate'\n"
+ " initiator='romeo@montague.lit/orchard'\n"
+ " sid='851ba2'>\n"
+ "<content creator='initiator' name='a-file-offer'>\n"
+ "<description xmlns='urn:xmpp:jingle:apps:file-transfer:4'>\n"
+ "<file>\n"
+ "<date>1969-07-21T02:56:15Z</date>\n"
+ "<desc>This is a test. If this were a real file...</desc>\n"
+ "<media-type>text/plain</media-type>\n"
+ "<name>test.txt</name>\n"
+ "<range/>\n"
+ "<size>1022</size>\n"
+ "<hash xmlns='urn:xmpp:hashes:1' algo='sha-1'>VS2nSZMIUsaa5dIUHTdmsQ==</hash>\n"
+ "</file>\n"
+ "</description>\n"
+ "<transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n"
+ " mode='tcp'\n"
+ " sid='vj3hs98y'>\n"
+ "<candidate cid='hft54dqy'\n"
+ " host='192.168.4.1'\n"
+ " jid='romeo@montague.lit/orchard'\n"
+ " port='5086'\n"
+ " priority='8257636'\n"
+ " type='direct'/>\n"
+ "<candidate cid='hutr46fe'\n"
+ " host='24.24.24.1'\n"
+ " jid='romeo@montague.lit/orchard'\n"
+ " port='5087'\n"
+ " priority='8258636'\n"
+ " type='direct'/>\n"
+ "</transport>\n"
+ "</content>\n"
+ "</jingle>\n"
));
JinglePayload::ref jingle = parser.getPayload<JinglePayload>();
@@ -270,16 +267,15 @@ class JingleParserTest : public CppUnit::TestFixture {
JingleFileTransferDescription::ref description = contents[0]->getDescription<JingleFileTransferDescription>();
-
- std::vector<StreamInitiationFileInfo> offers = description->getOffers();
- CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), offers.size());
- CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), offers[0].getName());
- CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), offers[0].getHash());
- CPPUNIT_ASSERT(1022 == offers[0].getSize());
- CPPUNIT_ASSERT_EQUAL(std::string("This is a test. If this were a real file..."), offers[0].getDescription());
- CPPUNIT_ASSERT_EQUAL(true, offers[0].getSupportsRangeRequests());
- CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == offers[0].getDate());
- CPPUNIT_ASSERT_EQUAL(std::string("md5"), offers[0].getAlgo());
+ CPPUNIT_ASSERT(description);
+ JingleFileTransferFileInfo fileInfo = description->getFileInfo();
+ CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), fileInfo.getName());
+ CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), fileInfo.getHashes().begin()->first);
+ CPPUNIT_ASSERT_EQUAL(std::string("VS2nSZMIUsaa5dIUHTdmsQ=="), Base64::encode(fileInfo.getHashes().begin()->second));
+ CPPUNIT_ASSERT(1022 == fileInfo.getSize());
+ CPPUNIT_ASSERT_EQUAL(std::string("This is a test. If this were a real file..."), fileInfo.getDescription());
+ CPPUNIT_ASSERT_EQUAL(true, fileInfo.getSupportsRangeRequests());
+ CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == fileInfo.getDate());
}
// http://xmpp.org/extensions/xep-0234.html#example-3
@@ -287,22 +283,21 @@ class JingleParserTest : public CppUnit::TestFixture {
PayloadsParserTester parser;
CPPUNIT_ASSERT(parser.parse(
"<jingle xmlns='urn:xmpp:jingle:1'\n"
- " action='session-accept'\n"
- " initiator='romeo@montague.lit/orchard'\n"
- " sid='851ba2'>\n"
- " <content creator='initiator' name='a-file-offer'>\n"
- " <description xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n"
- " <offer>\n"
- " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n"
- " name='test.txt'\n"
- " size='1022'\n"
- " hash='552da749930852c69ae5d2141d3766b1'\n"
- " date='1969-07-21T02:56:15Z'>\n"
- " <desc>This is a test. If this were a real file...</desc>\n"
- " <range/>\n"
- " </file>\n"
- " </offer>\n"
- " </description>\n"
+ " action='session-accept'\n"
+ " initiator='romeo@montague.lit/orchard'\n"
+ " sid='851ba2'>\n"
+ "<content creator='initiator' name='a-file-offer'>\n"
+ "<description xmlns='urn:xmpp:jingle:apps:file-transfer:4'>\n"
+ "<file>\n"
+ "<date>1969-07-21T02:56:15Z</date>\n"
+ "<desc>This is a test. If this were a real file...</desc>\n"
+ "<media-type>text/plain</media-type>\n"
+ "<name>test.txt</name>\n"
+ "<range/>\n"
+ "<size>1022</size>\n"
+ "<hash xmlns='urn:xmpp:hashes:1' algo='sha-1'>VS2nSZMIUsaa5dIUHTdmsQ==</hash>\n"
+ "</file>\n"
+ "</description>\n"
" <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n"
" mode='tcp'\n"
" sid='vj3hs98y'>\n"
@@ -340,16 +335,16 @@ class JingleParserTest : public CppUnit::TestFixture {
JingleFileTransferDescription::ref description = contents[0]->getDescription<JingleFileTransferDescription>();
+ CPPUNIT_ASSERT(description);
- std::vector<StreamInitiationFileInfo> offers = description->getOffers();
- CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), offers.size());
- CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), offers[0].getName());
- CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), offers[0].getHash());
- CPPUNIT_ASSERT(1022 == offers[0].getSize());
- CPPUNIT_ASSERT_EQUAL(std::string("This is a test. If this were a real file..."), offers[0].getDescription());
- CPPUNIT_ASSERT_EQUAL(true, offers[0].getSupportsRangeRequests());
- CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == offers[0].getDate());
- CPPUNIT_ASSERT_EQUAL(std::string("md5"), offers[0].getAlgo());
+ JingleFileTransferFileInfo fileInfo = description->getFileInfo();
+ CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), fileInfo.getName());
+ CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), fileInfo.getHashes().begin()->first);
+ CPPUNIT_ASSERT_EQUAL(std::string("VS2nSZMIUsaa5dIUHTdmsQ=="), Base64::encode(fileInfo.getHashes().begin()->second));
+ CPPUNIT_ASSERT(1022 == fileInfo.getSize());
+ CPPUNIT_ASSERT_EQUAL(std::string("This is a test. If this were a real file..."), fileInfo.getDescription());
+ CPPUNIT_ASSERT_EQUAL(true, fileInfo.getSupportsRangeRequests());
+ CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == fileInfo.getDate());
}
// http://xmpp.org/extensions/xep-0234.html#example-5
@@ -393,11 +388,9 @@ class JingleParserTest : public CppUnit::TestFixture {
" action='session-info'\n"
" initiator='romeo@montague.lit/orchard'\n"
" sid='a73sjjvkla37jfea'>\n"
- " <checksum xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n"
+ " <checksum xmlns='urn:xmpp:jingle:apps:file-transfer:4'>\n"
" <file>\n"
- " <hashes xmlns='urn:xmpp:hashes:0'>\n"
- " <hash algo='sha-1'>552da749930852c69ae5d2141d3766b1</hash>\n"
- " </hashes>\n"
+ " <hash xmlns='urn:xmpp:hashes:0' algo='sha-1'>VS2nSZMIUsaa5dIUHTdmsQ==</hash>\n"
" </file>\n"
" </checksum>\n"
"</jingle>\n"
@@ -410,12 +403,12 @@ class JingleParserTest : public CppUnit::TestFixture {
JingleFileTransferHash::ref hash = jingle->getPayload<JingleFileTransferHash>();
CPPUNIT_ASSERT(hash);
- CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), hash->getHashes().find("sha-1")->second);
-
+ CPPUNIT_ASSERT_EQUAL(std::string("VS2nSZMIUsaa5dIUHTdmsQ=="), Base64::encode(hash->getFileInfo().getHash("sha-1").get()));
}
// http://xmpp.org/extensions/xep-0234.html#example-10
void testParse_Xep0234_Example10() {
+ Log::setLogLevel(Log::debug);
PayloadsParserTester parser;
CPPUNIT_ASSERT(parser.parse(
"<jingle xmlns='urn:xmpp:jingle:1'\n"
@@ -423,13 +416,11 @@ class JingleParserTest : public CppUnit::TestFixture {
" initiator='romeo@montague.lit/orchard'\n"
" sid='uj3b2'>\n"
" <content creator='initiator' name='a-file-request'>\n"
- " <description xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n"
- " <request>\n"
- " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n"
- " hash='552da749930852c69ae5d2141d3766b1'>\n"
- " <range offset='270336'/>\n"
- " </file>\n"
- " </request>\n"
+ " <description xmlns='urn:xmpp:jingle:apps:file-transfer:4'>\n"
+ " <file>\n"
+ " <hash xmlns='urn:xmpp:hashes:1' algo='sha-1'>VS2nSZMIUsaa5dIUHTdmsQ==</hash>\n"
+ " <range offset='270336'/>\n"
+ " </file>\n"
" </description>\n"
" <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n"
" mode='tcp'\n"
@@ -466,101 +457,13 @@ class JingleParserTest : public CppUnit::TestFixture {
JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>();
CPPUNIT_ASSERT(content);
- StreamInitiationFileInfo file = content->getDescription<JingleFileTransferDescription>()->getRequests()[0];
- CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), file.getHash());
- CPPUNIT_ASSERT_EQUAL(static_cast<unsigned long long>(270336), file.getRangeOffset());
+ JingleFileTransferFileInfo file = content->getDescription<JingleFileTransferDescription>()->getFileInfo();
+ CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), file.getHashes().begin()->first);
+ CPPUNIT_ASSERT_EQUAL(std::string("VS2nSZMIUsaa5dIUHTdmsQ=="), Base64::encode(file.getHashes().begin()->second));
+ CPPUNIT_ASSERT_EQUAL(static_cast<boost::uintmax_t>(270336), file.getRangeOffset());
CPPUNIT_ASSERT_EQUAL(true, file.getSupportsRangeRequests());
}
- // http://xmpp.org/extensions/xep-0234.html#example-11
- void testParse_Xep0234_Example11() {
- PayloadsParserTester parser;
- CPPUNIT_ASSERT(parser.parse(
- "<jingle xmlns='urn:xmpp:jingle:1'\n"
- " action='session-initiate'\n"
- " initiator='romeo@montague.lit/orchard'\n"
- " sid='h2va419i'>\n"
- " <content creator='initiator' name='a-file-offer'>\n"
- " <description xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n"
- " <offer>\n"
- " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n"
- " date='2011-06-01T15:58:15Z'\n"
- " hash='a749930852c69ae5d2141d3766b1552d'\n"
- " name='somefile.txt'\n"
- " size='1234'/>\n"
- " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n"
- " date='2011-06-01T15:58:15Z'\n"
- " hash='930852c69ae5d2141d3766b1552da749'\n"
- " name='anotherfile.txt'\n"
- " size='2345'/>\n"
- " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n"
- " date='2011-06-01T15:58:15Z'\n"
- " hash='52c69ae5d2141d3766b1552da7499308'\n"
- " name='yetanotherfile.txt'\n"
- " size='3456'/>\n"
- " </offer>\n"
- " </description>\n"
- " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n"
- " mode='tcp'\n"
- " sid='vj3hs98y'>\n"
- " <candidate cid='hft54dqy'\n"
- " host='192.168.4.1'\n"
- " jid='romeo@montague.lit/orchard'\n"
- " port='5086'\n"
- " priority='8257636'\n"
- " type='direct'/>\n"
- " <candidate cid='hutr46fe'\n"
- " host='24.24.24.1'\n"
- " jid='romeo@montague.lit/orchard'\n"
- " port='5087'\n"
- " priority='8258636'\n"
- " type='direct'/>\n"
- " </transport>\n"
- " </content>\n"
- "</jingle>\n"
- ));
-
- JinglePayload::ref jingle = parser.getPayload<JinglePayload>();
- CPPUNIT_ASSERT(jingle);
- CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInitiate, jingle->getAction());
- CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator());
- CPPUNIT_ASSERT_EQUAL(std::string("h2va419i"), jingle->getSessionID());
-
- JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>();
- CPPUNIT_ASSERT(content);
- CPPUNIT_ASSERT_EQUAL(JingleContentPayload::InitiatorCreator, content->getCreator());
- CPPUNIT_ASSERT_EQUAL(std::string("a-file-offer"), content->getName());
-
- std::vector<StreamInitiationFileInfo> offers = content->getDescription<JingleFileTransferDescription>()->getOffers();
- CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), offers.size());
- }
-
- // http://xmpp.org/extensions/xep-0234.html#example-12
- void testParse_Xep0234_Example12() {
- PayloadsParserTester parser;
- CPPUNIT_ASSERT(parser.parse(
- "<jingle xmlns='urn:xmpp:jingle:1'\n"
- " action='session-info'\n"
- " initiator='romeo@montague.lit/orchard'\n"
- " sid='a73sjjvkla37jfea'>\n"
- " <received xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n"
- " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n"
- " hash='a749930852c69ae5d2141d3766b1552d'/>\n"
- " </received>\n"
- "</jingle>\n"
- ));
-
- JinglePayload::ref jingle = parser.getPayload<JinglePayload>();
- CPPUNIT_ASSERT(jingle);
- CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInfo, jingle->getAction());
- CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator());
- CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID());
-
- boost::shared_ptr<JingleFileTransferReceived> received = jingle->getPayload<JingleFileTransferReceived>();
- CPPUNIT_ASSERT(received);
- CPPUNIT_ASSERT_EQUAL(std::string("a749930852c69ae5d2141d3766b1552d"), received->getFileInfo().getHash());
- }
-
// http://xmpp.org/extensions/xep-0260.html#example-1
void testParse_Xep0260_Example1() {
PayloadsParserTester parser;
diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript
index 94ea6d3..4bdf66f 100644
--- a/Swiften/Parser/SConscript
+++ b/Swiften/Parser/SConscript
@@ -38,6 +38,7 @@ sources = [
"PayloadParsers/JingleFileTransferDescriptionParser.cpp",
"PayloadParsers/JingleFileTransferReceivedParser.cpp",
"PayloadParsers/JingleFileTransferHashParser.cpp",
+ "PayloadParsers/JingleFileTransferFileInfoParser.cpp",
"PayloadParsers/StreamInitiationFileInfoParser.cpp",
"PayloadParsers/CommandParser.cpp",
"PayloadParsers/InBandRegistrationPayloadParser.cpp",
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 877b084..147f7a6 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -235,6 +235,7 @@ if env["SCONS_STAGE"] == "build" :
"Serializer/PayloadSerializers/MAMResultSerializer.cpp",
"Serializer/PayloadSerializers/MAMQuerySerializer.cpp",
"Serializer/PayloadSerializers/IsodeIQDelegationSerializer.cpp",
+ "Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp",
"Serializer/PresenceSerializer.cpp",
"Serializer/StanzaSerializer.cpp",
"Serializer/StreamErrorSerializer.cpp",
diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
index 4a4d678..a9a1ae3 100644
--- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
+++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
@@ -32,6 +32,7 @@
#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.h>
+#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.h>
@@ -127,6 +128,7 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() {
serializers_.push_back(new IdleSerializer());
serializers_.push_back(new StreamInitiationFileInfoSerializer());
+ serializers_.push_back(new JingleFileTransferFileInfoSerializer());
serializers_.push_back(new JingleContentPayloadSerializer());
serializers_.push_back(new JingleFileTransferDescriptionSerializer());
serializers_.push_back(new JingleFileTransferHashSerializer());
diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp
index 16337ff..bbe1510 100644
--- a/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp
@@ -4,17 +4,27 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h>
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/lexical_cast.hpp>
#include <Swiften/Base/foreach.h>
+#include <Swiften/Base/DateTime.h>
+#include <Swiften/StringCodecs/Base64.h>
+
#include <Swiften/Serializer/XML/XMLNode.h>
#include <Swiften/Serializer/XML/XMLElement.h>
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
-#include <Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h>
+#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h>
namespace Swift {
@@ -22,24 +32,11 @@ JingleFileTransferDescriptionSerializer::JingleFileTransferDescriptionSerializer
}
std::string JingleFileTransferDescriptionSerializer::serializePayload(boost::shared_ptr<JingleFileTransferDescription> payload) const {
- XMLElement description("description", "urn:xmpp:jingle:apps:file-transfer:3");
- StreamInitiationFileInfoSerializer fileInfoSerializer;
- if (!payload->getOffers().empty()) {
- boost::shared_ptr<XMLElement> offers = boost::make_shared<XMLElement>("offer");
- foreach(const StreamInitiationFileInfo &fileInfo, payload->getOffers()) {
- boost::shared_ptr<XMLRawTextNode> fileInfoXML = boost::make_shared<XMLRawTextNode>(fileInfoSerializer.serialize(boost::make_shared<StreamInitiationFileInfo>(fileInfo)));
- offers->addNode(fileInfoXML);
- }
- description.addNode(offers);
- }
- if (!payload->getRequests().empty()) {
- boost::shared_ptr<XMLElement> requests = boost::make_shared<XMLElement>("request");
- foreach(const StreamInitiationFileInfo &fileInfo, payload->getRequests()) {
- boost::shared_ptr<XMLRawTextNode> fileInfoXML = boost::make_shared<XMLRawTextNode>(fileInfoSerializer.serialize(boost::make_shared<StreamInitiationFileInfo>(fileInfo)));
- requests->addNode(fileInfoXML);
- }
- description.addNode(requests);
- }
+ XMLElement description("description", "urn:xmpp:jingle:apps:file-transfer:4");
+
+ JingleFileTransferFileInfoSerializer fileInfoSerializer;
+ boost::shared_ptr<XMLRawTextNode> fileInfoXML = boost::make_shared<XMLRawTextNode>(fileInfoSerializer.serialize(boost::make_shared<JingleFileTransferFileInfo>(payload->getFileInfo())));
+ description.addNode(fileInfoXML);
return description.serialize();
}
diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp
new file mode 100644
index 0000000..1a675d0
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Base/DateTime.h>
+#include <Swiften/Serializer/XML/XMLElement.h>
+#include <Swiften/Serializer/XML/XMLRawTextNode.h>
+#include <Swiften/Serializer/XML/XMLTextNode.h>
+#include <Swiften/StringCodecs/Base64.h>
+
+namespace Swift {
+
+JingleFileTransferFileInfoSerializer::JingleFileTransferFileInfoSerializer() {
+}
+
+std::string JingleFileTransferFileInfoSerializer::serializePayload(boost::shared_ptr<JingleFileTransferFileInfo> fileInfo) const {
+
+ XMLElement fileElement("file", "");
+
+ if (fileInfo->getDate() != stringToDateTime("")) {
+ fileElement.addNode(boost::make_shared<XMLElement>("date", "", dateTimeToString(fileInfo->getDate())));
+ }
+
+ if (!fileInfo->getDescription().empty()) {
+ fileElement.addNode(boost::make_shared<XMLElement>("desc", "", fileInfo->getDescription()));
+ }
+
+ if (!fileInfo->getMediaType().empty()) {
+ fileElement.addNode(boost::make_shared<XMLElement>("media-type", "", fileInfo->getMediaType()));
+ }
+
+ if (!fileInfo->getName().empty()) {
+ fileElement.addNode(boost::make_shared<XMLElement>("name", "", fileInfo->getName()));
+ }
+
+ if (fileInfo->getSupportsRangeRequests()) {
+ boost::shared_ptr<XMLElement> range = boost::make_shared<XMLElement>("range");
+ if (fileInfo->getRangeOffset() != 0) {
+ range->setAttribute("offset", boost::lexical_cast<std::string>(fileInfo->getRangeOffset()));
+ }
+ fileElement.addNode(range);
+ }
+
+ if (fileInfo->getSize() > 0) {
+ fileElement.addNode(boost::make_shared<XMLElement>("size", "", boost::lexical_cast<std::string>(fileInfo->getSize())));
+ }
+
+ foreach (JingleFileTransferFileInfo::HashElementMap::value_type hashElement, fileInfo->getHashes()) {
+ boost::shared_ptr<XMLElement> hash = boost::make_shared<XMLElement>("hash", "urn:xmpp:hashes:1", Base64::encode(hashElement.second));
+ hash->setAttribute("algo", hashElement.first);
+ fileElement.addNode(hash);
+ }
+
+ return fileElement.serialize();
+}
+
+}
diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h b/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h
new file mode 100644
index 0000000..0c9f2de
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2014 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/API.h>
+#include <Swiften/Serializer/GenericPayloadSerializer.h>
+#include <Swiften/Elements/JingleFileTransferFileInfo.h>
+
+#include <Swiften/Serializer/XML/XMLElement.h>
+
+namespace Swift {
+ class PayloadSerializerCollection;
+
+ class SWIFTEN_API JingleFileTransferFileInfoSerializer : public GenericPayloadSerializer<JingleFileTransferFileInfo> {
+ public:
+ JingleFileTransferFileInfoSerializer();
+
+ virtual std::string serializePayload(boost::shared_ptr<JingleFileTransferFileInfo>) const;
+ };
+}
diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp
index 2bd3afa..f416ddc 100644
--- a/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp
@@ -4,6 +4,12 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h>
#include <string>
@@ -16,7 +22,7 @@
#include <Swiften/Serializer/XML/XMLNode.h>
#include <Swiften/Serializer/XML/XMLElement.h>
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
-
+#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h>
namespace Swift {
@@ -27,17 +33,14 @@ std::string JingleFileTransferHashSerializer::serializePayload(boost::shared_ptr
// code for version urn:xmpp:jingle:apps:file-transfer:2
//XMLElement hash("hash", "urn:xmpp:jingle:apps:file-transfer:info:2", payload->getHash());
- // code for version urn:xmpp:jingle:apps:file-transfer:3
- XMLElement checksum("checksum", "urn:xmpp:jingle:apps:file-transfer:3");
- boost::shared_ptr<XMLElement> file = boost::make_shared<XMLElement>("file");
+ // code for version urn:xmpp:jingle:apps:file-transfer:4
+ XMLElement checksum("checksum", "urn:xmpp:jingle:apps:file-transfer:4");
+
+ JingleFileTransferFileInfoSerializer fileSerializer;
+
+ boost::shared_ptr<XMLRawTextNode> file = boost::make_shared<XMLRawTextNode>(fileSerializer.serialize(boost::make_shared<JingleFileTransferFileInfo>(payload->getFileInfo())));
+
checksum.addNode(file);
- boost::shared_ptr<XMLElement> hashes = boost::make_shared<XMLElement>("hashes", "urn:xmpp:hashes:0");
- file->addNode(hashes);
- foreach(const JingleFileTransferHash::HashesMap::value_type& pair, payload->getHashes()) {
- boost::shared_ptr<XMLElement> hash = boost::make_shared<XMLElement>("hash", "", pair.second);
- hash->setAttribute("algo", pair.first);
- hashes->addNode(hash);
- }
return checksum.serialize();
}
diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp
index e3ec8fc..722c039 100644
--- a/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp
+++ b/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp
@@ -4,6 +4,12 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
@@ -15,13 +21,14 @@
#include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h>
#include <Swiften/Elements/JingleFileTransferDescription.h>
-#include <Swiften/Elements/StreamInitiationFileInfo.h>
+#include <Swiften/Elements/JingleFileTransferFileInfo.h>
#include <Swiften/Elements/JingleIBBTransportPayload.h>
#include <Swiften/Elements/JingleS5BTransportPayload.h>
#include <Swiften/Elements/JingleFileTransferHash.h>
#include <Swiften/Elements/JinglePayload.h>
#include <Swiften/Elements/JingleFileTransferReceived.h>
#include <Swiften/Base/DateTime.h>
+#include <Swiften/StringCodecs/Base64.h>
using namespace Swift;
@@ -38,7 +45,6 @@ class JingleSerializersTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testSerialize_Xep0234_Example3);
CPPUNIT_TEST(testSerialize_Xep0234_Example5);
CPPUNIT_TEST(testSerialize_Xep0234_Example8);
- CPPUNIT_TEST(testSerialize_Xep0234_Example10);
CPPUNIT_TEST(testSerialize_Xep0234_Example13);
CPPUNIT_TEST(testSerialize_Xep0260_Example1);
@@ -179,30 +185,27 @@ class JingleSerializersTest : public CppUnit::TestFixture {
// http://xmpp.org/extensions/xep-0234.html#example-1
void testSerialize_Xep0234_Example1() {
- std::string expected = "<description xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">"
- "<offer>"
- "<file"
- " date=\"1969-07-21T02:56:15Z\""
- " hash=\"552da749930852c69ae5d2141d3766b1\""
- " name=\"test.txt\""
- " size=\"1022\""
- " xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">"
- "<desc>This is a test. If this were a real file...</desc>"
- "<range/>"
- "</file>"
- "</offer>"
- "</description>";
+ std::string expected = "<description xmlns=\"urn:xmpp:jingle:apps:file-transfer:4\">"
+ "<file>"
+ "<date>1969-07-21T02:56:15Z</date>"
+ "<desc>This is a test. If this were a real file...</desc>"
+ "<name>test.txt</name>"
+ "<range/>"
+ "<size>1022</size>"
+ "<hash algo=\"sha-1\" xmlns=\"urn:xmpp:hashes:1\">VS2nSZMIUsaa5dIUHTdmsQ==</hash>"
+ "</file>"
+ "</description>";
JingleFileTransferDescription::ref desc = boost::make_shared<JingleFileTransferDescription>();
- StreamInitiationFileInfo fileInfo;
+ JingleFileTransferFileInfo fileInfo;
fileInfo.setDate(stringToDateTime("1969-07-21T02:56:15Z"));
- fileInfo.setHash("552da749930852c69ae5d2141d3766b1");
+ fileInfo.addHash(HashElement("sha-1", Base64::decode("VS2nSZMIUsaa5dIUHTdmsQ==")));
fileInfo.setSize(1022);
fileInfo.setName("test.txt");
fileInfo.setDescription("This is a test. If this were a real file...");
fileInfo.setSupportsRangeRequests(true);
- desc->addOffer(fileInfo);
+ desc->setFileInfo(fileInfo);
CPPUNIT_ASSERT_EQUAL(expected, boost::make_shared<JingleFileTransferDescriptionSerializer>()->serialize(desc));
}
@@ -215,18 +218,15 @@ class JingleSerializersTest : public CppUnit::TestFixture {
" sid=\"851ba2\""
" xmlns=\"urn:xmpp:jingle:1\">"
"<content creator=\"initiator\" name=\"a-file-offer\">"
- "<description xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">"
- "<offer>"
- "<file"
- " date=\"1969-07-21T02:56:15Z\""
- " hash=\"552da749930852c69ae5d2141d3766b1\""
- " name=\"test.txt\""
- " size=\"1022\""
- " xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">"
- "<desc>This is a test. If this were a real file...</desc>"
- "<range/>"
- "</file>"
- "</offer>"
+ "<description xmlns=\"urn:xmpp:jingle:apps:file-transfer:4\">"
+ "<file>"
+ "<date>1969-07-21T02:56:15Z</date>"
+ "<desc>This is a test. If this were a real file...</desc>"
+ "<name>test.txt</name>"
+ "<range/>"
+ "<size>1022</size>"
+ "<hash algo=\"sha-1\" xmlns=\"urn:xmpp:hashes:1\">VS2nSZMIUsaa5dIUHTdmsQ==</hash>"
+ "</file>"
"</description>"
/*"<transport xmlns=\"urn:xmpp:jingle:transports:s5b:1\""
" mode=\"tcp\""
@@ -263,15 +263,15 @@ class JingleSerializersTest : public CppUnit::TestFixture {
content->setName("a-file-offer");
JingleFileTransferDescription::ref description = boost::make_shared<JingleFileTransferDescription>();
- StreamInitiationFileInfo fileInfo;
+ JingleFileTransferFileInfo fileInfo;
fileInfo.setName("test.txt");
fileInfo.setSize(1022);
- fileInfo.setHash("552da749930852c69ae5d2141d3766b1");
+ fileInfo.addHash(HashElement("sha-1", Base64::decode("VS2nSZMIUsaa5dIUHTdmsQ==")));
fileInfo.setDate(stringToDateTime("1969-07-21T02:56:15Z"));
fileInfo.setDescription("This is a test. If this were a real file...");
fileInfo.setSupportsRangeRequests(true);
- description->addOffer(fileInfo);
+ description->setFileInfo(fileInfo);
content->addDescription(description);
payload->addPayload(content);
@@ -316,11 +316,9 @@ class JingleSerializersTest : public CppUnit::TestFixture {
" initiator=\"romeo@montague.lit/orchard\""
" sid=\"a73sjjvkla37jfea\""
" xmlns=\"urn:xmpp:jingle:1\">"
- "<checksum xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">"
+ "<checksum xmlns=\"urn:xmpp:jingle:apps:file-transfer:4\">"
"<file>"
- "<hashes xmlns=\"urn:xmpp:hashes:0\">"
- "<hash algo=\"sha-1\">552da749930852c69ae5d2141d3766b1</hash>"
- "</hashes>"
+ "<hash algo=\"sha-1\" xmlns=\"urn:xmpp:hashes:1\">VS2nSZMIUsaa5dIUHTdmsQ==</hash>"
"</file>"
"</checksum>"
"</jingle>";
@@ -331,82 +329,12 @@ class JingleSerializersTest : public CppUnit::TestFixture {
payload->setSessionID("a73sjjvkla37jfea");
JingleFileTransferHash::ref hash = boost::make_shared<JingleFileTransferHash>();
- hash->setHash("sha-1", "552da749930852c69ae5d2141d3766b1");
+ hash->getFileInfo().addHash(HashElement("sha-1", Base64::decode("VS2nSZMIUsaa5dIUHTdmsQ==")));
payload->addPayload(hash);
CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload));
}
-
- // http://xmpp.org/extensions/xep-0234.html#example-10
- void testSerialize_Xep0234_Example10() {
- std::string expected =
- "<jingle"
- " action=\"session-initiate\""
- " initiator=\"romeo@montague.lit/orchard\""
- " sid=\"uj3b2\""
- " xmlns=\"urn:xmpp:jingle:1\">"
- "<content creator=\"initiator\" name=\"a-file-request\">"
- "<description"
- " xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">"
- "<request>"
- "<file"
- " hash=\"552da749930852c69ae5d2141d3766b1\""
- " xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">"
- "<range offset=\"270336\"/>"
- "</file>"
- "</request>"
- "</description>"
- /*"<transport"
- " mode=\"tcp\""
- " sid=\"xig361fj\""
- " xmlns=\"urn:xmpp:jingle:transports:s5b:1\">"
- "<candidate"
- " cid=\"ht567dq\""
- " host=\"192.169.1.10\""
- " jid=\"juliet@capulet.lit/balcony\""
- " port=\"6539\""
- " priority=\"8257636\""
- " type=\"direct\"/>"
- "<candidate"
- " cid=\"hr65dqyd\""
- " host=\"134.102.201.180\""
- " jid=\"juliet@capulet.lit/balcony\""
- " port=\"16453\""
- " priority=\"7929856\""
- " type=\"assisted\"/>"
- "<candidate"
- " cid=\"grt654q2\""
- " host=\"2001:638:708:30c9:219:d1ff:fea4:a17d\""
- " jid=\"juliet@capulet.lit/balcony\""
- " port=\"6539\""
- " priority=\"8257606\""
- " type=\"direct\"/>"
- "</transport>"*/
- "</content>"
- "</jingle>";
-
- JinglePayload::ref payload = boost::make_shared<JinglePayload>();
- payload->setAction(JinglePayload::SessionInitiate);
- payload->setInitiator(JID("romeo@montague.lit/orchard"));
- payload->setSessionID("uj3b2");
-
- StreamInitiationFileInfo fileInfo;
- fileInfo.setHash("552da749930852c69ae5d2141d3766b1");
- fileInfo.setRangeOffset(270336);
-
- JingleFileTransferDescription::ref desc = boost::make_shared<JingleFileTransferDescription>();
- desc->addRequest(fileInfo);
-
- JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>();
- content->setCreator(JingleContentPayload::InitiatorCreator);
- content->setName("a-file-request");
- content->addDescription(desc);
-
- payload->addPayload(content);
-
- CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload));
- }
// http://xmpp.org/extensions/xep-0234.html#example-10
void testSerialize_Xep0234_Example13() {