diff options
Diffstat (limited to 'Swiften/Network/BOSHConnection.cpp')
| -rw-r--r-- | Swiften/Network/BOSHConnection.cpp | 34 | 
1 files changed, 15 insertions, 19 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 @@ -17,84 +17,79 @@  #include <boost/lexical_cast.hpp>  #include <string>  #include <Swiften/Network/ConnectionFactory.h>  #include <Swiften/Base/Log.h>  #include <Swiften/Base/String.h>  #include <Swiften/Base/Concat.h>  #include <Swiften/Base/ByteArray.h>  #include <Swiften/Network/HostAddressPort.h>  #include <Swiften/Network/TLSConnection.h>  #include <Swiften/Parser/BOSHBodyExtractor.h>  namespace Swift {  BOSHConnection::BOSHConnection(const URL& boshURL, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory)  	: boshURL_(boshURL),   	  connectionFactory_(connectionFactory),   	  parserFactory_(parserFactory),  	  sid_(),  	  waitingForStartResponse_(false),  	  pending_(false),  	  tlsFactory_(tlsFactory),  	  connectionReady_(false)  {  }  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);  }  void BOSHConnection::terminateStream() {  	write(createSafeByteArray(""), false, true);  }  void BOSHConnection::write(const SafeByteArray& data) {  	write(data, false, false);  }  std::pair<SafeByteArray, size_t> BOSHConnection::createHTTPRequest(const SafeByteArray& data, bool streamRestart, bool terminate, long rid, const std::string& sid, const URL& boshURL) {  	size_t size;  	std::stringstream content;  	SafeByteArray contentTail = createSafeByteArray("</body>");  	std::stringstream header;  	content << "<body rid='" << rid << "' sid='" << sid << "'";  	if (streamRestart) {  		content << " xmpp:restart='true' xmlns:xmpp='urn:xmpp:xbosh'";  	}  	if (terminate) {  		content << " type='terminate'";  	}  	content << " xmlns='http://jabber.org/protocol/httpbind'>"; @@ -138,147 +133,148 @@ void BOSHConnection::handleConnectionConnectFinished(bool error) {  void BOSHConnection::startStream(const std::string& to, unsigned long rid) {  	assert(connectionReady_);  	// Session Creation Request  	std::stringstream content;  	std::stringstream header;  	content << "<body content='text/xml; charset=utf-8'"  			<< " hold='1'"  			<< " to='" << to << "'"  			<< " rid='" << rid << "'"  			<< " ver='1.6'"  			<< " wait='60'" /* FIXME: we probably want this configurable*/  			/*<< " ack='0'" FIXME: support acks */  			<< " xml:lang='en'"  			<< " xmlns:xmpp='urn:xmpp:bosh'"  			<< " xmpp:version='1.0'"  			<< " xmlns='http://jabber.org/protocol/httpbind' />";  	std::string contentString = content.str();  	header	<< "POST /" << boshURL_.getPath() << " HTTP/1.1\r\n"  			<< "Host: " << boshURL_.getHost() << ":" << boshURL_.getPort() << "\r\n"  		/*<< "Accept-Encoding: deflate\r\n"*/  			<< "Content-Type: text/xml; charset=utf-8\r\n"  			<< "Content-Length: " << contentString.size() << "\r\n\r\n"  			<< contentString;  	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;  	if (text == "bad-request") {  		condition = BOSHError::BadRequest;  	}  	else if (text == "host-gone") {  		condition = BOSHError::HostGone;  	}  	else if (text == "host-unknown") {  		condition = BOSHError::HostUnknown;  	}  	else if (text == "improper-addressing") {  		condition = BOSHError::ImproperAddressing;  	}  	else if (text == "internal-server-error") {  		condition = BOSHError::InternalServerError;  	}  	else if (text == "item-not-found") {  		condition = BOSHError::ItemNotFound;  	}  	else if (text == "other-request") {  		condition = BOSHError::OtherRequest;  	}  	else if (text == "policy-violation") {  		condition = BOSHError::PolicyViolation;  	}  	else if (text == "remote-connection-failed") {  		condition = BOSHError::RemoteConnectionFailed;  	}  	else if (text == "remote-stream-error") {  		condition = BOSHError::RemoteStreamError;  	}  	else if (text == "see-other-uri") {  		condition = BOSHError::SeeOtherURI;  	}  	else if (text == "system-shutdown") {  		condition = BOSHError::SystemShutdown;  	}  	else if (text == "") {  		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();  }  } | 
 Swift
 Swift