Exemplo n.º 1
0
void BoshTransport::onRequestReply (Error result, const HttpResponsePtr & response, int64_t rid, const ResultCallback & originalCallback) {
	Log (LogInfo) << LOGID << "Reply of RID " << rid << ":" << toString (result) << " (" << (response ? response->resultCode : 0) << ")" << std::endl;
	if (mState != Connected && mState != Closing){
		if (mState != Unconnected)
			Log (LogWarning) << LOGID << "Strange state" << std::endl;
		return;
	}
	if (mAuthenticated && !response->authenticated){
		Log (LogWarning) << LOGID << "Lost authentication status" << std::endl;
		return failRequest (error::AuthError, rid, "Lost authentication", originalCallback);
	}
	if (result || response->resultCode != 200) {
		// Recovering from errors
		if (result) Log (LogWarning) << LOGID << "Got HTTP error " << toString (result) << std::endl;
		else
			if (response->resultCode != 200) Log (LogWarning) << LOGID << "Got bad HTTP result code " << response->resultCode << std::endl;

		mErrorCount++;
		mSumErrorCount++;
		if (mErrorCount > mMaxErrorCount) {
			return failRequest (result, rid, "To many HTTP errors", originalCallback);
		}
		// Try it again
		sf::ByteArrayPtr data = mOpenRids[rid];
		assert (data);
		Log (LogInfo) << LOGID << "Try to recover (ErrCnt=" << mErrorCount << " SucCnt=" << mSuccessCount << ")" << std::endl;
		return executeRequest (data, mLongPollTimeoutMs, abind (dMemFun (this, &BoshTransport::onRequestReply), rid, originalCallback));
	}
	mSuccessCount++;
	if (mErrorCount > 0) mErrorCount--; // so we can recover from errors
	BoshNodeParser parser;
	Error e = parser.parse(response->data->const_c_array(), response->data->size());
	if (e) {
		return failRequest (e, rid, "Parse error", originalCallback);
	}
	mOpenRids.erase(rid);
	mOpenRidCount--;

	mInWaitingRids[rid] = sf::createByteArrayPtr (parser.content());
	if (!parser.attribute ("type").empty()){
		// server sent terminate or something
		failRequest (error::Eof, rid, String ("Server sent type=" ) + parser.attribute ("type"), originalCallback);
	} else {
		notifyAsync (originalCallback, NoError);
	}
	insertWaitingInputData ();

	/// some braking
	sf::xcallTimed(dMemFun (this, &BoshTransport::continueWorking), sf::futureInMs(mReconnectWaitMs));
	if (mChanged)
		xcall (mChanged);
}
Exemplo n.º 2
0
int testNodeBuildAndParse () {
	BoshNodeBuilder builder;
	builder.addAttribute("hello", "world");
	builder.addAttribute("and", "anotherone");
	builder.addContent (sf::createByteArrayPtr ("<bla>Hi dude</bla>"));
	builder.addContent (sf::createByteArrayPtr ("<bli></bli>"));
	String s = builder.toString();
	printf ("Serialized code: %s\n", s.c_str());

	BoshNodeParser parser;
	Error e = parser.parse(s);
	tcheck1(!e);

	tcheck1(parser.attribute("hello") == "world");
	tcheck1(parser.attribute("and") == "anotherone");
	String back = parser.content();
	XMLChunk chunk = xml::parseDocument(back.c_str(), back.length());
	tcheck1 (chunk.getChild("bla").text() == "Hi dude");
	tcheck1 (chunk.getHasChild("bli"));
	return 0;
}
Exemplo n.º 3
0
void BoshTransport::onConnectReply (Error result, const HttpResponsePtr & response, const ResultCallback & callback) {
	if (mState != Connecting) {
		Log (LogError) << LOGID << "Strange state " << toString (mState) << std::endl;
		return;
	}
	if (result) {
		return failConnect (result, callback, "error on http connect");
	}
	if (!(response->resultCode == 200))
		return failConnect (error::ConnectionError, callback, String ("bad http result=" + toString (response->resultCode)).c_str());
	mAuthenticated = response->authenticated;

	BoshNodeParser parser;
	Error e = parser.parse(response->data->const_c_array(), response->data->size());
	if (e) {
		return failConnect (e, callback, "parse");
	}

	mSid = parser.attribute("sid");
	if (mSid.empty()){
		return failConnect (error::BadProtocol, callback, "parse");
	}

	String wait = parser.attribute("wait");
	if (wait.empty()){
		Log (LogWarning) << LOGID << "Server did not respond with wait attribute!" << std::endl;

		// workaround. wait is mandatory, but at least the local Prosody instance does not send it
		// http://code.google.com/p/lxmppd/issues/detail?id=219
		mLongPollTimeoutMs = 60000;
	} else {
		try {
			mLongPollTimeoutMs = boost::lexical_cast<int> (wait) * 1000;
		} catch (boost::bad_lexical_cast & e){
			return failConnect (error::BadProtocol, callback, "bad wait response");
		}
	}

	String type = parser.attribute ("type");
	if (!type.empty()) { // error or terminate
		return failConnect (error::CouldNotConnectHost, callback, String ("opponent sent type=" + type).c_str());
	}
	mState = Connected;

	String content = parser.content();
	if (!content.empty()){
		mInputBuffer.append(content.c_str(), content.length());
		Log (LogInfo) << LOGID << "Server sent " << content.length() << " bytes on session create response" << std::endl;
	}
	mRidRecv++; // cannot receive first message out of order.

	asyncNotify (callback, NoError);
	// initial pending request
	continueWorking ();
	if (mChanged) {
		xcall (mChanged);
	}
}