/** * Nick received. If it's a downloader, fine, otherwise it must be an uploader. */ void ConnectionManager::on(UserConnectionListener::MyNick, UserConnection* aSource, const string& aNick) throw() { if(aSource->getState() != UserConnection::STATE_NICK) { // Already got this once, ignore... dcdebug("CM::onMyNick %p sent nick twice\n", aSource); return; } dcassert(aNick.size() > 0); dcdebug("ConnectionManager::onMyNick %p, %s\n", aSource, aNick.c_str()); dcassert(!aSource->getUser()); // First, we try looking in the pending downloads...hopefully it's one of them... { Lock l(cs); for(ConnectionQueueItem::Iter i = pendingDown.begin(); i != pendingDown.end(); ++i) { ConnectionQueueItem* cqi = *i; if(cqi->getUser()->getNick() == aNick) { aSource->setUser(cqi->getUser()); // Indicate that we're interested in this file... aSource->setFlag(UserConnection::FLAG_DOWNLOAD); } } } if(!aSource->getUser()) { // Make sure we know who it is, i e that he/she is connected... if(!ClientManager::getInstance()->isOnline(aNick)) { dcdebug("CM::onMyNick Incoming connection from unknown user %s\n", aNick.c_str()); putConnection(aSource); return; } aSource->setUser(ClientManager::getInstance()->getUser(aNick)); // We don't need this connection for downloading...make it an upload connection instead... aSource->setFlag(UserConnection::FLAG_UPLOAD); } if( aSource->isSet(UserConnection::FLAG_INCOMING) ) { aSource->myNick(aSource->getUser()->getClientNick()); aSource->lock(CryptoManager::getInstance()->getLock(), CryptoManager::getInstance()->getPk()); } aSource->setState(UserConnection::STATE_LOCK); }
void ConnectionManager::on(UserConnectionListener::MyNick, UserConnection* aSource, const string& aNick) throw() { if(aSource->getState() != UserConnection::STATE_SUPNICK) { // Already got this once, ignore... dcdebug("CM::onMyNick %p sent nick twice\n", (void*)aSource); return; } dcassert(aNick.size() > 0); dcdebug("ConnectionManager::onMyNick %p, %s\n", (void*)aSource, aNick.c_str()); dcassert(!aSource->getUser()); if(aSource->isSet(UserConnection::FLAG_INCOMING)) { // Try to guess where this came from... pair<string, string> i = expectedConnections.remove(aNick); if(i.second.empty()) { dcassert(i.first.empty()); dcdebug("Unknown incoming connection from %s\n", aNick.c_str()); putConnection(aSource); return; } aSource->setToken(i.first); aSource->setHubUrl(i.second); } CID cid = ClientManager::getInstance()->makeCid(aNick, aSource->getHubUrl()); // First, we try looking in the pending downloads...hopefully it's one of them... { Lock l(cs); for(ConnectionQueueItem::Iter i = downloads.begin(); i != downloads.end(); ++i) { ConnectionQueueItem* cqi = *i; if((cqi->getState() == ConnectionQueueItem::CONNECTING || cqi->getState() == ConnectionQueueItem::WAITING) && cqi->getUser()->getCID() == cid) { aSource->setUser(cqi->getUser()); // Indicate that we're interested in this file... aSource->setFlag(UserConnection::FLAG_DOWNLOAD); break; } } } if(!aSource->getUser()) { // Make sure we know who it is, i e that he/she is connected... aSource->setUser(ClientManager::getInstance()->findUser(cid)); if(!aSource->getUser() || !ClientManager::getInstance()->isOnline(aSource->getUser())) { dcdebug("CM::onMyNick Incoming connection from unknown user %s\n", aNick.c_str()); putConnection(aSource); return; } // We don't need this connection for downloading...make it an upload connection instead... aSource->setFlag(UserConnection::FLAG_UPLOAD); } if(ClientManager::getInstance()->isOp(aSource->getUser(), aSource->getHubUrl())) aSource->setFlag(UserConnection::FLAG_OP); if( aSource->isSet(UserConnection::FLAG_INCOMING) ) { aSource->myNick(aSource->getToken()); aSource->lock(CryptoManager::getInstance()->getLock(), CryptoManager::getInstance()->getPk()); } aSource->setState(UserConnection::STATE_LOCK); }
void ConnectionManager::on(TimerManagerListener::Second, uint32_t aTick) throw() { User::List passiveUsers; ConnectionQueueItem::List removed; User::List idlers; { Lock l(cs); bool attemptDone = false; idlers = checkIdle; checkIdle.clear(); for(ConnectionQueueItem::Iter i = downloads.begin(); i != downloads.end(); ++i) { ConnectionQueueItem* cqi = *i; if(cqi->getState() != ConnectionQueueItem::ACTIVE) { if(!cqi->getUser()->isOnline()) { // Not online anymore...remove it from the pending... removed.push_back(cqi); continue; } if(cqi->getUser()->isSet(User::PASSIVE) && !ClientManager::getInstance()->isActive()) { passiveUsers.push_back(cqi->getUser()); removed.push_back(cqi); continue; } if( ((cqi->getLastAttempt() + 60*1000) < aTick) && !attemptDone ) { cqi->setLastAttempt(aTick); QueueItem::Priority prio = QueueManager::getInstance()->hasDownload(cqi->getUser()); if(prio == QueueItem::PAUSED) { removed.push_back(cqi); continue; } bool startDown = DownloadManager::getInstance()->startDownload(prio); if(cqi->getState() == ConnectionQueueItem::WAITING) { if(startDown) { cqi->setState(ConnectionQueueItem::CONNECTING); ClientManager::getInstance()->connect(cqi->getUser()); fire(ConnectionManagerListener::StatusChanged(), cqi); attemptDone = true; } else { cqi->setState(ConnectionQueueItem::NO_DOWNLOAD_SLOTS); fire(ConnectionManagerListener::Failed(), cqi, STRING(ALL_DOWNLOAD_SLOTS_TAKEN)); } } else if(cqi->getState() == ConnectionQueueItem::NO_DOWNLOAD_SLOTS && startDown) { cqi->setState(ConnectionQueueItem::WAITING); } } else if(((cqi->getLastAttempt() + 50*1000) < aTick) && (cqi->getState() == ConnectionQueueItem::CONNECTING)) { fire(ConnectionManagerListener::Failed(), cqi, STRING(CONNECTION_TIMEOUT)); cqi->setState(ConnectionQueueItem::WAITING); } } } for(ConnectionQueueItem::Iter m = removed.begin(); m != removed.end(); ++m) { putCQI(*m); } } for(User::Iter i = idlers.begin(); i != idlers.end(); ++i) { DownloadManager::getInstance()->checkIdle(*i); } for(User::Iter ui = passiveUsers.begin(); ui != passiveUsers.end(); ++ui) { QueueManager::getInstance()->removeSource(*ui, QueueItem::Source::FLAG_PASSIVE); } }
void ConnectionManager::on(TimerManagerListener::Second, u_int32_t aTick) throw() { ConnectionQueueItem::List failPassive; ConnectionQueueItem::List connecting; ConnectionQueueItem::List removed; User::List getDown; { Lock l(cs); { for(User::Iter k = pendingAdd.begin(); k != pendingAdd.end(); ++k) { ConnectionQueueItem::Iter i = find(downPool.begin(), downPool.end(), *k); if(i == downPool.end()) { // Hm, connection must have failed before it could be collected... getDown.push_back(*k); } else { ConnectionQueueItem* cqi = *i; downPool.erase(i); dcassert(find(active.begin(), active.end(), cqi) == active.end()); active.push_back(cqi); dcassert(cqi->getConnection()); dcassert(cqi->getConnection()->getCQI() == cqi); cqi->getConnection()->removeListener(this); DownloadManager::getInstance()->addConnection(cqi->getConnection()); } } pendingAdd.clear(); } bool tooMany = ((SETTING(DOWNLOAD_SLOTS) != 0) && DownloadManager::getInstance()->getDownloads() >= (size_t)SETTING(DOWNLOAD_SLOTS)); bool tooFast = ((SETTING(MAX_DOWNLOAD_SPEED) != 0 && DownloadManager::getInstance()->getAverageSpeed() >= (SETTING(MAX_DOWNLOAD_SPEED)*1024))); bool startDown = !tooMany && !tooFast; int attempts = 0; ConnectionQueueItem::Iter i = pendingDown.begin(); while(i != pendingDown.end()) { ConnectionQueueItem* cqi = *i; dcassert(cqi->getUser()); if(!cqi->getUser()->isOnline()) { // Not online anymore...remove him from the pending... i = pendingDown.erase(i); removed.push_back(cqi); continue; } if( ((cqi->getLastAttempt() + 60*1000) < aTick) && (attempts < 2) ) { cqi->setLastAttempt(aTick); if(!QueueManager::getInstance()->hasDownload(cqi->getUser())) { i = pendingDown.erase(i); removed.push_back(cqi); continue; } if(cqi->getUser()->isSet(User::PASSIVE) && (SETTING(CONNECTION_TYPE) != SettingsManager::CONNECTION_ACTIVE)) { i = pendingDown.erase(i); failPassive.push_back(cqi); continue; } // Always start high-priority downloads unless we have 3 more than maxdownslots already... if(!startDown) { bool extraFull = (SETTING(DOWNLOAD_SLOTS) != 0) && (DownloadManager::getInstance()->getDownloads() >= (size_t)(SETTING(DOWNLOAD_SLOTS)+3)); startDown = !extraFull && QueueManager::getInstance()->hasDownload(cqi->getUser(), QueueItem::HIGHEST); } if(cqi->getState() == ConnectionQueueItem::WAITING) { if(startDown) { cqi->setState(ConnectionQueueItem::CONNECTING); cqi->getUser()->connect(); fire(ConnectionManagerListener::StatusChanged(), cqi); attempts++; } else { cqi->setState(ConnectionQueueItem::NO_DOWNLOAD_SLOTS); fire(ConnectionManagerListener::Failed(), cqi, STRING(ALL_DOWNLOAD_SLOTS_TAKEN)); } } else if(cqi->getState() == ConnectionQueueItem::NO_DOWNLOAD_SLOTS && startDown) { cqi->setState(ConnectionQueueItem::WAITING); } } else if(((cqi->getLastAttempt() + 50*1000) < aTick) && (cqi->getState() == ConnectionQueueItem::CONNECTING)) { fire(ConnectionManagerListener::Failed(), cqi, STRING(CONNECTION_TIMEOUT)); cqi->setState(ConnectionQueueItem::WAITING); } ++i; } } ConnectionQueueItem::Iter m; for(m = removed.begin(); m != removed.end(); ++m) { fire(ConnectionManagerListener::Removed(), *m); delete *m; } for(m = failPassive.begin(); m != failPassive.end(); ++m) { QueueManager::getInstance()->removeSources((*m)->getUser(), QueueItem::Source::FLAG_PASSIVE); fire(ConnectionManagerListener::Removed(), *m); delete *m; } for(User::Iter n = getDown.begin(); n != getDown.end(); ++n) { getDownloadConnection(*n); } }