summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2009-07-13 07:17:57 (GMT)
committerRemko Tronçon <git@el-tramo.be>2009-07-13 07:18:39 (GMT)
commit6ca206b0d0645e50a8a2c59ebd134f9c0f164b9b (patch)
tree1c4d785f79941b07e7c7d7473fe98d09229b5fa6
parent72858ab262a16aa8db209c2898ab0d3c951a9829 (diff)
downloadswift-6ca206b0d0645e50a8a2c59ebd134f9c0f164b9b.zip
swift-6ca206b0d0645e50a8a2c59ebd134f9c0f164b9b.tar.bz2
Server stream header support.
-rw-r--r--Limber/main.cpp35
-rw-r--r--Swiften/Client/UnitTest/SessionTest.cpp5
-rw-r--r--Swiften/Parser/UnitTest/XMPPParserTest.cpp23
-rw-r--r--Swiften/Parser/XMPPParser.cpp2
-rw-r--r--Swiften/Parser/XMPPParserClient.h2
-rw-r--r--Swiften/Serializer/XMPPSerializer.cpp15
-rw-r--r--Swiften/Serializer/XMPPSerializer.h2
-rw-r--r--Swiften/Server/ServerFromClientSession.cpp7
-rw-r--r--Swiften/Server/ServerFromClientSession.h6
-rw-r--r--Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp10
-rw-r--r--Swiften/StreamStack/XMPPLayer.cpp12
-rw-r--r--Swiften/StreamStack/XMPPLayer.h7
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();