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