void XMPPStream::onChannelError (Error e) { mError = e; if (mCurrentCallback) { xcall (abind (mCurrentCallback,e)); } if (mAsyncError) { xcall (mAsyncError); } mCurrentOp = XMO_Null; mState = XMS_Error; }
void HttpConnectionManager::doFinish (Error result, EstablishConnectionOp * op) { RequestConnectionCallback cb = op->callback; HttpConnectionPtr con = result ? HttpConnectionPtr() : op->connection; if (!result) { mCreatedConnections++; } else { // TLSChannel doesn't like to be deleted while giving out a callback xcall (abind (&throwAway, op->connection)); } delete op; xcall (abind (cb, result, con)); }
void XMPPStream::onXmlStreamStateChange () { XMLStreamDecoder::State s = mXmlStreamDecoder.state(); if (s == XMLStreamDecoder::XS_ReadXmlBegin) return; // ignore if (s == XMLStreamDecoder::XS_ReadOpener) { if (mState == XMS_StartInitializing) { if (!decodeStreamInit()) { finishOp (XMO_StartInitialize, mError); return; } mState = XMS_Initialized; finishOp (XMO_StartInitialize, NoError); return; } else if (mState == XMS_RespondInitializing) { if (!decodeStreamInit()){ finishOp (XMO_RespondInitialize, mError); return; } sendStreamInit(); mState = XMS_Initialized; finishOp (XMO_RespondInitialize, NoError); } else { onChannelError (error::BadProtocol); } } if (s == XMLStreamDecoder::XS_Closed) { mState = XMS_End; if (mClosed) xcall (mClosed); } }
void BoshTransport::connect(const sf::Url & url, const StringMap & additionalArgs, int timeOutMs, const ResultCallback & callback){ if (mState != Unconnected) { Log (LogError) << LOGID << "Wrong State " << toString (mState) << std::endl; return xcall (abind (callback, error::WrongState)); } mUrl = url; mRid = randomRid(); mRidRecv = mRid; // Setting Parameters StringMap args = additionalArgs; args["rid"] = toString (mRid); setIfNotSet (&args, "ver", "1.10"); setIfNotSet (&args, "wait", "60"); setIfNotSet (&args, "hold", "1"); setIfNotSet (&args, "xmlns", "http://jabber.org/protocol/httpbind"); BoshNodeBuilder builder; for (StringMap::const_iterator i = args.begin(); i != args.end(); i++){ builder.addAttribute(i->first,i->second); } // Send it out... mState = Connecting; executeRequest (sf::createByteArrayPtr(builder.toString()), timeOutMs, abind (dMemFun (this, &BoshTransport::onConnectReply), callback)); }
void Controller::init () { QSettings settings; Model::Settings s; settings.beginGroup("im"); s.userId = sfString (settings.value("userId","@sflx.net").toString()); s.resource = sfString (settings.value("resource", qtString (sf::net::hostName())).toString()); s.password = sfString (settings.value("password").toString()); s.destinationDirectory = sfString (settings.value("destinationDirectory", QDir::homePath()).toString()); s.echoServerIp = sfString (settings.value("echoServerIp", "82.211.19.149").toString()); if (s.echoServerIp == "62.48.92.13"){ // sflx.net moved! // workaround s.echoServerIp = "82.211.19.149"; } s.echoServerPort = settings.value("echoServerPort", "1234").toInt (); s.useBosh = settings.value("useBosh", false).toBool(); s.autoConnect = settings.value("autoConnect", false).toBool(); settings.endGroup (); { SF_SCHNEE_LOCK; mModel->setSettings(s); mModel->init (); mModel->beacon()->connections().conDetailsChanged() = dMemFun (this, &Controller::onConDetailsChanged); mModel->listTracker()->trackingUpdate() = dMemFun (this, &Controller::onTrackingUpdate); mModel->listTracker()->lostTracking() = dMemFun (this, &Controller::onLostTracking); mModel->fileGetting()->gotListing() = dMemFun (this, &Controller::onUpdatedListing); mModel->fileGetting()->updatedTransfer() = dMemFun (this, &Controller::onUpdatedIncomingTransfer); mModel->fileSharing()->updatedTransfer() = dMemFun (this, &Controller::onUpdatedOutgoingTransfer); sf::InterplexBeacon * beacon = mModel->beacon(); beacon->presences().peersChanged().add (sf::dMemFun (this, &Controller::onPeersChanged)); beacon->presences().onlineStateChanged().add (sf::dMemFun (this, &Controller::onOnlineStateChanged)); beacon->presences().subscribeRequest() = sf::dMemFun (this, &Controller::onUserSubscribeRequest); beacon->presences().serverStreamErrorReceived().add (sf::dMemFun (this, &Controller::onServerStreamErrorReceived)); // Set own features and activating protocol filter { const sf::String schneeProtocol = "http://sflx.net/protocols/schnee"; std::vector<sf::String> ownFeatures; ownFeatures.push_back (schneeProtocol); sf::Error e = beacon->presences().setOwnFeature(sf::String ("schneeflocke ") + sf::schnee::version(), ownFeatures); if (e) { sf::Log (LogError) << LOGID << "Could not set own feature" << std::endl; } else { mUserList->setFeatureFilter(schneeProtocol); } } } mGUI->init (); mGUI->call (sf::bind (&UserList::rebuildList, mUserList)); loadShares(); if (s.autoConnect){ xcall (abind (dMemFun (this, &Controller::onChangeConnection), DS_CONNECT)); } }
void LocalChannel::incoming (ByteArrayPtr data){ if (mCollector) mCollector->addPendingData (data->size()); mInputBuffer.append(*data); if (mChanged) { xcall (mChanged); } }
void XMPPStream::finishOp (CurrentOp op, Error result) { if (mCurrentOp == op) { if (mCurrentCallback) xcall (abind (mCurrentCallback, result)); mCurrentCallback.clear(); mCurrentOp = XMO_Null; } }
Error LocalChannel::write (const ByteArrayPtr& data, const ResultCallback & callback) { if (!mOther) return error::NotInitialized; // no target mOther->incoming (data); if (callback) xcall (abind (callback, NoError)); if (mCollector) mCollector->addTransferred (mHostId, mOther->hostId(), data->size(), mHops); return NoError; }
void BoshTransport::failConnect (Error result, const ResultCallback & callback, const String & msg) { Log(LogWarning) << LOGID << "Connect failed: " << toString(result) << " " << msg << std::endl; asyncNotify (callback, result); if (mChanged) xcall (mChanged); mState = Other; mError = result; mErrorMessage = msg; }
void HttpConnectionManager::requestConnection (const Url & url, int timeOutMs, const RequestConnectionCallback & callback) { assert (callback); { // Check the pool PendingConnectionMap::iterator i = mPendingConnections.find(ConId(url.protocol(), url.host())); if (i != mPendingConnections.end()){ while (!i->second.empty()){ AsyncOpId id = i->second.front(); i->second.pop_front(); PendingConnectionOp * op; getReadyAsyncOp (id, PendingConnection, &op); mPendingConnectionsCount--; if (op) { Log (LogInfo) << LOGID << "Reusing connection to " << url.protocol() << "/" << url.host() << " id=" << op->id() << std::endl; xcall (abind(callback, NoError, op->connection)); delete op; return; } } // not existant anymore mPendingConnections.erase (i); } } EstablishConnectionOp * op = new EstablishConnectionOp (regTimeOutMs (timeOutMs)); const String & protocol = url.protocol(); if (protocol != "http" && protocol != "https") { Log (LogWarning) << LOGID << "Unsupported protocol: " << protocol << std::endl; return xcall(abind(callback, error::NotSupported, HttpConnectionPtr())); } op->callback = callback; op->connection = HttpConnectionPtr (new HttpConnection()); op->connection->host = url.host(); op->connection->pureHost = url.pureHost(); op->connection->protocol = url.protocol(); TCPSocketPtr sock = TCPSocketPtr (new TCPSocket ()); op->connection->channel = sock; op->setId(genFreeId()); op->setState(EstablishConnectionOp::WaitTcpConnect); Error e = sock->connectToHost(url.pureHost(), url.port(), timeOutMs, abind(dMemFun(this, &HttpConnectionManager::onTcpConnect), op->id())); if (e) { delete op; return xcall (abind(callback, e, HttpConnectionPtr())); } addAsyncOp (op); }
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); } }
void LocalChannel::close (const ResultCallback & resultCallback) { if (mOther){ if (mOther->mChanged) xcall (mOther->mChanged); mOther->setOther (0); } setOther (0); notifyAsync (mChanged); notifyAsync (resultCallback, NoError); }
Error XMPPStream::waitFeatures (const ResultCallback & callback) { if (mReceivedFeatures) { // we have it already. if (callback) xcall (abind (callback, NoError)); return NoError; } Error e = startOp (XMO_WaitFeatures, callback); if (e) return e; return NoError; }
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 UDPEchoClient::start (String echoServer, int echoPort, int timeOutMs) { mToken = sf::genRandomToken80 (); mSocket.readyRead() = dMemFun (this, &UDPEchoClient::onReadyRead); mTimeoutHandle = xcallTimed (dMemFun (this, &UDPEchoClient::onTimeOut), regTimeOutMs(timeOutMs)); char request [256]; snprintf (request, 256, "condata %s", mToken.c_str()); Error e = mSocket.sendTo(echoServer, echoPort, sf::createByteArrayPtr (request)); if (e) { xcall (abind (mResultDelegate, e)); return; } mState = WAIT; }
Error XMPPStream::init (ChannelPtr channel, bool skipInit) { if (mChannel) mChannel->changed().clear(); mError = NoError; mSkipInit = skipInit; mState = XMS_Null; if (mSkipInit) mXmlStreamDecoder.resetToPureStream(); else mXmlStreamDecoder.reset(); mReceivedFeatures = false; mFeatures = XMLChunk (); mChannel = channel; mChannel->changed() = dMemFun (this, &XMPPStream::onChannelChange); xcall (dMemFun (this, &XMPPStream::onChannelChange)); return NoError; }
void HttpConnectionManager::giveBack (Error lastResult, const HttpConnectionPtr & connection) { if (lastResult) { // throw away, asynchronous // we do not trust this anymore... xcall (abind (&throwAway, connection)); return; } PendingConnectionOp * op = new PendingConnectionOp (regTimeOutMs (mGeneralTimeoutMs)); AsyncOpId id = genFreeId(); op->setId(id); op->connection = connection; op->boss = this; op->connection->channel->changed() = abind (dMemFun (this, &HttpConnectionManager::onChannelChange), id); addToPendingConnections (op); Log (LogInfo) << LOGID << "Storing pending connection to " << connection->host << " id=" << id << std::endl; addAsyncOp (op); }
void Model::registerAccount (const sf::ResultCallback & callback) { sf::LockGuard guard (mMutex); if (mRegistration) { if (callback) xcall (sf::abind (callback, sf::error::TooMuch)); return; } mRegistration = new sf::XMPPRegistration (); sf::String username, servername; sf::XMPPRegistration::Credentials cred; sf::String server; splitUserServer (mSettings.userId, &cred.username, &server); cred.password = mSettings.password; // email is hopefully not needed... sf::ResultCallback acb = sf::abind (sf::dMemFun (this, &Model::onRegisterResult), callback); // TODO: Get rid of the return values of functions who call back anyway! #125 sf::Error e = mRegistration->start(server, cred, 30000, acb); if (e) sf::xcall (sf::abind(acb, e)); }
void HttpConnectionManager::onChannelChange (AsyncOpId id) { PendingConnectionOp * op; getReadyAsyncOp (id, PendingConnection, &op); if (!op) return; ByteArrayPtr all = op->connection->channel->read(); if (all && !all->empty()){ Log (LogInfo) << LOGID << "Recv in pending connection: " << *all << std::endl; op->connection->inputBuffer.append(*all); } Error e = op->connection->channel->error(); if (e) { // adieu Log (LogInfo) << LOGID << "Closing channel to " << op->connection->host << " as channel reported error: " << toString (e) << std::endl; xcall (abind (&throwAway, op->connection)); removeFromPendingConnections (op); delete op; return; } // data ready? nobody knows, add it again... addAsyncOp (op); }
void Controller::changeConnection (DesiredState state) { // do it asynchronous, as it may calls back xcall (abind (dMemFun (this, &Controller::onChangeConnection), state)); }
void HttpConnectionManager::PendingConnectionOp::onCancel (sf::Error reason) { Log (LogInfo) << LOGID << "Closing connection to " << connection->host << " due " << toString (reason) << std::endl; // NOTE: Strange behaviour is from pre-general-lock-times. // TODO: Cleanup xcall (abind (dMemFun (boss, &HttpConnectionManager::removeFromPendingConnectionsExplicit), ConId (connection->protocol, connection->host), id())); }
static void asyncNotify (const ResultCallback & callback, Error e){ if (callback) xcall (abind (callback, e)); }
void XMPPStream::uncouple () { mChannel->changed().clear (); xcall (abind (dMemFun (this, &XMPPStream::throwAwayChannel), mChannel)); mChannel = ChannelPtr (); }
void BoshXMPPConnection::setState (State s) { if (mConnectionStateChanged) xcall (abind (mConnectionStateChanged, s)); mState = s; }