📄 connectionmanager.cpp
字号:
void ConnectionManager::adcConnect(const string& aServer, short aPort, const string& aToken) {
if(shuttingDown)
return;
UserConnection* uc = NULL;
try {
uc = getConnection(false);
uc->setToken(aToken);
uc->setState(UserConnection::STATE_CONNECT);
uc->connect(aServer, aPort);
} catch(const SocketException&) {
if(uc)
putConnection(uc);
}
}
void ConnectionManager::on(AdcCommand::SUP, UserConnection* aSource, const AdcCommand&) throw() {
if(aSource->getState() != UserConnection::STATE_SUPNICK) {
// Already got this once, ignore...
dcdebug("CM::onMyNick %p sent nick twice\n", aSource);
return;
}
if(aSource->isSet(UserConnection::FLAG_INCOMING)) {
aSource->sup(adcFeatures);
aSource->inf(false);
} else {
aSource->inf(true);
}
aSource->setState(UserConnection::STATE_INF);
}
void ConnectionManager::on(AdcCommand::NTD, UserConnection*, const AdcCommand&) throw() {
}
void ConnectionManager::on(AdcCommand::STA, UserConnection*, const AdcCommand&) throw() {
}
void ConnectionManager::on(UserConnectionListener::Connected, UserConnection* aSource) throw() {
dcassert(aSource->getState() == UserConnection::STATE_CONNECT);
if(aSource->isSet(UserConnection::FLAG_NMDC)) {
aSource->myNick(aSource->getNick());
aSource->lock(CryptoManager::getInstance()->getLock(), CryptoManager::getInstance()->getPk());
} else {
aSource->sup(adcFeatures);
}
aSource->setState(UserConnection::STATE_SUPNICK);
}
/**
* 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_SUPNICK) {
// 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 = downloads.begin(); i != downloads.end(); ++i) {
ConnectionQueueItem* cqi = *i;
if((cqi->getState() == ConnectionQueueItem::CONNECTING || cqi->getState() == ConnectionQueueItem::WAITING) && cqi->getUser()->getNick() == aNick) {
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...
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::CLock, UserConnection* aSource, const string& aLock, const string& aPk) throw() {
if(aSource->getState() != UserConnection::STATE_LOCK) {
dcdebug("CM::onLock %p received lock twice, ignoring\n", aSource);
return;
}
if( CryptoManager::getInstance()->isExtended(aLock) ) {
// Alright, we have an extended protocol, set a user flag for this user and refresh his info...
if( (aPk.find("DCPLUSPLUS") != string::npos) && aSource->getUser() && !aSource->getUser()->isSet(User::DCPLUSPLUS)) {
aSource->getUser()->setFlag(User::DCPLUSPLUS);
User::updated(aSource->getUser());
}
StringList defFeatures = features;
if(BOOLSETTING(COMPRESS_TRANSFERS)) {
defFeatures.push_back(UserConnection::FEATURE_GET_ZBLOCK);
defFeatures.push_back(UserConnection::FEATURE_ZLIB_GET);
}
aSource->supports(defFeatures);
}
aSource->setState(UserConnection::STATE_DIRECTION);
aSource->direction(aSource->getDirectionString(), aSource->getNumber());
aSource->key(CryptoManager::getInstance()->makeKey(aLock));
}
void ConnectionManager::on(UserConnectionListener::Direction, UserConnection* aSource, const string& dir, const string& num) throw() {
if(aSource->getState() != UserConnection::STATE_DIRECTION) {
dcdebug("CM::onDirection %p received direction twice, ignoring\n", aSource);
return;
}
dcassert(aSource->isSet(UserConnection::FLAG_DOWNLOAD) ^ aSource->isSet(UserConnection::FLAG_UPLOAD));
if(dir == "Upload") {
// Fine, the other fellow want's to send us data...make sure we really want that...
if(aSource->isSet(UserConnection::FLAG_UPLOAD)) {
// Huh? Strange...disconnect...
putConnection(aSource);
return;
}
} else {
if(aSource->isSet(UserConnection::FLAG_DOWNLOAD)) {
int number = Util::toInt(num);
// Damn, both want to download...the one with the highest number wins...
if(aSource->getNumber() < number) {
// Damn! We lost!
aSource->unsetFlag(UserConnection::FLAG_DOWNLOAD);
aSource->setFlag(UserConnection::FLAG_UPLOAD);
} else if(aSource->getNumber() == number) {
putConnection(aSource);
return;
}
}
}
dcassert(aSource->isSet(UserConnection::FLAG_DOWNLOAD) ^ aSource->isSet(UserConnection::FLAG_UPLOAD));
aSource->setState(UserConnection::STATE_KEY);
}
void ConnectionManager::addDownloadConnection(UserConnection* uc, bool sendNTD) {
dcassert(uc->isSet(UserConnection::FLAG_DOWNLOAD));
uc->removeListener(this);
bool addConn = false;
{
Lock l(cs);
ConnectionQueueItem::Iter i = find(downloads.begin(), downloads.end(), uc->getUser());
if(i != downloads.end()) {
ConnectionQueueItem* cqi = *i;
if(cqi->getState() == ConnectionQueueItem::WAITING || cqi->getState() == ConnectionQueueItem::CONNECTING) {
// Associate the two...
dcassert(uc->getCQI() == NULL);
uc->setCQI(cqi);
dcassert(cqi->getConnection() == NULL);
cqi->setConnection(uc);
cqi->setState(ConnectionQueueItem::ACTIVE);
fire(ConnectionManagerListener::Connected(), cqi);
dcdebug("ConnectionManager::addDownloadConnection, leaving to downloadmanager\n");
addConn = true;
}
}
}
if(addConn) {
DownloadManager::getInstance()->addConnection(uc);
} else if(sendNTD) {
uc->ntd();
uc->unsetFlag(UserConnection::FLAG_DOWNLOAD);
uc->setFlag(UserConnection::FLAG_UPLOAD);
addUploadConnection(uc);
} else {
putConnection(uc);
}
}
void ConnectionManager::addUploadConnection(UserConnection* uc) {
dcassert(uc->isSet(UserConnection::FLAG_UPLOAD));
uc->removeListener(this);
bool addConn = false;
{
Lock l(cs);
ConnectionQueueItem::Iter i = find(uploads.begin(), uploads.end(), uc->getUser());
if(i == uploads.end()) {
ConnectionQueueItem* cqi = getCQI(uc->getUser(), false);
uc->setCQI(cqi);
cqi->setConnection(uc);
cqi->setState(ConnectionQueueItem::ACTIVE);
fire(ConnectionManagerListener::Connected(), cqi);
dcdebug("ConnectionManager::addUploadConnection, leaving to uploadmanager\n");
addConn = true;
}
}
if(addConn) {
UploadManager::getInstance()->addConnection(uc);
} else {
putConnection(uc);
}
}
void ConnectionManager::on(UserConnectionListener::Key, UserConnection* aSource, const string&/* aKey*/) throw() {
if(aSource->getState() != UserConnection::STATE_KEY) {
dcdebug("CM::onKey Bad state, ignoring");
return;
}
dcassert(aSource->getUser());
if(aSource->isSet(UserConnection::FLAG_DOWNLOAD)) {
addDownloadConnection(aSource, false);
} else {
addUploadConnection(aSource);
}
}
void ConnectionManager::on(AdcCommand::INF, UserConnection* aSource, const AdcCommand& cmd) throw() {
if(aSource->getState() != UserConnection::STATE_INF) {
// Already got this once, ignore...
aSource->sta(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_GENERIC, "Expecting INF");
dcdebug("CM::onMyNick %p sent nick twice\n", aSource);
return;
}
aSource->setUser(ClientManager::getInstance()->getUser(cmd.getFrom(), false));
if(!aSource->getUser()) {
dcdebug("CM::onINF: User not found");
aSource->sta(AdcCommand::SEV_FATAL, AdcCommand::ERROR_GENERIC, "User not found");
putConnection(aSource);
return;
}
if(aSource->isSet(UserConnection::FLAG_INCOMING)) {
aSource->setFlag(UserConnection::FLAG_DOWNLOAD);
addDownloadConnection(aSource, true);
} else {
aSource->setFlag(UserConnection::FLAG_UPLOAD);
addUploadConnection(aSource);
}
}
void ConnectionManager::on(UserConnectionListener::Failed, UserConnection* aSource, const string& /*aError*/) throw() {
if(aSource->isSet(UserConnection::FLAG_DOWNLOAD) && aSource->getCQI()) {
{
Lock l(cs);
ConnectionQueueItem* cqi = aSource->getCQI();
dcassert(cqi->getState() == ConnectionQueueItem::IDLE);
cqi->setState(ConnectionQueueItem::WAITING);
cqi->setLastAttempt(GET_TICK());
cqi->setConnection(NULL);
aSource->setCQI(NULL);
}
}
putConnection(aSource);
}
void ConnectionManager::removeConnection(const User::Ptr& aUser, int isDownload) {
Lock l(cs);
for(UserConnection::Iter i = userConnections.begin(); i != userConnections.end(); ++i) {
UserConnection* uc = *i;
if(uc->getUser() == aUser && uc->isSet(isDownload ? UserConnection::FLAG_DOWNLOAD : UserConnection::FLAG_UPLOAD)) {
uc->disconnect();
break;
}
}
}
void ConnectionManager::shutdown() {
shuttingDown = true;
socket.removeListener(this);
socket.disconnect();
{
Lock l(cs);
for(UserConnection::Iter j = userConnections.begin(); j != userConnections.end(); ++j) {
(*j)->disconnect();
}
}
// Wait until all connections have died out...
while(true) {
{
Lock l(cs);
if(userConnections.empty()) {
break;
}
}
Thread::sleep(50);
}
}
// UserConnectionListener
void ConnectionManager::on(UserConnectionListener::Supports, UserConnection* conn, const StringList& feat) throw() {
for(StringList::const_iterator i = feat.begin(); i != feat.end(); ++i) {
if(*i == UserConnection::FEATURE_GET_ZBLOCK)
conn->setFlag(UserConnection::FLAG_SUPPORTS_GETZBLOCK);
else if(*i == UserConnection::FEATURE_MINISLOTS)
conn->setFlag(UserConnection::FLAG_SUPPORTS_MINISLOTS);
else if(*i == UserConnection::FEATURE_XML_BZLIST)
conn->setFlag(UserConnection::FLAG_SUPPORTS_XML_BZLIST);
else if(*i == UserConnection::FEATURE_ADCGET)
conn->setFlag(UserConnection::FLAG_SUPPORTS_ADCGET);
else if(*i == UserConnection::FEATURE_ZLIB_GET)
conn->setFlag(UserConnection::FLAG_SUPPORTS_ZLIB_GET);
else if(*i == UserConnection::FEATURE_TTHL)
conn->setFlag(UserConnection::FLAG_SUPPORTS_TTHL);
else if(*i == UserConnection::FEATURE_TTHF)
conn->setFlag(UserConnection::FLAG_SUPPORTS_TTHF);
}
}
/**
* @file
* $Id: ConnectionManager.cpp,v 1.96 2005/03/19 13:00:47 arnetheduck Exp $
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -