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 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)); }
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 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)); } }
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; }
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 XMPPStream::finishOp (CurrentOp op, Error result) { if (mCurrentOp == op) { if (mCurrentCallback) xcall (abind (mCurrentCallback, result)); mCurrentCallback.clear(); mCurrentOp = XMO_Null; } }
void DataTracker::onSubscribeReply (const HostId & sender, const ds::SubscribeReply & reply, TrackInfoPtr info) { bool doNotifyState = false; do { info->awaiting &= ~AwaitSubscribe; if (info->state == TO_DELETE || info->state == ERROR){ return; } if (reply.err){ info->state = ERROR; doNotifyState = true; break; } // do first request now sf::Error err = mSharingClient->request ( info->uri.host(), ds::Request (info->uri.path()), abind (sf::dMemFun (this, &DataTracker::onRequestReply), info), mTimeOutMs); if (err) { info->state = ERROR; doNotifyState = true; break; } else { info->awaiting |= AwaitRequest; } } while (false); if (doNotifyState) { info->stateChanged (info->uri, info->state); } }
void DataTracker::onNotify (const HostId & sender, const ds::Notify & notify, TrackInfoPtr info) { bool doNotifyState = false; do { if (notify.mark == ds::Notify::SubscriptionCancel){ info->state = LOST; doNotifyState = true; break; } // request an update.. if (notify.revision > info->revision){ // may happen that notify is slower than requestreply Error err = mSharingClient->request ( info->uri.host(), ds::Request (info->uri.path()), abind (sf::dMemFun (this, &DataTracker::onRequestReply), info), mTimeOutMs); if (err){ info->state = ERROR; doNotifyState = true; } else { info->awaiting |=AwaitRequest; } } } while (false); if (doNotifyState) { info->stateChanged(info->uri, info->state); } }
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 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); }
Error DataTracker::track (const sf::Uri & uri, const DataUpdateCallback & dataUpdateCallback, const StateChangeCallback & stateChangeCallback){ TrackInfoPtr info (new TrackInfo); Error subscribeResult = mSharingClient->subscribe ( uri.host(), ds::Subscribe(uri.path()), abind (sf::dMemFun (this, &DataTracker::onSubscribeReply), info), abind (sf::dMemFun (this, &DataTracker::onNotify), info), mTimeOutMs ); if (subscribeResult) return subscribeResult; info->awaiting = AwaitSubscribe; info->state = ESTABLISHING; // No Track change info info->dataUpdated = dataUpdateCallback; info->stateChanged = stateChangeCallback; info->uri = uri; mTracked[uri] = info; return NoError; }
int trans_load(void) { struct sr_module *mod; struct sr_module *prev = NULL, *next; cmd_export_t *cmd; char * proto_name; int proto = PROTO_NONE; api_proto_init abind; /* go through all protocol modules loaded and load only the ones * that are prefixed with the PROTO_PREFIX token */ for (mod=modules; mod && (next = mod->next, 1); mod = next) { if (strncmp(PROTO_PREFIX, mod->exports->name, PROTO_PREFIX_LEN) == 0) { proto_name = mod->exports->name + PROTO_PREFIX_LEN; if (parse_proto((unsigned char *)proto_name, strlen(proto_name), &proto) < 0) { LM_ERR("don't know any protocol <%s>\n", proto_name); return -1; } /* check if we have any listeners for that protocol */ if (!protos[proto].listeners) { LM_WARN("protocol %s loaded, but no listeners defined! " "Skipping ...\n", proto_name); if (!prev) modules = mod->next; else prev->next = mod->next; /* we do not call the destroy_f because the module was not * initialized yet here */ pkg_free(mod); continue; } for (cmd = mod->exports->cmds; cmd && cmd->name; cmd++) { if (strcmp("proto_init", cmd->name)==0) { abind = (api_proto_init)cmd->function; if (abind(&protos[proto]) < 0) { LM_ERR("cannot load protocol's functions for %s\n", proto_name); return -1; } /* everything was fine, return */ protos[proto].id = proto; protos[proto].name = proto_name; goto next; } } LM_ERR("No binding found for protocol %s\n", proto_name); return -1; } next: prev = mod; } return 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; }
void XMPPStream::onChannelError (Error e) { mError = e; if (mCurrentCallback) { xcall (abind (mCurrentCallback,e)); } if (mAsyncError) { xcall (mAsyncError); } mCurrentOp = XMO_Null; mState = XMS_Error; }
DataPromisePtr DirectorySharingPromise::subFile (const Path & path) const { String osp = osPath (path); if (mError) { return DataPromisePtr(); } FileSharingPromisePtr p (new FileSharingPromise (osp)); if (mTransmissionUpdated){ p->transmissionUpdated() = abind (mTransmissionUpdated, weak_ptr<FileSharingPromise> (p)); } return DataPromisePtr (p); }
Error XMPPStream::close () { Error e = NoError; if (!mSkipInit){ e = send ("</stream:stream>"); } if (mChannel) { mChannel->changed().clear (); mChannel->close(abind (dMemFun (this, &XMPPStream::throwAwayOnClose), mChannel)); mChannel = ChannelPtr (); } return e; }
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; }
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); }
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)); }
Error XMPPStream::bindResource (const String & name, const BindCallback & callback) { BindIq iq; iq.resource = name; return requestIq (&iq, abind (dMemFun (this, &XMPPStream::onResourceBind), callback)); }
void Node::RegisterUser(REG_TYPE type,char * aor,char *contact,char *username,char * passwd) { /* REGISTER sip:[email protected] SIP/2.0 Via:SIP/2.0/UDP 192.168.1.61:15060;branch=z9hG4bkxxxxx To:liqq <sip:[email protected]> From:liqq <sip:[email protected]> Call-ID: CSeq: Contact:<sip:[email protected]> Content-Length:0 */ /*判断本节点是否对该用户信息负责, 如果负责,添加到user_info_list, 如果不负责,计算next-hop,并发送REGISTER请求*/ unsigned int uid; uid=uhash(aor); ChordId localnode=getChordId(); ChordId pred=getFingerTable()->getPredecessor(); Constants constants(NULL); ChordId UserID(uid,&constants); aor_t aaor(aor); binding_t abind(contact); uinfo_t *user_info=new uinfo_t(username,passwd); user_info->uinfo_set_aor(&aaor); user_info->uinfo_set_binding(&abind); ADD_ELEMENT(local_user_info_list,user_info); // int lid=localnode.GetId(); // int pid=predecessor.GetId(); //if((lid<pid && uid<=lid && uid>pid)||(lid>pid && (uid < lid || uid >=pid))) if(UserID.BelongsRightInclusive(pred,localnode)) { printf("Add a new local user\n"); uinfo_t *uinfo=new uinfo_t(username,passwd); uinfo->uinfo_set_aor(&aaor); uinfo->uinfo_set_binding(&abind); ADD_ELEMENT(user_info_list,uinfo); if(pred.equals(localnode)) { uinfo_t *ruinfo=new uinfo_t(username,passwd); ruinfo->uinfo_set_aor(&aaor); ruinfo->uinfo_set_binding(&abind); ADD_ELEMENT(red_user_info_list,ruinfo); } ChordId succ=getFingerTable()->getSuccessor(0); if(!succ.equals(getChordId())) { string next_hop="sip:"; next_hop+=succ.GetAddress(); SndUserRegisterRequest(RED_REGISTER,uinfo,next_hop.c_str() ,3600); } } else { ChordId node=closestPrecedingFinger(UserID); //ChordId node=getFingerTable()->getPredecessor(); //ChordId node=getChordId(); string registrar="sip:"; registrar+=node.GetAddress(); SndUserRegisterRequest(USER_REGISTRATION,user_info,registrar.c_str() ,3600); } }
Error XMPPStream::startSession (const ResultCallback & callback) { SessionIq iq; // hack typedef function<void (Error, const xmpp::Iq &, const XMLChunk &, const ResultCallback &)> InternalHandler; return requestIq (&iq, abind (&sessionIqResultHandler, callback)); }
void BoshXMPPConnection::setState (State s) { if (mConnectionStateChanged) xcall (abind (mConnectionStateChanged, s)); mState = s; }
int trans_load(void) { int id; struct sr_module *mod; cmd_export_t *cmd; int found_all = 0; int found_proto; api_proto_init abind; struct proto_info pi; /* go through all protocol modules loaded and load only the ones * that are prefixed with the PROTO_PREFIX token */ for (mod = modules; mod; mod = mod->next) { if (strncmp(PROTO_PREFIX, mod->exports->name, PROTO_PREFIX_LEN) != 0) continue; found_proto = 0; /* we have a transport module here - check for protocols */ for (cmd = mod->exports->cmds; cmd && cmd->name; cmd++) { if (strcmp("proto_init", cmd->name)==0) { abind = (api_proto_init)cmd->function; memset(&pi, 0, sizeof(pi)); if (abind(&pi) < 0) { LM_ERR("cannot load protocol's functions for %s\n", cmd->name); return -1; } /* double check if it is a known/valid proto */ if (pi.id < PROTO_FIRST || pi.id >= PROTO_OTHER) { LM_ERR("Unknown protocol id %d; check sip_protos structure!\n", pi.id); return -1; } /* double check the name of the proto */ if (parse_proto((unsigned char *)pi.name, strlen(pi.name), &id) < 0) { LM_ERR("Cannot parse protocol %s\n", pi.name); return -1; } if (id != pi.id) { LM_ERR("Protocol ID mismatch %d != %d\n", id, pi.id); return -1; } /* check if already added */ if (protos[id].id != PROTO_NONE) { LM_ERR("Protocol already loaded %s\n", pi.name); return -1; } /* all good now */ found_all++; found_proto = 1; /* copy necessary info */ protos[pi.id].id = pi.id; protos[pi.id].name = pi.name; protos[pi.id].default_port = pi.default_port; protos[pi.id].tran = pi.tran; protos[pi.id].net = pi.net; } } if (found_proto) continue; LM_ERR("No binding found for protocol %s\n", mod->exports->name); return -1; } /* return whether we found any protocol or not */ return found_all; }
void XMPPStream::uncouple () { mChannel->changed().clear (); xcall (abind (dMemFun (this, &XMPPStream::throwAwayChannel), mChannel)); mChannel = ChannelPtr (); }