diff options
author | Remko Tronçon <git@el-tramo.be> | 2009-07-13 07:17:57 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2009-07-13 07:18:39 (GMT) |
commit | 6ca206b0d0645e50a8a2c59ebd134f9c0f164b9b (patch) | |
tree | 1c4d785f79941b07e7c7d7473fe98d09229b5fa6 | |
parent | 72858ab262a16aa8db209c2898ab0d3c951a9829 (diff) | |
download | swift-6ca206b0d0645e50a8a2c59ebd134f9c0f164b9b.zip swift-6ca206b0d0645e50a8a2c59ebd134f9c0f164b9b.tar.bz2 |
Server stream header support.
-rw-r--r-- | Limber/main.cpp | 35 | ||||
-rw-r--r-- | Swiften/Client/UnitTest/SessionTest.cpp | 5 | ||||
-rw-r--r-- | Swiften/Parser/UnitTest/XMPPParserTest.cpp | 23 | ||||
-rw-r--r-- | Swiften/Parser/XMPPParser.cpp | 2 | ||||
-rw-r--r-- | Swiften/Parser/XMPPParserClient.h | 2 | ||||
-rw-r--r-- | Swiften/Serializer/XMPPSerializer.cpp | 15 | ||||
-rw-r--r-- | Swiften/Serializer/XMPPSerializer.h | 2 | ||||
-rw-r--r-- | Swiften/Server/ServerFromClientSession.cpp | 7 | ||||
-rw-r--r-- | Swiften/Server/ServerFromClientSession.h | 6 | ||||
-rw-r--r-- | Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp | 10 | ||||
-rw-r--r-- | Swiften/StreamStack/XMPPLayer.cpp | 12 | ||||
-rw-r--r-- | Swiften/StreamStack/XMPPLayer.h | 7 |
12 files changed, 98 insertions, 28 deletions
diff --git a/Limber/main.cpp b/Limber/main.cpp index 6dad151..969a390 100644 --- a/Limber/main.cpp +++ b/Limber/main.cpp @@ -9,6 +9,7 @@ #include <boost/thread.hpp> #include "Swiften/Base/ByteArray.h" +#include "Swiften/Base/IDGenerator.h" #include "Swiften/EventLoop/MainEventLoop.h" #include "Swiften/EventLoop/SimpleEventLoop.h" #include "Swiften/Network/ConnectionServer.h" @@ -19,6 +20,8 @@ using namespace Swift; +static const size_t BUFFER_SIZE = 4096; + // A reference-counted non-modifiable buffer class. class SharedBuffer { public: @@ -58,17 +61,39 @@ class IncomingBoostConnection : public IncomingConnection, public boost::enable_ boost::asio::placeholders::error)); } + void start() { + read(); + } + private: - IncomingBoostConnection(boost::asio::io_service& ioService) : socket_(ioService) { + IncomingBoostConnection(boost::asio::io_service& ioService) : socket_(ioService), readBuffer_(BUFFER_SIZE) { + } + + void read() { + socket_.async_read_some( + boost::asio::buffer(readBuffer_), + boost::bind(&IncomingBoostConnection::handleDataRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + } + + void handleDataRead(const boost::system::error_code& error, size_t bytesTransferred) { + if (!error) { + MainEventLoop::postEvent(boost::bind(boost::ref(onDataRead), ByteArray(&readBuffer_[0], bytesTransferred)), this); + read(); + } + else if (error != boost::asio::error::operation_aborted) { + //MainEventLoop::postEvent(boost::bind(boost::ref(onError), ReadError), this); + } } void handleDataWritten(const boost::system::error_code& error) { - if (error) { - std::cerr << "ERROR: Unable to write data to socket" << std::endl; + if (error && error != boost::asio::error::operation_aborted) { + //std::cerr << "ERROR: Unable to write data to socket" << std::endl; + //MainEventLoop::postEvent(boost::bind(boost::ref(onError), ReadError), this); } } boost::asio::ip::tcp::socket socket_; + std::vector<char> readBuffer_; }; class BoostConnectionServer : public ConnectionServer { @@ -87,6 +112,7 @@ class BoostConnectionServer : public ConnectionServer { void handleAccept(IncomingBoostConnection::pointer newConnection, const boost::system::error_code& error) { if (!error) { MainEventLoop::postEvent(boost::bind(boost::ref(onNewConnection), newConnection), this); + newConnection->start(); acceptNextConnection(); } } @@ -107,7 +133,7 @@ class Server { private: void handleNewConnection(boost::shared_ptr<IncomingConnection> c) { - ServerFromClientSession* session = new ServerFromClientSession(c, &payloadParserFactories_, &payloadSerializers_); + ServerFromClientSession* session = new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_); serverFromClientSessions_.push_back(session); session->onSessionFinished.connect(boost::bind(&Server::handleSessionFinished, this, session)); } @@ -118,6 +144,7 @@ class Server { } private: + IDGenerator idGenerator_; BoostIOServiceThread boostIOServiceThread_; BoostConnectionServer* serverFromClientConnectionServer_; std::vector<ServerFromClientSession*> serverFromClientSessions_; diff --git a/Swiften/Client/UnitTest/SessionTest.cpp b/Swiften/Client/UnitTest/SessionTest.cpp index f4c40da..c2b99db 100644 --- a/Swiften/Client/UnitTest/SessionTest.cpp +++ b/Swiften/Client/UnitTest/SessionTest.cpp @@ -509,7 +509,8 @@ class SessionTest : public CppUnit::TestFixture { parser_ = new XMPPParser(this, &payloadParserFactories_); } - void handleStreamStart() { + void handleStreamStart(const String&, const String& to, const String&) { + CPPUNIT_ASSERT_EQUAL(getDomain(), to); handleEvent(Event::StreamStartEvent); } @@ -543,7 +544,7 @@ class SessionTest : public CppUnit::TestFixture { String serializeEvent(const Event& event) { switch (event.type) { case Event::StreamStartEvent: - return serializer_.serializeHeader(getDomain()); + return serializer_.serializeHeader("", getDomain(), ""); case Event::ElementEvent: return serializer_.serializeElement(event.element); case Event::StreamEndEvent: diff --git a/Swiften/Parser/UnitTest/XMPPParserTest.cpp b/Swiften/Parser/UnitTest/XMPPParserTest.cpp index 787828c..a8b805e 100644 --- a/Swiften/Parser/UnitTest/XMPPParserTest.cpp +++ b/Swiften/Parser/UnitTest/XMPPParserTest.cpp @@ -19,6 +19,7 @@ class XMPPParserTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(XMPPParserTest); CPPUNIT_TEST(testParse_SimpleSession); + CPPUNIT_TEST(testParse_SimpleClientFromServerSession); CPPUNIT_TEST(testParse_Presence); CPPUNIT_TEST(testParse_IQ); CPPUNIT_TEST(testParse_Message); @@ -43,12 +44,26 @@ class XMPPParserTest : public CppUnit::TestFixture CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(client_.events.size())); CPPUNIT_ASSERT_EQUAL(Client::StreamStart, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(String("example.com"), client_.events[0].to); CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type); CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[2].type); CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[3].type); CPPUNIT_ASSERT_EQUAL(Client::StreamEnd, client_.events[4].type); } + void testParse_SimpleClientFromServerSession() { + XMPPParser testling(&client_, &factories_); + + CPPUNIT_ASSERT(testling.parse("<?xml version='1.0'?>")); + CPPUNIT_ASSERT(testling.parse("<stream:stream from='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='aeab'>")); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(client_.events.size())); + CPPUNIT_ASSERT_EQUAL(Client::StreamStart, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(String("example.com"), client_.events[0].from); + CPPUNIT_ASSERT_EQUAL(String("aeab"), client_.events[0].id); + } + + void testParse_Presence() { XMPPParser testling(&client_, &factories_); @@ -137,17 +152,21 @@ class XMPPParserTest : public CppUnit::TestFixture struct Event { Event(Type type, boost::shared_ptr<Element> element) : type(type), element(element) {} + Event(Type type, const String& from, const String& to, const String& id) : type(type), from(from), to(to), id(id) {} Event(Type type) : type(type) {} Type type; + String from; + String to; + String id; boost::shared_ptr<Element> element; }; Client() {} - void handleStreamStart() { - events.push_back(Event(StreamStart)); + void handleStreamStart(const String& from, const String& to, const String& id) { + events.push_back(Event(StreamStart, from, to, id)); } void handleElement(boost::shared_ptr<Element> element) { diff --git a/Swiften/Parser/XMPPParser.cpp b/Swiften/Parser/XMPPParser.cpp index 59cfce7..0f04cca 100644 --- a/Swiften/Parser/XMPPParser.cpp +++ b/Swiften/Parser/XMPPParser.cpp @@ -54,7 +54,7 @@ bool XMPPParser::parse(const String& data) { void XMPPParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) { if (!inStream()) { if (element == "stream" && ns == "http://etherx.jabber.org/streams") { - client_->handleStreamStart(attributes.getAttribute("to")); + client_->handleStreamStart(attributes.getAttribute("from"), attributes.getAttribute("to"), attributes.getAttribute("id")); } else { parseErrorOccurred_ = true; diff --git a/Swiften/Parser/XMPPParserClient.h b/Swiften/Parser/XMPPParserClient.h index d19c7d0..fb81df8 100644 --- a/Swiften/Parser/XMPPParserClient.h +++ b/Swiften/Parser/XMPPParserClient.h @@ -12,7 +12,7 @@ namespace Swift { public: virtual ~XMPPParserClient(); - virtual void handleStreamStart(const String& header) = 0; + virtual void handleStreamStart(const String& from, const String& to, const String& id) = 0; virtual void handleElement(boost::shared_ptr<Element>) = 0; virtual void handleStreamEnd() = 0; }; diff --git a/Swiften/Serializer/XMPPSerializer.cpp b/Swiften/Serializer/XMPPSerializer.cpp index c43f9db..6139586 100644 --- a/Swiften/Serializer/XMPPSerializer.cpp +++ b/Swiften/Serializer/XMPPSerializer.cpp @@ -34,8 +34,19 @@ XMPPSerializer::XMPPSerializer(PayloadSerializerCollection* payloadSerializers) serializers_.push_back(boost::shared_ptr<ElementSerializer>(new StreamFeaturesSerializer())); } -String XMPPSerializer::serializeHeader(const String& domain) const { - return "<?xml version='1.0'?><stream:stream to='" + domain + "' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' >"; +String XMPPSerializer::serializeHeader(const String& from, const String& to, const String& id) const { + String result = "<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\""; + if (!from.isEmpty()) { + result += " from=\"" + from + "\""; + } + if (!to.isEmpty()) { + result += " to=\"" + to + "\""; + } + if (!id.isEmpty()) { + result += " id=\"" + id + "\""; + } + result += ">"; + return result; } String XMPPSerializer::serializeElement(boost::shared_ptr<Element> element) const { diff --git a/Swiften/Serializer/XMPPSerializer.h b/Swiften/Serializer/XMPPSerializer.h index 1fc8b9d..f77e14b 100644 --- a/Swiften/Serializer/XMPPSerializer.h +++ b/Swiften/Serializer/XMPPSerializer.h @@ -16,7 +16,7 @@ namespace Swift { public: XMPPSerializer(PayloadSerializerCollection*); - String serializeHeader(const String& domain) const; + String serializeHeader(const String& from, const String& to, const String& id = "") const; String serializeElement(boost::shared_ptr<Element> stanza) const; String serializeFooter() const; diff --git a/Swiften/Server/ServerFromClientSession.cpp b/Swiften/Server/ServerFromClientSession.cpp index e85021e..be8b601 100644 --- a/Swiften/Server/ServerFromClientSession.cpp +++ b/Swiften/Server/ServerFromClientSession.cpp @@ -10,15 +10,17 @@ namespace Swift { ServerFromClientSession::ServerFromClientSession( + const String& id, boost::shared_ptr<IncomingConnection> connection, PayloadParserFactoryCollection* payloadParserFactories, PayloadSerializerCollection* payloadSerializers) : + id_(id), connection_(connection), payloadParserFactories_(payloadParserFactories), payloadSerializers_(payloadSerializers) { xmppLayer_ = new XMPPLayer(payloadParserFactories_, payloadSerializers_); xmppLayer_->onStreamStart.connect( - boost::bind(&ServerFromClientSession::handleStreamStart, this, _1)); + boost::bind(&ServerFromClientSession::handleStreamStart, this, _2)); xmppLayer_->onElement.connect( boost::bind(&ServerFromClientSession::handleElement, this, _1)); //xmppLayer_->onError.connect( @@ -41,7 +43,8 @@ void ServerFromClientSession::handleElement(boost::shared_ptr<Element>) { } void ServerFromClientSession::handleStreamStart(const String& domain) { - xmppLayer_->writeHeader(domain); + domain_ = domain; + xmppLayer_->writeHeader(domain_, id_); } } diff --git a/Swiften/Server/ServerFromClientSession.h b/Swiften/Server/ServerFromClientSession.h index cedfcdb..3413a03 100644 --- a/Swiften/Server/ServerFromClientSession.h +++ b/Swiften/Server/ServerFromClientSession.h @@ -3,6 +3,8 @@ #include <boost/shared_ptr.hpp> #include <boost/signal.hpp> +#include "Swiften/Base/String.h" + namespace Swift { class Element; class PayloadParserFactoryCollection; @@ -12,11 +14,11 @@ namespace Swift { class IncomingConnectionLayer; class IncomingConnection; class ByteArray; - class String; class ServerFromClientSession { public: ServerFromClientSession( + const String& id, boost::shared_ptr<IncomingConnection> connection, PayloadParserFactoryCollection* payloadParserFactories, PayloadSerializerCollection* payloadSerializers); @@ -31,11 +33,13 @@ namespace Swift { void handleStreamStart(const String& domain); private: + String id_; boost::shared_ptr<IncomingConnection> connection_; PayloadParserFactoryCollection* payloadParserFactories_; PayloadSerializerCollection* payloadSerializers_; IncomingConnectionLayer* connectionLayer_; StreamStack* streamStack_; XMPPLayer* xmppLayer_; + String domain_; }; } diff --git a/Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp b/Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp index 2150f4d..f60c370 100644 --- a/Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp +++ b/Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp @@ -48,9 +48,9 @@ class XMPPLayerTest : public CppUnit::TestFixture testling_->onElement.connect(boost::bind(&XMPPLayerTest::handleElement, this, _1)); testling_->onError.connect(boost::bind(&XMPPLayerTest::handleError, this)); - testling_->parseData("<stream:stream to='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' >"); + testling_->parseData("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" >"); testling_->resetParser(); - testling_->parseData("<stream:stream to='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' >"); + testling_->parseData("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" >"); testling_->parseData("<presence/>"); CPPUNIT_ASSERT_EQUAL(1, elementsReceived_); @@ -59,8 +59,8 @@ class XMPPLayerTest : public CppUnit::TestFixture void testResetParser_FromSlot() { testling_->onElement.connect(boost::bind(&XMPPLayerTest::handleElementAndReset, this, _1)); - testling_->parseData("<stream:stream to='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' ><presence/>"); - testling_->parseData("<stream:stream to='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' ><presence/>"); + testling_->parseData("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" ><presence/>"); + testling_->parseData("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" ><presence/>"); CPPUNIT_ASSERT_EQUAL(2, elementsReceived_); CPPUNIT_ASSERT_EQUAL(0, errorReceived_); @@ -70,7 +70,7 @@ class XMPPLayerTest : public CppUnit::TestFixture testling_->onWriteData.connect(boost::bind(&XMPPLayerTest::handleWriteData, this, _1)); testling_->writeHeader("example.com"); - CPPUNIT_ASSERT_EQUAL(String("<?xml version='1.0'?><stream:stream to='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' >"), dataReceived_); + CPPUNIT_ASSERT_EQUAL(String("<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\" to=\"example.com\">"), dataReceived_); } void testWriteElement() { diff --git a/Swiften/StreamStack/XMPPLayer.cpp b/Swiften/StreamStack/XMPPLayer.cpp index 464d4b0..73d763a 100644 --- a/Swiften/StreamStack/XMPPLayer.cpp +++ b/Swiften/StreamStack/XMPPLayer.cpp @@ -20,8 +20,12 @@ XMPPLayer::~XMPPLayer() { delete xmppParser_; } -void XMPPLayer::writeHeader(const String& domain) { - onWriteData(ByteArray(xmppSerializer_->serializeHeader(domain))); +void XMPPLayer::writeHeader(const String& to) { + onWriteData(ByteArray(xmppSerializer_->serializeHeader("", to))); +} + +void XMPPLayer::writeHeader(const String& from, const String& id) { + onWriteData(ByteArray(xmppSerializer_->serializeHeader(from, "", id))); } void XMPPLayer::writeFooter() { @@ -56,8 +60,8 @@ void XMPPLayer::doResetParser() { resetParserAfterParse_ = false; } -void XMPPLayer::handleStreamStart(const String& domain) { - onStreamStart(domain); +void XMPPLayer::handleStreamStart(const String& from, const String& to, const String& id) { + onStreamStart(from, to, id); } void XMPPLayer::handleElement(boost::shared_ptr<Element> stanza) { diff --git a/Swiften/StreamStack/XMPPLayer.h b/Swiften/StreamStack/XMPPLayer.h index e064d94..7437112 100644 --- a/Swiften/StreamStack/XMPPLayer.h +++ b/Swiften/StreamStack/XMPPLayer.h @@ -22,7 +22,8 @@ namespace Swift { PayloadSerializerCollection* payloadSerializers); ~XMPPLayer(); - void writeHeader(const String& domain); + void writeHeader(const String& from, const String& id); + void writeHeader(const String& to); void writeFooter(); void writeElement(boost::shared_ptr<Element>); void writeData(const String& data); @@ -31,14 +32,14 @@ namespace Swift { void resetParser(); public: - boost::signal<void (const String& domain)> onStreamStart; + boost::signal<void (const String& /* from */, const String& /* to */ , const String& /* id */)> onStreamStart; boost::signal<void (boost::shared_ptr<Element>)> onElement; boost::signal<void (const ByteArray&)> onWriteData; boost::signal<void (const ByteArray&)> onDataRead; boost::signal<void ()> onError; private: - void handleStreamStart(const String&); + void handleStreamStart(const String&, const String&, const String&); void handleElement(boost::shared_ptr<Element>); void handleStreamEnd(); |