From fde15d66a75334b23ca8bbd56b44e33893c813c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 3 Sep 2010 20:40:34 +0200
Subject: Establish stream management after resource bind.


diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp
index 551d835..daffbc6 100644
--- a/Swiften/Client/ClientSession.cpp
+++ b/Swiften/Client/ClientSession.cpp
@@ -48,6 +48,7 @@ ClientSession::ClientSession(
 			allowPLAINOverNonTLS(false),
 			needSessionStart(false),
 			needResourceBind(false),
+			needAcking(false),
 			authenticator(NULL) {
 }
 
@@ -213,13 +214,8 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
 			stream->setWhitespacePingEnabled(true);
 			needSessionStart = streamFeatures->hasSession();
 			needResourceBind = streamFeatures->hasResourceBind();
-			if (streamFeatures->hasStreamManagement()) {
-				state = EnablingSessionManagement;
-				stream->writeElement(boost::shared_ptr<EnableStreamManagement>(new EnableStreamManagement()));
-			}
-			else {
-				continueSessionInitialization();
-			}
+			needAcking = streamFeatures->hasStreamManagement();
+			continueSessionInitialization();
 		}
 	}
 	else if (boost::dynamic_pointer_cast<Compressed>(element)) {
@@ -238,9 +234,11 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
 		stanzaAckRequester_->onStanzaAcked.connect(boost::bind(&ClientSession::handleStanzaAcked, this, _1));
 		stanzaAckResponder_ = boost::shared_ptr<StanzaAckResponder>(new StanzaAckResponder());
 		stanzaAckResponder_->onAck.connect(boost::bind(&ClientSession::ack, this, _1));
+		needAcking = false;
 		continueSessionInitialization();
 	}
 	else if (boost::dynamic_pointer_cast<StreamManagementFailed>(element)) {
+		needAcking = false;
 		continueSessionInitialization();
 	}
 	else if (AuthChallenge* challenge = dynamic_cast<AuthChallenge*>(element.get())) {
@@ -295,6 +293,10 @@ void ClientSession::continueSessionInitialization() {
 		}
 		sendStanza(IQ::createRequest(IQ::Set, JID(), "session-bind", resourceBind));
 	}
+	else if (needAcking) {
+		state = EnablingSessionManagement;
+		stream->writeElement(boost::shared_ptr<EnableStreamManagement>(new EnableStreamManagement()));
+	}
 	else if (needSessionStart) {
 		state = StartingSession;
 		sendStanza(IQ::createRequest(IQ::Set, JID(), "session-start", boost::shared_ptr<StartSession>(new StartSession())));
diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h
index c15508a..359d7c8 100644
--- a/Swiften/Client/ClientSession.h
+++ b/Swiften/Client/ClientSession.h
@@ -119,6 +119,7 @@ namespace Swift {
 			bool allowPLAINOverNonTLS;
 			bool needSessionStart;
 			bool needResourceBind;
+			bool needAcking;
 			ClientAuthenticator* authenticator;
 			boost::shared_ptr<StanzaAckRequester> stanzaAckRequester_;
 			boost::shared_ptr<StanzaAckResponder> stanzaAckResponder_;
diff --git a/Swiften/Client/UnitTest/ClientSessionTest.cpp b/Swiften/Client/UnitTest/ClientSessionTest.cpp
index e27f130..2762188 100644
--- a/Swiften/Client/UnitTest/ClientSessionTest.cpp
+++ b/Swiften/Client/UnitTest/ClientSessionTest.cpp
@@ -182,12 +182,14 @@ class ClientSessionTest : public CppUnit::TestFixture {
 			server->receiveStreamStart();
 			server->sendStreamStart();
 			server->sendStreamFeaturesWithBindAndStreamManagement();
+			server->receiveBind();
+			server->sendBindResult();
 			server->receiveStreamManagementEnable();
 			server->sendStreamManagementEnabled();
 
 			CPPUNIT_ASSERT(session->getStreamManagementEnabled());
-			server->receiveBind();
 			// TODO: Test if the requesters & responders do their work
+			CPPUNIT_ASSERT_EQUAL(ClientSession::Initialized, session->getState());
 		}
 
 		void testStreamManagement_Failed() {
@@ -202,11 +204,13 @@ class ClientSessionTest : public CppUnit::TestFixture {
 			server->receiveStreamStart();
 			server->sendStreamStart();
 			server->sendStreamFeaturesWithBindAndStreamManagement();
+			server->receiveBind();
+			server->sendBindResult();
 			server->receiveStreamManagementEnable();
 			server->sendStreamManagementFailed();
 
 			CPPUNIT_ASSERT(!session->getStreamManagementEnabled());
-			server->receiveBind();
+			CPPUNIT_ASSERT_EQUAL(ClientSession::Initialized, session->getState());
 		}
 
 
@@ -347,6 +351,13 @@ class ClientSessionTest : public CppUnit::TestFixture {
 					onElementReceived(boost::shared_ptr<StreamManagementFailed>(new StreamManagementFailed()));
 				}
 
+				void sendBindResult() {
+					boost::shared_ptr<ResourceBind> resourceBind(new ResourceBind());
+					resourceBind->setJID(JID("foo@bar.com/bla"));
+					boost::shared_ptr<IQ> iq = IQ::createResult(JID("foo@bar.com"), bindID, resourceBind);
+					onElementReceived(iq);
+				}
+
 				void receiveStreamStart() {
 					Event event = popEvent();
 					CPPUNIT_ASSERT(event.header);
@@ -378,6 +389,7 @@ class ClientSessionTest : public CppUnit::TestFixture {
 					boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(event.element);
 					CPPUNIT_ASSERT(iq);
 					CPPUNIT_ASSERT(iq->getPayload<ResourceBind>());
+					bindID = iq->getID();
 				}
 
 				Event popEvent() {
@@ -392,6 +404,7 @@ class ClientSessionTest : public CppUnit::TestFixture {
 				bool tlsEncrypted;
 				bool compressed;
 				bool whitespacePingEnabled;
+				String bindID;
 				int resetCount;
 				std::deque<Event> receivedEvents;
 		};
-- 
cgit v0.10.2-6-g49f6