void ConnectionManager::on(UserConnectionListener::Key, UserConnection* aSource, const string&/* aKey*/) throw() { if(aSource->getState() != UserConnection::STATE_KEY) { dcdebug("CM::onKey Bad state, ignoring"); return; } // We don't want any messages while the Up/DownloadManagers are working... aSource->removeListener(this); dcassert(aSource->getUser()); { Lock l(cs); // Only one connection / user & direction... for(ConnectionQueueItem::Iter k = active.begin(); k != active.end(); ++k) { bool sameDirection = (*k)->getConnection()->isSet(UserConnection::FLAG_UPLOAD) == aSource->isSet(UserConnection::FLAG_UPLOAD); if( sameDirection && (*k == aSource->getUser()) ) { putConnection(aSource); return; } } ConnectionQueueItem* cqi = NULL; if(aSource->isSet(UserConnection::FLAG_DOWNLOAD)) { // See if we have a matching user in the pending connections... ConnectionQueueItem::Iter i = find(pendingDown.begin(), pendingDown.end(), aSource->getUser()); if(i == pendingDown.end()) { putConnection(aSource); return; } cqi = *i; pendingDown.erase(i); cqi->setConnection(aSource); } else { dcassert(aSource->isSet(UserConnection::FLAG_UPLOAD)); cqi = new ConnectionQueueItem(aSource->getUser()); cqi->setConnection(aSource); fire(ConnectionManagerListener::Added(), cqi); } aSource->setCQI(cqi); dcassert(find(active.begin(), active.end(), cqi) == active.end()); active.push_back(cqi); fire(ConnectionManagerListener::Connected(), cqi); if(aSource->isSet(UserConnection::FLAG_DOWNLOAD)) { dcdebug("ConnectionManager::onKey, leaving to downloadmanager\n"); DownloadManager::getInstance()->addConnection(aSource); } else { dcassert(aSource->isSet(UserConnection::FLAG_UPLOAD)); dcdebug("ConnectionManager::onKey, leaving to uploadmanager\n"); UploadManager::getInstance()->addConnection(aSource); } } }
void ConnectionManager::putDownloadConnection(UserConnection* aSource, bool reuse /* = false */) { // Pool it for later usage... if(reuse) { aSource->addListener(this); { Lock l(cs); aSource->getCQI()->setState(ConnectionQueueItem::IDLE); dcassert(find(active.begin(), active.end(), aSource->getCQI()) != active.end()); active.erase(find(active.begin(), active.end(), aSource->getCQI())); downPool.push_back(aSource->getCQI()); } dcdebug("ConnectionManager::putDownloadConnection Pooling reusable connection %p to %s\n", aSource, aSource->getUser()->getNick().c_str()); } else { if(QueueManager::getInstance()->hasDownload(aSource->getCQI()->getUser())) { aSource->removeListeners(); aSource->disconnect(); Lock l(cs); ConnectionQueueItem* cqi = aSource->getCQI(); dcassert(cqi); // Remove the userconnection, don't need it any more dcassert(find(userConnections.begin(), userConnections.end(), aSource) != userConnections.end()); userConnections.erase(find(userConnections.begin(), userConnections.end(), aSource)); pendingDelete.push_back(aSource); cqi->setConnection(NULL); cqi->setState(ConnectionQueueItem::WAITING); dcassert(find(active.begin(), active.end(), aSource->getCQI()) != active.end()); active.erase(find(active.begin(), active.end(), aSource->getCQI())); cqi->setLastAttempt(GET_TICK()); pendingDown.push_back(cqi); } else { { Lock l(cs); dcassert(find(active.begin(), active.end(), aSource->getCQI()) != active.end()); active.erase(find(active.begin(), active.end(), aSource->getCQI())); } putConnection(aSource); } } }