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; }
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)); }
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; }
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); }
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; } }