summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2011-12-24 14:27:33 (GMT)
committerRemko Tronçon <git@el-tramo.be>2011-12-24 14:44:44 (GMT)
commitc060049e759571ae02a3a970c6a3088e099e5c9f (patch)
tree8512e2ca0ae0fba16238651b9d0edbb74e085b16
parentb453b3bf94dcd40d71c30fd0053f7110cb52b211 (diff)
downloadswift-contrib-c060049e759571ae02a3a970c6a3088e099e5c9f.zip
swift-contrib-c060049e759571ae02a3a970c6a3088e099e5c9f.tar.bz2
Some BOSH refactoring.
-rw-r--r--Swiften/Network/BOSHConnection.cpp34
-rw-r--r--Swiften/Network/BOSHConnection.h22
-rw-r--r--Swiften/Network/BOSHConnectionPool.cpp4
-rw-r--r--Swiften/Network/BOSHConnectionPool.h2
-rw-r--r--Swiften/Network/UnitTest/BOSHConnectionTest.cpp21
5 files changed, 42 insertions, 41 deletions
diff --git a/Swiften/Network/BOSHConnection.cpp b/Swiften/Network/BOSHConnection.cpp
index 09548e9..ea84400 100644
--- a/Swiften/Network/BOSHConnection.cpp
+++ b/Swiften/Network/BOSHConnection.cpp
@@ -43,32 +43,27 @@ BOSHConnection::BOSHConnection(const URL& boshURL, ConnectionFactory* connection
BOSHConnection::~BOSHConnection() {
if (connection_) {
connection_->onConnectFinished.disconnect(boost::bind(&BOSHConnection::handleConnectionConnectFinished, shared_from_this(), _1));
connection_->onDataRead.disconnect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
connection_->onDisconnected.disconnect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
}
disconnect();
}
-void BOSHConnection::connect(const HostAddressPort& server) {
- /* FIXME: Redundant parameter */
+void BOSHConnection::connect() {
Connection::ref rawConnection = connectionFactory_->createConnection();
connection_ = (boshURL_.getScheme() == "https") ? boost::make_shared<TLSConnection>(rawConnection, tlsFactory_) : rawConnection;
connection_->onConnectFinished.connect(boost::bind(&BOSHConnection::handleConnectionConnectFinished, shared_from_this(), _1));
connection_->onDataRead.connect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1));
connection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1));
connection_->connect(HostAddressPort(HostAddress(boshURL_.getHost()), boshURL_.getPort()));
}
-void BOSHConnection::listen() {
- assert(false);
-}
-
void BOSHConnection::disconnect() {
if(connection_) {
connection_->disconnect();
sid_ = "";
}
}
void BOSHConnection::restartStream() {
write(createSafeByteArray(""), true, false);
@@ -164,50 +159,54 @@ void BOSHConnection::startStream(const std::string& to, unsigned long rid) {
waitingForStartResponse_ = true;
SafeByteArray safeHeader = createSafeByteArray(header.str());
onBOSHDataWritten(safeHeader);
connection_->write(safeHeader);
SWIFT_LOG(debug) << "write stream header: " << safeByteArrayToString(safeHeader) << std::endl;
}
void BOSHConnection::handleDataRead(boost::shared_ptr<SafeByteArray> data) {
- onBOSHDataRead(*data.get());
- buffer_ = concat(buffer_, *data.get());
+ onBOSHDataRead(*data);
+ buffer_ = concat(buffer_, *data);
std::string response = safeByteArrayToString(buffer_);
if (response.find("\r\n\r\n") == std::string::npos) {
onBOSHDataRead(createSafeByteArray("[[Previous read incomplete, pending]]"));
return;
}
std::string httpCode = response.substr(response.find(" ") + 1, 3);
if (httpCode != "200") {
onHTTPError(httpCode);
return;
}
BOSHBodyExtractor parser(parserFactory_, createByteArray(response.substr(response.find("\r\n\r\n") + 4)));
if (parser.getBody()) {
- if ((*parser.getBody()).attributes.getAttribute("type") == "terminate") {
- BOSHError::Type errorType = parseTerminationCondition((*parser.getBody()).attributes.getAttribute("condition"));
+ if (parser.getBody()->attributes.getAttribute("type") == "terminate") {
+ BOSHError::Type errorType = parseTerminationCondition(parser.getBody()->attributes.getAttribute("condition"));
onSessionTerminated(errorType == BOSHError::NoError ? boost::shared_ptr<BOSHError>() : boost::make_shared<BOSHError>(errorType));
}
buffer_.clear();
if (waitingForStartResponse_) {
waitingForStartResponse_ = false;
- sid_ = (*parser.getBody()).attributes.getAttribute("sid");
- std::string requestsString = (*parser.getBody()).attributes.getAttribute("requests");
+ sid_ = parser.getBody()->attributes.getAttribute("sid");
+ std::string requestsString = parser.getBody()->attributes.getAttribute("requests");
int requests = 2;
if (!requestsString.empty()) {
- requests = boost::lexical_cast<size_t>(requestsString);
+ try {
+ requests = boost::lexical_cast<size_t>(requestsString);
+ }
+ catch (const boost::bad_lexical_cast&) {
+ }
}
onSessionStarted(sid_, requests);
}
- SafeByteArray payload = createSafeByteArray((*parser.getBody()).content);
+ SafeByteArray payload = createSafeByteArray(parser.getBody()->content);
/* Say we're good to go again, so don't add anything after here in the method */
pending_ = false;
onXMPPDataRead(payload);
}
}
BOSHError::Type BOSHConnection::parseTerminationCondition(const std::string& text) {
BOSHError::Type condition = BOSHError::UndefinedCondition;
@@ -251,34 +250,31 @@ BOSHError::Type BOSHConnection::parseTerminationCondition(const std::string& tex
condition = BOSHError::NoError;
}
return condition;
}
const std::string& BOSHConnection::getSID() {
return sid_;
}
-void BOSHConnection::setRID(unsigned long rid) {
+void BOSHConnection::setRID(unsigned long long rid) {
rid_ = rid;
}
void BOSHConnection::setSID(const std::string& sid) {
sid_ = sid;
}
-void BOSHConnection::handleDisconnected(const boost::optional<Error>& error) {
+void BOSHConnection::handleDisconnected(const boost::optional<Connection::Error>& error) {
onDisconnected(error);
sid_ = "";
connectionReady_ = false;
}
-HostAddressPort BOSHConnection::getLocalAddress() const {
- return connection_->getLocalAddress();
-}
bool BOSHConnection::isReadyToSend() {
/* Without pipelining you need to not send more without first receiving the response */
/* With pipelining you can. Assuming we can't, here */
return connectionReady_ && !pending_ && !waitingForStartResponse_ && !sid_.empty();
}
}
diff --git a/Swiften/Network/BOSHConnection.h b/Swiften/Network/BOSHConnection.h
index 283ea10..4d53253 100644
--- a/Swiften/Network/BOSHConnection.h
+++ b/Swiften/Network/BOSHConnection.h
@@ -23,18 +23,20 @@
#include <Swiften/Session/SessionStream.h>
namespace boost {
class thread;
namespace system {
class error_code;
}
}
+class BOSHConnectionTest;
+
namespace Swift {
class ConnectionFactory;
class XMLParserFactory;
class TLSContextFactory;
class BOSHError : public SessionStream::Error {
public:
enum Type {BadRequest, HostGone, HostUnknown, ImproperAddressing,
InternalServerError, ItemNotFound, OtherRequest, PolicyViolation,
@@ -43,61 +45,63 @@ namespace Swift {
BOSHError(Type type) : SessionStream::Error(SessionStream::Error::ConnectionReadError), type(type) {}
Type getType() {return type;}
typedef boost::shared_ptr<BOSHError> ref;
private:
Type type;
};
- class BOSHConnection : public Connection, public boost::enable_shared_from_this<BOSHConnection> {
+ class BOSHConnection : public boost::enable_shared_from_this<BOSHConnection> {
public:
typedef boost::shared_ptr<BOSHConnection> ref;
static ref create(const URL& boshURL, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory) {
return ref(new BOSHConnection(boshURL, connectionFactory, parserFactory, tlsFactory));
}
virtual ~BOSHConnection();
- virtual void listen();
- virtual void connect(const HostAddressPort& address);
+ virtual void connect();
virtual void disconnect();
virtual void write(const SafeByteArray& data);
- virtual HostAddressPort getLocalAddress() const;
const std::string& getSID();
- void setRID(unsigned long rid);
+ void setRID(unsigned long long rid);
void setSID(const std::string& sid);
void startStream(const std::string& to, unsigned long rid);
void terminateStream();
bool isReadyToSend();
void restartStream();
- static std::pair<SafeByteArray, size_t> createHTTPRequest(const SafeByteArray& data, bool streamRestart, bool terminate, long rid, const std::string& sid, const URL& boshURL);
+ boost::signal<void (bool /* error */)> onConnectFinished;
+ boost::signal<void (bool /* error */)> onDisconnected;
boost::signal<void (BOSHError::ref)> onSessionTerminated;
boost::signal<void (const std::string& /*sid*/, size_t /*requests*/)> onSessionStarted;
boost::signal<void (const SafeByteArray&)> onXMPPDataRead;
boost::signal<void (const SafeByteArray&)> onBOSHDataRead;
boost::signal<void (const SafeByteArray&)> onBOSHDataWritten;
boost::signal<void (const std::string&)> onHTTPError;
+
private:
- BOSHConnection(const URL& boshURL, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory);
+ friend class ::BOSHConnectionTest;
+ BOSHConnection(const URL& boshURL, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory);
+ static std::pair<SafeByteArray, size_t> createHTTPRequest(const SafeByteArray& data, bool streamRestart, bool terminate, long rid, const std::string& sid, const URL& boshURL);
void handleConnectionConnectFinished(bool error);
void handleDataRead(boost::shared_ptr<SafeByteArray> data);
- void handleDisconnected(const boost::optional<Error>& error);
+ void handleDisconnected(const boost::optional<Connection::Error>& error);
void write(const SafeByteArray& data, bool streamRestart, bool terminate); /* FIXME: refactor */
BOSHError::Type parseTerminationCondition(const std::string& text);
URL boshURL_;
ConnectionFactory* connectionFactory_;
XMLParserFactory* parserFactory_;
boost::shared_ptr<Connection> connection_;
std::string sid_;
bool waitingForStartResponse_;
- unsigned long rid_;
+ unsigned long long rid_;
SafeByteArray buffer_;
bool pending_;
TLSContextFactory* tlsFactory_;
bool connectionReady_;
};
}
diff --git a/Swiften/Network/BOSHConnectionPool.cpp b/Swiften/Network/BOSHConnectionPool.cpp
index 4886ede..a30bf7b 100644
--- a/Swiften/Network/BOSHConnectionPool.cpp
+++ b/Swiften/Network/BOSHConnectionPool.cpp
@@ -191,19 +191,19 @@ void BOSHConnectionPool::tryToSendQueuedData() {
}
}
}
}
void BOSHConnectionPool::handleHTTPError(const std::string& /*errorCode*/) {
handleSessionTerminated(boost::make_shared<BOSHError>(BOSHError::UndefinedCondition));
}
-void BOSHConnectionPool::handleConnectionDisconnected(const boost::optional<Connection::Error>& error, BOSHConnection::ref connection) {
+void BOSHConnectionPool::handleConnectionDisconnected(bool error, BOSHConnection::ref connection) {
destroyConnection(connection);
if (false && error) {
handleSessionTerminated(boost::make_shared<BOSHError>(BOSHError::UndefinedCondition));
}
else {
/* We might have just freed up a connection slot to send with */
tryToSendQueuedData();
}
}
@@ -212,19 +212,19 @@ boost::shared_ptr<BOSHConnection> BOSHConnectionPool::createConnection() {
BOSHConnection::ref connection = BOSHConnection::create(boshURL, connectProxyFactory ? connectProxyFactory : connectionFactory, xmlParserFactory, tlsFactory);
connection->onXMPPDataRead.connect(boost::bind(&BOSHConnectionPool::handleDataRead, this, _1));
connection->onSessionStarted.connect(boost::bind(&BOSHConnectionPool::handleSessionStarted, this, _1, _2));
connection->onBOSHDataRead.connect(boost::bind(&BOSHConnectionPool::handleBOSHDataRead, this, _1));
connection->onBOSHDataWritten.connect(boost::bind(&BOSHConnectionPool::handleBOSHDataWritten, this, _1));
connection->onDisconnected.connect(boost::bind(&BOSHConnectionPool::handleConnectionDisconnected, this, _1, connection));
connection->onConnectFinished.connect(boost::bind(&BOSHConnectionPool::handleConnectFinished, this, _1, connection));
connection->onSessionTerminated.connect(boost::bind(&BOSHConnectionPool::handleSessionTerminated, this, _1));
connection->onHTTPError.connect(boost::bind(&BOSHConnectionPool::handleHTTPError, this, _1));
- connection->connect(HostAddressPort(HostAddress("0.0.0.0"), 0));
+ connection->connect();
connections.push_back(connection);
return connection;
}
void BOSHConnectionPool::destroyConnection(boost::shared_ptr<BOSHConnection> connection) {
connections.erase(std::remove(connections.begin(), connections.end(), connection), connections.end());
connection->onXMPPDataRead.disconnect(boost::bind(&BOSHConnectionPool::handleDataRead, this, _1));
connection->onSessionStarted.disconnect(boost::bind(&BOSHConnectionPool::handleSessionStarted, this, _1, _2));
connection->onBOSHDataRead.disconnect(boost::bind(&BOSHConnectionPool::handleBOSHDataRead, this, _1));
diff --git a/Swiften/Network/BOSHConnectionPool.h b/Swiften/Network/BOSHConnectionPool.h
index 2264c90..cc354b8 100644
--- a/Swiften/Network/BOSHConnectionPool.h
+++ b/Swiften/Network/BOSHConnectionPool.h
@@ -32,19 +32,19 @@ namespace Swift {
boost::signal<void (const SafeByteArray&)> onBOSHDataWritten;
private:
void handleDataRead(const SafeByteArray& data);
void handleSessionStarted(const std::string& sid, size_t requests);
void handleBOSHDataRead(const SafeByteArray& data);
void handleBOSHDataWritten(const SafeByteArray& data);
void handleSessionTerminated(BOSHError::ref condition);
void handleConnectFinished(bool, BOSHConnection::ref connection);
- void handleConnectionDisconnected(const boost::optional<Connection::Error>& error, BOSHConnection::ref connection);
+ void handleConnectionDisconnected(bool error, BOSHConnection::ref connection);
void handleHTTPError(const std::string& errorCode);
private:
BOSHConnection::ref createConnection();
void destroyConnection(BOSHConnection::ref connection);
void tryToSendQueuedData();
BOSHConnection::ref getSuitableConnection();
private:
diff --git a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
index 9215725..8062bea 100644
--- a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
+++ b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
@@ -39,30 +39,31 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testHTTPRequest_Empty);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {
eventLoop = new DummyEventLoop();
connectionFactory = new MockConnectionFactory(eventLoop);
connectFinished = false;
disconnected = false;
+ disconnectedError = false;
dataRead.clear();
}
void tearDown() {
eventLoop->processEvents();
delete connectionFactory;
delete eventLoop;
}
void testHeader() {
BOSHConnection::ref testling = createTestling();
- testling->connect(HostAddressPort(HostAddress("127.0.0.1"), 5280));
+ testling->connect();
eventLoop->processEvents();
testling->startStream("wonderland.lit", 1);
std::string initial("<body wait='60' "
"inactivity='30' "
"polling='5' "
"requests='2' "
"hold='1' "
"maxpause='120' "
"sid='MyShinySID' "
@@ -70,82 +71,82 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
"from='wonderland.lit' "
"xmlns='http://jabber.org/protocol/httpbind'/>");
readResponse(initial, connectionFactory->connections[0]);
CPPUNIT_ASSERT_EQUAL(std::string("MyShinySID"), sid);
CPPUNIT_ASSERT(testling->isReadyToSend());
}
void testReadiness_ok() {
BOSHConnection::ref testling = createTestling();
- testling->connect(HostAddressPort(HostAddress("127.0.0.1"), 5280));
+ testling->connect();
eventLoop->processEvents();
testling->setSID("blahhhhh");
CPPUNIT_ASSERT(testling->isReadyToSend());
}
void testReadiness_pending() {
BOSHConnection::ref testling = createTestling();
- testling->connect(HostAddressPort(HostAddress("127.0.0.1"), 5280));
+ testling->connect();
eventLoop->processEvents();
testling->setSID("mySID");
CPPUNIT_ASSERT(testling->isReadyToSend());
testling->write(createSafeByteArray("<mypayload/>"));
CPPUNIT_ASSERT(!testling->isReadyToSend());
readResponse("<body><blah/></body>", connectionFactory->connections[0]);
CPPUNIT_ASSERT(testling->isReadyToSend());
}
void testReadiness_disconnect() {
BOSHConnection::ref testling = createTestling();
- testling->connect(HostAddressPort(HostAddress("127.0.0.1"), 5280));
+ testling->connect();
eventLoop->processEvents();
testling->setSID("mySID");
CPPUNIT_ASSERT(testling->isReadyToSend());
connectionFactory->connections[0]->onDisconnected(false);
CPPUNIT_ASSERT(!testling->isReadyToSend());
}
void testReadiness_noSID() {
BOSHConnection::ref testling = createTestling();
- testling->connect(HostAddressPort(HostAddress("127.0.0.1"), 5280));
+ testling->connect();
eventLoop->processEvents();
CPPUNIT_ASSERT(!testling->isReadyToSend());
}
void testWrite_Receive() {
BOSHConnection::ref testling = createTestling();
- testling->connect(HostAddressPort(HostAddress("127.0.0.1"), 5280));
+ testling->connect();
eventLoop->processEvents();
testling->setSID("mySID");
testling->write(createSafeByteArray("<mypayload/>"));
readResponse("<body><blah/></body>", connectionFactory->connections[0]);
CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead));
}
void testWrite_ReceiveTwice() {
BOSHConnection::ref testling = createTestling();
- testling->connect(HostAddressPort(HostAddress("127.0.0.1"), 5280));
+ testling->connect();
eventLoop->processEvents();
testling->setSID("mySID");
testling->write(createSafeByteArray("<mypayload/>"));
readResponse("<body><blah/></body>", connectionFactory->connections[0]);
CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead));
dataRead.clear();
testling->write(createSafeByteArray("<mypayload2/>"));
readResponse("<body><bleh/></body>", connectionFactory->connections[0]);
CPPUNIT_ASSERT_EQUAL(std::string("<bleh/>"), byteArrayToString(dataRead));
}
void testRead_Fragment() {
BOSHConnection::ref testling = createTestling();
- testling->connect(HostAddressPort(HostAddress("127.0.0.1"), 5280));
+ testling->connect();
eventLoop->processEvents();
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), connectionFactory->connections.size());
boost::shared_ptr<MockConnection> connection = connectionFactory->connections[0];
boost::shared_ptr<SafeByteArray> data1 = boost::make_shared<SafeByteArray>(createSafeByteArray(
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/xml; charset=utf-8\r\n"
"Access-Control-Allow-Origin: *\r\n"
"Access-Control-Allow-Headers: Content-Type\r\n"
"Content-Length: 64\r\n"));
@@ -192,19 +193,19 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
c->setRID(42);
return c;
}
void handleConnectFinished(bool error) {
connectFinished = true;
connectFinishedWithError = error;
}
- void handleDisconnected(const boost::optional<Connection::Error>& e) {
+ void handleDisconnected(bool e) {
disconnected = true;
disconnectedError = e;
}
void handleDataRead(const SafeByteArray& d) {
append(dataRead, d);
}
void handleSID(const std::string& s) {
@@ -274,18 +275,18 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
}
private:
DummyEventLoop* eventLoop;
MockConnectionFactory* connectionFactory;
bool connectFinished;
bool connectFinishedWithError;
bool disconnected;
- boost::optional<Connection::Error> disconnectedError;
+ bool disconnectedError;
ByteArray dataRead;
PlatformXMLParserFactory parserFactory;
std::string sid;
};
CPPUNIT_TEST_SUITE_REGISTRATION(BOSHConnectionTest);