summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordknn <yoann.blein@free.fr>2012-06-03 13:11:35 (GMT)
committerdknn <yoann.blein@free.fr>2012-09-22 08:53:12 (GMT)
commit931b52184bf37f298f9c967883a3b71c912f834b (patch)
treedf2b6d80fb76d3ccbe1c721d3e574d0f2491c90a /Swiften/Parser
parent174d01d9812694d201f6f3939fc7b8bf4650cfa2 (diff)
downloadswift-contrib-931b52184bf37f298f9c967883a3b71c912f834b.zip
swift-contrib-931b52184bf37f298f9c967883a3b71c912f834b.tar.bz2
Add parsing add related tests for RTP description
Diffstat (limited to 'Swiften/Parser')
-rw-r--r--Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp4
-rw-r--r--Swiften/Parser/PayloadParsers/JingleRTPDescriptionParser.cpp80
-rw-r--r--Swiften/Parser/PayloadParsers/JingleRTPDescriptionParser.h38
-rw-r--r--Swiften/Parser/PayloadParsers/JingleRTPDescriptionParserFactory.h35
-rw-r--r--Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.cpp14
-rw-r--r--Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h2
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp115
-rw-r--r--Swiften/Parser/SConscript2
8 files changed, 281 insertions, 9 deletions
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
index a40e8f6..e6f3f60 100644
--- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
+++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
@@ -67,6 +67,8 @@
#include <Swiften/Parser/PayloadParsers/DeliveryReceiptParserFactory.h>
#include <Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParserFactory.h>
#include <Swiften/Parser/PayloadParsers/WhiteboardParser.h>
+#include <Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h>
+#include <Swiften/Parser/PayloadParsers/JingleRTPDescriptionParserFactory.h>
using namespace boost;
@@ -128,6 +130,8 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<WhiteboardParser> >("wb", "http://swift.im/whiteboard"));
factories_.push_back(boost::make_shared<DeliveryReceiptParserFactory>());
factories_.push_back(boost::make_shared<DeliveryReceiptRequestParserFactory>());
+ factories_.push_back(boost::make_shared<JingleRTPDescriptionParserFactory>(this));
+ factories_.push_back(boost::make_shared<GenericPayloadParserFactory<RTPPayloadTypeParser> >("payload-type"));
foreach(shared_ptr<PayloadParserFactory> factory, factories_) {
addFactory(factory.get());
diff --git a/Swiften/Parser/PayloadParsers/JingleRTPDescriptionParser.cpp b/Swiften/Parser/PayloadParsers/JingleRTPDescriptionParser.cpp
new file mode 100644
index 0000000..7429b39
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/JingleRTPDescriptionParser.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "JingleRTPDescriptionParser.h"
+
+#include <Swiften/Parser/PayloadParserFactoryCollection.h>
+#include <Swiften/Parser/PayloadParserFactory.h>
+
+#include <boost/optional.hpp>
+
+namespace Swift {
+
+JingleRTPDescriptionParser::JingleRTPDescriptionParser(PayloadParserFactoryCollection* factories) :
+ factories(factories), level(0), parsingBandwidth(false) {
+
+}
+
+void JingleRTPDescriptionParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) {
+ if (level == 0) {
+ const std::string& media = attributes.getAttributeValue("media").get_value_or("");
+ getPayloadInternal()->setMedia(mediaTypeFromString(media));
+ }
+
+ if (level == 1) {
+ if (element == "bandwidth") {
+ parsingBandwidth = true;
+ bandwidthType = attributes.getAttributeValue("type").get_value_or("");
+ } else {
+ PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes);
+ if (payloadParserFactory) {
+ currentPayloadParser.reset(payloadParserFactory->createPayloadParser());
+ }
+ }
+ }
+
+ if (level >= 1 && currentPayloadParser && !parsingBandwidth) {
+ currentPayloadParser->handleStartElement(element, ns, attributes);
+ }
+
+ ++level;
+}
+
+void JingleRTPDescriptionParser::handleEndElement(const std::string& element, const std::string& ns) {
+ --level;
+ if (element == "bandwidth") {
+ parsingBandwidth = false;
+ getPayloadInternal()->setBandwidth(bandwidthType, bandwidthValue);
+ } else if (currentPayloadParser) {
+ if (level >= 1) {
+ currentPayloadParser->handleEndElement(element, ns);
+ }
+ if (level == 1) {
+ RTPPayloadType::ref payloadType = boost::dynamic_pointer_cast<RTPPayloadType>(currentPayloadParser->getPayload());
+ if (payloadType) {
+ getPayloadInternal()->addPayloadType(*payloadType);
+ }
+ }
+ }
+}
+
+void JingleRTPDescriptionParser::handleCharacterData(const std::string& data) {
+ if (level == 2 && parsingBandwidth) {
+ bandwidthValue += data;
+ }
+}
+
+JingleRTPDescription::MediaType JingleRTPDescriptionParser::mediaTypeFromString(const std::string& media) const {
+ if (media == "audio") {
+ return JingleRTPDescription::Audio;
+ } else if (media == "video") {
+ return JingleRTPDescription::Video;
+ } else {
+ return JingleRTPDescription::Unknown;
+ }
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/JingleRTPDescriptionParser.h b/Swiften/Parser/PayloadParsers/JingleRTPDescriptionParser.h
new file mode 100644
index 0000000..d250754
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/JingleRTPDescriptionParser.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Elements/JingleRTPDescription.h>
+#include <Swiften/Parser/GenericPayloadParser.h>
+#include <Swiften/Parser/PayloadParser.h>
+
+namespace Swift {
+
+class PayloadParserFactoryCollection;
+
+class JingleRTPDescriptionParser : public GenericPayloadParser<JingleRTPDescription> {
+ public:
+ JingleRTPDescriptionParser(PayloadParserFactoryCollection* factories);
+
+ virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);
+ virtual void handleEndElement(const std::string& element, const std::string& ns);
+ virtual void handleCharacterData(const std::string& data);
+
+ private:
+ JingleRTPDescription::MediaType mediaTypeFromString(const std::string& media) const;
+
+ private:
+ PayloadParserFactoryCollection* factories;
+ int level;
+ //CurrentParseElement currentElement;
+ boost::shared_ptr<PayloadParser> currentPayloadParser;
+ bool parsingBandwidth;
+ std::string bandwidthType;
+ std::string bandwidthValue;
+};
+
+}
diff --git a/Swiften/Parser/PayloadParsers/JingleRTPDescriptionParserFactory.h b/Swiften/Parser/PayloadParsers/JingleRTPDescriptionParserFactory.h
new file mode 100644
index 0000000..90d32eb
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/JingleRTPDescriptionParserFactory.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Parser/GenericPayloadParserFactory.h>
+#include <Swiften/Parser/PayloadParsers/JingleRTPDescriptionParser.h>
+
+namespace Swift {
+
+ class PayloadParserFactoryCollection;
+
+ class JingleRTPDescriptionParserFactory : public PayloadParserFactory {
+ public:
+ JingleRTPDescriptionParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) {
+ }
+
+ virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const {
+ return element == "description" && ns == "urn:xmpp:jingle:apps:rtp:1";
+ }
+
+ virtual PayloadParser* createPayloadParser() {
+ return new JingleRTPDescriptionParser(factories);
+ }
+
+ private:
+ PayloadParserFactoryCollection* factories;
+
+ };
+}
+
+
diff --git a/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.cpp b/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.cpp
index 56fe109..f9d9bb3 100644
--- a/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.cpp
+++ b/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.cpp
@@ -8,9 +8,7 @@
#include <boost/optional.hpp>
#include <boost/lexical_cast.hpp>
-
-//#include <Swiften/Base/DateTime.h>
-//#include <Swiften/Base/Log.h>
+#include <boost/numeric/conversion/cast.hpp>
namespace Swift {
@@ -20,7 +18,7 @@ RTPPayloadTypeParser::RTPPayloadTypeParser() : level(0) {
void RTPPayloadTypeParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) {
if (level == 0) {
- // channel
+ // channels
try {
getPayloadInternal()->setChannels(boost::lexical_cast<boost::uint32_t>(attributes.getAttributeValue("channels").get_value_or("1")));
} catch (boost::bad_lexical_cast &) {
@@ -34,9 +32,9 @@ void RTPPayloadTypeParser::handleStartElement(const std::string& element, const
}
// ID
try {
- getPayloadInternal()->setID(boost::lexical_cast<boost::uint8_t>(attributes.getAttributeValue("id").get_value_or("0")));
+ getPayloadInternal()->setID(boost::numeric_cast<boost::uint8_t>(boost::lexical_cast<int>(attributes.getAttributeValue("id").get_value_or("0"))));
} catch (boost::bad_lexical_cast &) {
- getPayloadInternal()->setID(0);
+ getPayloadInternal()->setID(151);
}
// maxptime
try {
@@ -52,14 +50,14 @@ void RTPPayloadTypeParser::handleStartElement(const std::string& element, const
} catch (boost::bad_lexical_cast &) {
getPayloadInternal()->setPTime(0);
}
- } else if (level == 1) {
+ } else if (level == 1 && element == "parameter") {
getPayloadInternal()->addParameter(attributes.getAttributeValue("name").get_value_or(""),
attributes.getAttributeValue("value").get_value_or(""));
}
++level;
}
-void RTPPayloadTypeParser::handleEndElement(const std::string& element, const std::string&) {
+void RTPPayloadTypeParser::handleEndElement(const std::string&, const std::string&) {
--level;
}
diff --git a/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h b/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h
index 8dee938..f632aca 100644
--- a/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h
+++ b/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h
@@ -16,7 +16,7 @@ namespace Swift {
RTPPayloadTypeParser();
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 handleEndElement(const std::string&, const std::string&);
virtual void handleCharacterData(const std::string&) {};
private:
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp
index 8719a5d..18f38b2 100644
--- a/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp
+++ b/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp
@@ -15,6 +15,8 @@
#include <Swiften/Elements/StreamInitiationFileInfo.h>
#include <Swiften/Elements/JingleFileTransferReceived.h>
#include <Swiften/Elements/JingleFileTransferHash.h>
+//#include <Swiften/Elements/RTPPayloadType.h>
+#include <Swiften/Elements/JingleRTPDescription.h>
#include <Swiften/Base/DateTime.h>
#include <Swiften/Base/Log.h>
@@ -41,6 +43,10 @@ class JingleParserTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testParse_Xep0260_Example1);
CPPUNIT_TEST(testParse_Xep0260_Example3);
+
+ CPPUNIT_TEST(testParse_Xep0167_Example1);
+ CPPUNIT_TEST(testParse_Xep0167_Example48);
+
CPPUNIT_TEST_SUITE_END();
public:
@@ -704,6 +710,115 @@ class JingleParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(8257606, candidate.priority);
CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::Candidate::DirectType, candidate.type);
}
+
+ // http://xmpp.org/extensions/xep-0167.html#example-1
+ void testParse_Xep0167_Example1() {
+ PayloadsParserTester parser;
+ CPPUNIT_ASSERT(parser.parse(
+ "<jingle action=\"session-initiate\""
+ " initiator=\"romeo@montague.lit/orchard\""
+ " sid=\"a73sjjvkla37jfea\""
+ " xmlns=\"urn:xmpp:jingle:1\">"
+ "<content creator=\"initiator\" name=\"voice\">"
+ "<description media=\"audio\" xmlns=\"urn:xmpp:jingle:apps:rtp:1\">"
+ "<payload-type clockrate=\"16000\" id=\"96\" name=\"speex\"/>"
+ "<payload-type id=\"18\" name=\"G729\"/>"
+ "<payload-type channels=\"2\" clockrate=\"16000\" id=\"103\" name=\"L16\"/>"
+ "</description>"
+ //"<transport [...] >"
+ "</content>"
+ "</jingle>"
+ ));
+
+ 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("a73sjjvkla37jfea"), jingle->getSessionID());
+
+ JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>();
+ CPPUNIT_ASSERT(content);
+ CPPUNIT_ASSERT_EQUAL(std::string("voice"), content->getName());
+
+ JingleRTPDescription::ref desc = content->getDescription<JingleRTPDescription>();
+ CPPUNIT_ASSERT(desc);
+ CPPUNIT_ASSERT_EQUAL(JingleRTPDescription::Audio, desc->getMedia());
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), desc->getPayloadTypes().size());
+
+ const RTPPayloadType& payloadType1 = desc->getPayloadTypes()[0];
+ CPPUNIT_ASSERT_EQUAL(static_cast<boost::uint32_t>(16000), payloadType1.getClockrate());
+ CPPUNIT_ASSERT_EQUAL(static_cast<boost::uint8_t>(96), payloadType1.getID());
+ CPPUNIT_ASSERT_EQUAL(std::string("speex"), payloadType1.getName());
+
+ const RTPPayloadType& payloadType2 = desc->getPayloadTypes()[1];
+ CPPUNIT_ASSERT_EQUAL(static_cast<boost::uint8_t>(18), payloadType2.getID());
+ CPPUNIT_ASSERT_EQUAL(std::string("G729"), payloadType2.getName());
+
+ const RTPPayloadType& payloadType3 = desc->getPayloadTypes()[2];
+ CPPUNIT_ASSERT_EQUAL(static_cast<boost::uint32_t>(2), payloadType3.getChannels());
+ CPPUNIT_ASSERT_EQUAL(static_cast<boost::uint32_t>(16000), payloadType3.getClockrate());
+ CPPUNIT_ASSERT_EQUAL(static_cast<boost::uint8_t>(103), payloadType3.getID());
+ CPPUNIT_ASSERT_EQUAL(std::string("L16"), payloadType3.getName());
+ }
+
+ // http://xmpp.org/extensions/xep-0167.html#example-48
+ void testParse_Xep0167_Example48() {
+ PayloadsParserTester parser;
+ CPPUNIT_ASSERT(parser.parse(
+ "<jingle action=\"content-accept\""
+ " initiator=\"romeo@montague.lit/orchard\""
+ " sid=\"a73sjjvkla37jfea\""
+ " xmlns=\"urn:xmpp:jingle:1\">"
+ "<content creator=\"initiator\" name=\"webcam\">"
+ "<description media=\"video\" xmlns=\"urn:xmpp:jingle:apps:rtp:1\">"
+ "<payload-type clockrate=\"90000\" id=\"98\" name=\"theora\">"
+ "<parameter name=\"configuration\" value=\"somebase16string\"/>"
+ "<parameter name=\"delivery-method\" value=\"inline\"/>"
+ "<parameter name=\"height\" value=\"600\"/>"
+ "<parameter name=\"sampling\" value=\"YCbCr-4:2:2\"/>"
+ "<parameter name=\"width\" value=\"800\"/>"
+ "</payload-type>"
+ "<bandwidth type=\"AS\">128</bandwidth>"
+ "</description>"
+ //"<transport xmlns=\"urn:xmpp:jingle:transports:ice-udp:0\"/>"
+ "</content>"
+ "</jingle>"
+ ));
+
+ JinglePayload::ref jingle = parser.getPayload<JinglePayload>();
+ CPPUNIT_ASSERT(jingle);
+ CPPUNIT_ASSERT_EQUAL(JinglePayload::ContentAccept, jingle->getAction());
+ CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator());
+ CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID());
+
+ JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>();
+ CPPUNIT_ASSERT(content);
+ CPPUNIT_ASSERT_EQUAL(std::string("webcam"), content->getName());
+
+ JingleRTPDescription::ref desc = content->getDescription<JingleRTPDescription>();
+ CPPUNIT_ASSERT(desc);
+ CPPUNIT_ASSERT_EQUAL(JingleRTPDescription::Video, desc->getMedia());
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), desc->getPayloadTypes().size());
+
+ const RTPPayloadType& payloadType = desc->getPayloadTypes()[0];
+ CPPUNIT_ASSERT_EQUAL(static_cast<boost::uint32_t>(90000), payloadType.getClockrate());
+ CPPUNIT_ASSERT_EQUAL(static_cast<boost::uint8_t>(98), payloadType.getID());
+ CPPUNIT_ASSERT_EQUAL(std::string("theora"), payloadType.getName());
+
+ RTPPayloadType::ParameterMap params = payloadType.getParameters(); // Explicit copy for easy testing
+ CPPUNIT_ASSERT_EQUAL(params["configuration"], std::string("somebase16string"));
+ CPPUNIT_ASSERT_EQUAL(params["delivery-method"], std::string("inline"));
+ CPPUNIT_ASSERT_EQUAL(params["height"], std::string("600"));
+ CPPUNIT_ASSERT_EQUAL(params["sampling"], std::string("YCbCr-4:2:2"));
+ CPPUNIT_ASSERT_EQUAL(params["width"], std::string("800"));
+
+ std::string type, value;
+ desc->getBandwidth(type, value);
+ CPPUNIT_ASSERT_EQUAL(std::string("AS"), type);
+ CPPUNIT_ASSERT_EQUAL(std::string("128"), value);
+ }
};
CPPUNIT_TEST_SUITE_REGISTRATION(JingleParserTest);
diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript
index 64e9eb9..1ce84b9 100644
--- a/Swiften/Parser/SConscript
+++ b/Swiften/Parser/SConscript
@@ -73,6 +73,8 @@ sources = [
"PayloadParsers/DeliveryReceiptParser.cpp",
"PayloadParsers/DeliveryReceiptRequestParser.cpp",
"PayloadParsers/WhiteboardParser.cpp",
+ "PayloadParsers/RTPPayloadTypeParser.cpp",
+ "PayloadParsers/JingleRTPDescriptionParser.cpp",
"PlatformXMLParserFactory.cpp",
"PresenceParser.cpp",
"SerializingParser.cpp",