Beispiel #1
0
void LocalChannel::close (const ResultCallback & resultCallback) {
	if (mOther){
		if (mOther->mChanged) xcall (mOther->mChanged);
		mOther->setOther (0);
	}
	setOther (0);
	notifyAsync (mChanged);
	notifyAsync (resultCallback, NoError);
}
void BoshXMPPConnection::finalize (Error e, ConnectingOp * op, const char * errorText) {
	mConnecting = false;
	if (e) {
		Log (LogProfile) << LOGID << "Connect op failed in state " << op->state() << " due " << toString (e) << std::endl;
		notifyAsync (op->resultCallback, e);
		if (errorText)
			mErrorText = errorText;
		setState (IMClient::CS_ERROR);
		delete op;
		return;
	}
	Log (LogProfile) << LOGID << "Successfully logged in, rest time = " << op->lastingTimeMs();
	setState (IMClient::CS_CONNECTED);
	notifyAsync (op->resultCallback, NoError);
	delete op;
}
Beispiel #3
0
void BoshTransport::startNextRequest (const StringMap & additionalArgs, const ResultCallback & callback) {
	if (mState != Connected && mState != Closing){
		Log (LogWarning) << LOGID << "Strange state" << std::endl;
		notifyAsync (callback, error::WrongState);
		return;
	}
	// Building Message
	mRid++;
	BoshNodeBuilder builder;
	builder.addAttribute("rid", toString(mRid));
	builder.addAttribute("sid", mSid);
	builder.addAttribute("xmlns", "http://jabber.org/protocol/httpbind");
	for (StringMap::const_iterator i = additionalArgs.begin(); i != additionalArgs.end(); i++) {
		builder.addAttribute(i->first.c_str(), i->second);
	}

	// Adding data..
	for (std::deque<ByteArrayPtr>::const_iterator i = mOutputBuffer.begin(); i != mOutputBuffer.end(); i++) {
		builder.addContent(*i);
	}
	mOutputBuffer.clear();

	// Sending
	sf::ByteArrayPtr data = sf::createByteArrayPtr (builder.toString());
	mOpenRids[mRid] = data;
	mOpenRidCount++;
	executeRequest (data, mLongPollTimeoutMs, abind (dMemFun (this, &BoshTransport::onRequestReply), mRid, callback));
}
Beispiel #4
0
void BoshTransport::failRequest (Error result, int64_t rid, const String & msg, const ResultCallback & originalCallback) {
	notifyAsync (mChanged);
	Log (LogWarning) << LOGID << "Terminating connection with " << toString (result) << " " << msg << std::endl;
	Log (LogWarning) << LOGID << "Open Output data: " << mOutputBuffer.size() << " parts" << std::endl;
	Log (LogWarning) << LOGID << "Open Connections: " << mOpenRidCount << std::endl;

	if (result == error::Eof) {
		// not so bad, just terminated session
		mState = Unconnected;
		notifyAsync (originalCallback, NoError);
		return;
	} else {
		notifyAsync (originalCallback, mError);
	}
	mState = Other;
	mError = result;
	mErrorMessage = msg;
}
Beispiel #5
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);
}
Beispiel #6
0
void XMPPStream::onXmlChunkRead (const XMLChunk & chunk) {
	if (mNextChunkHandler){
		mNextChunkHandler (chunk);
		mNextChunkHandler.clear();
		return;
	}

	if (chunk.name() == "stream:features") {
		if (mReceivedFeatures) {
			Log (LogWarning) << LOGID << "Double receive features!" << std::endl;
		}
		mFeatures         = chunk;
		mReceivedFeatures = true;
		finishOp (XMO_WaitFeatures, NoError);
		return;
	} else
	if (chunk.name() == "iq") {
		xmpp::Iq iq;
		bool suc = iq.decode(chunk);
		if (!suc) {
			Log (LogWarning) << LOGID << "Could not decode " << chunk << std::endl;
			return;
		}
		String id = chunk.getAttribute("id");
		if (id.empty()){
			Log (LogWarning) << LOGID << "Received empty id in iq" << std::endl;
		}

		OpenIqMap::iterator i = mOpenIqs.find (id);
		if (i != mOpenIqs.end()){
			IqResultCallback cb = i->second;
			mOpenIqs.erase(i); // make this behaviour selectable?
			if (cb){
				notifyAsync (cb, NoError, iq, chunk);
			} else {
				Log (LogInfo) << LOGID << "Ignoring iq reply as there is no callback set (id=" << iq.id << ")" << std::endl;
			}
		} else {
			if (mIncomingIq) {
				notifyAsync (mIncomingIq, iq, chunk);
			} else {
				Log (LogWarning) << LOGID << "No iq handler set!" << std::endl;
			}
		}
	} else
	if (chunk.name() == "message") {
		xmpp::Message m;
		bool suc = m.decode(chunk);
		if (!suc) {
			Log (LogWarning) << LOGID << "Could not decode message " << chunk << std::endl;
			return;
		}
		notifyAsync (mIncomingMessage, m, chunk);
	} else
	if (chunk.name() == "presence") {
		xmpp::PresenceInfo p;
		bool suc = p.decode(chunk);
		if (!suc) {
			Log (LogWarning) << LOGID << "Could not decode presence " << chunk << std::endl;
			return;
		}
		notifyAsync (mIncomingPresence, p, chunk);
	} else
	if (chunk.name() == "stream:error"){
		String text = chunk.getChild("text").text();
		if (mIncomingStreamError){
			notifyAsync (mIncomingStreamError, text, chunk);
		} else {
			Log (LogWarning) << LOGID << "Discarding incoming stream error, no delegate " << text << std::endl;
		}
	} else {
		Log (LogWarning) << LOGID << "Unknown chunk type " << chunk << std::endl;
	}
}