Ejemplo n.º 1
0
Error BoshXMPPConnection::startConnect (bool withLogin, const XMPPStreamPtr & stream, int timeOutMs, const ResultCallback & callback) {
	if (mConnecting){
		Log (LogError) << LOGID << "There is already a connection process" << std::endl;
		return error::ExistsAlready;
	}
	ConnectingOp * op = new ConnectingOp (sf::regTimeOutMs (timeOutMs));
	op->setId (genFreeId());
	op->resultCallback = callback;
	op->withLogin = withLogin;
	op->transport = BoshTransportPtr (new BoshTransport());
	op->stream = stream;
	op->boss = this;

	if (mDetails.port == 0)
		mDetails.port = 443;

	// Starting connect
	Url url = Url (String ("https://") + mDetails.server + ":" + toString (mDetails.port) +  "/http-bind/");
	BoshTransport::StringMap addArgs;
	addArgs["to"] = mDetails.server;
	addArgs["xmpp:version"] = "1.0";
	addArgs["xmlns:xmpp"] = "urn:xmpp:xbosh"; // is important for ejabberd

	op->transport->connect(url, addArgs, op->lastingTimeMs(), abind (dMemFun (this, &BoshXMPPConnection::onBoshConnect), op->id()));
	op->setState (ConnectingOp::WAIT_BOSH_CONNECT);
	setState (IMClient::CS_CONNECTING);
	addAsyncOp (op);
	return NoError;
}
Ejemplo n.º 2
0
Error TCPConnectProtocol::requestDetails (const HostId & target, const RequestConnectDetailsCallback & callback, int timeOutMs){
	OpId id = genFreeId ();
	RequestConnectDetails req;
	req.id = id;
	Error e = mCommunicationDelegate->send (target, Datagram::fromCmd(req));
	if (e) return e;
	RequestOp * op = new RequestOp (regTimeOutMs(timeOutMs));
	op->cb = callback;
	op->setId(id);
	addAsyncOp (op);
	return NoError;
}
Ejemplo n.º 3
0
void BoshXMPPConnection::onFeatures (ConnectingOp * op, Error result) {
	if (result) {
		return finalize (result, op);
	}
	if (!op->withLogin) {
		// Yeah
		return finalize (NoError, op);
	}
	op->setState (ConnectingOp::WAIT_LOGIN);
	LOG_STATE ("WAIT_LOGIN");
	result = op->stream->authenticate(mDetails.username, mDetails.password, aOpMemFun (op, &BoshXMPPConnection::onLogin));
	if (result) return finalize (result, op);
	addAsyncOp (op);
}
Ejemplo n.º 4
0
void BoshXMPPConnection::onFeatures2 (ConnectingOp * op, Error result) {
	if (result) {
		return finalize (result, op);
	}
	op->setState (ConnectingOp::WAIT_BIND);
	LOG_STATE ("WAIT_BIND");

	function <void (Error, const String &)> xx = aOpMemFun (op, &BoshXMPPConnection::onResourceBind);

	result = op->stream->bindResource(mDetails.resource, aOpMemFun (op, &BoshXMPPConnection::onResourceBind));
	if (result)
		return finalize (result, op);
	addAsyncOp (op);
}
Ejemplo n.º 5
0
void BoshXMPPConnection::onLogin (ConnectingOp * op, Error result) {
	if (result) {
		return finalize (result, op);
	}
	op->setState (ConnectingOp::WAIT_FEATURE2);
	op->transport->restart();
	op->stream->startInitAfterHandshake(op->transport);
	result = op->stream->waitFeatures(aOpMemFun (op, &BoshXMPPConnection::onFeatures2));
	if (result)
		return finalize (result, op);
	LOG_STATE ("WAIT_FEATURE2"); // Note: Internal state, not external state
	setState (IMClient::CS_AUTHENTICATING);

	addAsyncOp (op);
}
Ejemplo n.º 6
0
void BoshXMPPConnection::onBoshConnect (Error result, AsyncOpId id) {
	ConnectingOp * op;
	getReadyAsyncOpInState (id, CONNECT_OP, ConnectingOp::WAIT_BOSH_CONNECT, &op);
	if (!op) return;

	if (result) {
		return finalize (result, op);
	}

	op->stream->startInitAfterHandshake(op->transport);
	op->setState (ConnectingOp::WAIT_FEATURE);
	LOG_STATE ("WAIT_FEATURE");
	result = op->stream->waitFeatures(aOpMemFun (op, &BoshXMPPConnection::onFeatures));
	if (result) return finalize (result, op);
	addAsyncOp (op);
}
Ejemplo n.º 7
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);
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
void BoshXMPPConnection::onResourceBind (ConnectingOp * op, Error result, const String& fullJid) {
	if (result) {
		return finalize (result, op);
	}
	String expectedId = mDetails.fullId();
	if (fullJid != mDetails.fullId()){
		// Forbit this: Full JID must be predictable in order to get crypt/authentication working.
		Log (LogWarning) << LOGID << "Bound to wrong full jid! expected: " << expectedId << " found: " << fullJid << std::endl;
		return finalize (error::BadProtocol, op);
	}

	op->setState (ConnectingOp::WAIT_SESSION);
	LOG_STATE ("WAIT_SESSION");
	result = op->stream->startSession(aOpMemFun (op, &BoshXMPPConnection::onStartSession));
	if (result)
		return finalize (result, op);
	addAsyncOp (op);
}
Ejemplo n.º 10
0
void HttpConnectionManager::onTcpConnect (Error result, AsyncOpId id) {
	EstablishConnectionOp * op;
	getReadyAsyncOpInState (id, EstablishConnection, EstablishConnectionOp::WaitTcpConnect, &op);
	if (!op) return;

	if (result) {
		return doFinish (result, op);
	}

	if (op->connection->protocol == "https") {
		// Add another TLS layer onto it...
		TLSChannelPtr tlsChannel = TLSChannelPtr (new TLSChannel (op->connection->channel));
		op->connection->channel = tlsChannel;
		tlsChannel->clientHandshake(TLSChannel::X509, op->connection->pureHost, abind (dMemFun(this, &HttpConnectionManager::onTlsHandshake), id));
		op->setState (EstablishConnectionOp::WaitTls);
		addAsyncOp (op);
		return;
	}
	// plain http, can finish now..
	doFinish (result, op);
}
Ejemplo n.º 11
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);
}