Esempio n. 1
0
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));
}
Esempio n. 3
0
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);
	}
}
Esempio n. 4
0
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));
}
Esempio n. 5
0
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));
	}
}
Esempio n. 6
0
void LocalChannel::incoming (ByteArrayPtr data){
	if (mCollector) mCollector->addPendingData (data->size());
	mInputBuffer.append(*data);
	if (mChanged) {
		xcall (mChanged);
	}
}
Esempio n. 7
0
void XMPPStream::finishOp (CurrentOp op, Error result) {
	if (mCurrentOp == op) {
		if (mCurrentCallback) xcall (abind (mCurrentCallback, result));
		mCurrentCallback.clear();
		mCurrentOp = XMO_Null;
	}
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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);
}
Esempio n. 11
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);
	}
}
Esempio n. 12
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);
}
Esempio n. 13
0
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;
}
Esempio n. 14
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);
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
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;
}
Esempio n. 17
0
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);
}
Esempio n. 18
0
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));
}
Esempio n. 19
0
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);
}
Esempio n. 20
0
void Controller::changeConnection (DesiredState state) {
	// do it asynchronous, as it may calls back
	xcall (abind (dMemFun (this, &Controller::onChangeConnection), state));
}
Esempio n. 21
0
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()));
}
Esempio n. 22
0
static void asyncNotify (const ResultCallback & callback, Error e){
	if (callback) xcall (abind (callback, e));
}
Esempio n. 23
0
void XMPPStream::uncouple () {
	mChannel->changed().clear ();
	xcall (abind (dMemFun (this, &XMPPStream::throwAwayChannel), mChannel));
	mChannel = ChannelPtr ();
}
Esempio n. 24
0
void BoshXMPPConnection::setState (State s) {
	if (mConnectionStateChanged)
		xcall (abind (mConnectionStateChanged, s));
	mState = s;
}