📄 connectionmanager.cpp
字号:
if(feat == UserConnection::FEATURE_ADC_BASE)
baseOk = true;
else if(feat == UserConnection::FEATURE_ZLIB_GET)
aSource->setFlag(UserConnection::FLAG_SUPPORTS_ZLIB_GET);
}
}
if(!baseOk) {
aSource->send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_GENERIC, "Invalid SUP"));
aSource->disconnect();
return;
}
if(aSource->isSet(UserConnection::FLAG_INCOMING)) {
StringList defFeatures = adcFeatures;
if(BOOLSETTING(COMPRESS_TRANSFERS)) {
defFeatures.push_back("AD" + UserConnection::FEATURE_ZLIB_GET);
}
aSource->sup(defFeatures);
aSource->inf(false);
} else {
aSource->inf(true);
}
aSource->setState(UserConnection::STATE_INF);
}
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->getToken());
aSource->lock(CryptoManager::getInstance()->getLock(), CryptoManager::getInstance()->getPk());
} else {
StringList defFeatures = adcFeatures;
if(BOOLSETTING(COMPRESS_TRANSFERS)) {
defFeatures.push_back("AD" + UserConnection::FEATURE_ZLIB_GET);
}
aSource->sup(defFeatures);
}
aSource->setState(UserConnection::STATE_SUPNICK);
}
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(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", (void*)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);
}
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", (void*)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) {
dcassert(uc->isSet(UserConnection::FLAG_DOWNLOAD));
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) {
cqi->setState(ConnectionQueueItem::ACTIVE);
uc->setFlag(UserConnection::FLAG_ASSOCIATED);
fire(ConnectionManagerListener::Connected(), cqi);
dcdebug("ConnectionManager::addDownloadConnection, leaving to downloadmanager\n");
addConn = true;
}
}
}
if(addConn) {
DownloadManager::getInstance()->addConnection(uc);
} else {
putConnection(uc);
}
}
void ConnectionManager::addUploadConnection(UserConnection* uc) {
dcassert(uc->isSet(UserConnection::FLAG_UPLOAD));
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);
cqi->setState(ConnectionQueueItem::ACTIVE);
uc->setFlag(UserConnection::FLAG_ASSOCIATED);
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);
} 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->send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_GENERIC, "Expecting INF"));
dcdebug("CM::onINF %p sent INF twice\n", (void*)aSource);
aSource->disconnect();
return;
}
string cid;
if(!cmd.getParam("ID", 0, cid)) {
aSource->send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_INF_MISSING, "ID missing").addParam("FL", "ID"));
dcdebug("CM::onINF missing ID\n");
aSource->disconnect();
return;
}
aSource->setUser(ClientManager::getInstance()->findUser(CID(cid)));
if(!aSource->getUser()) {
dcdebug("CM::onINF: User not found");
aSource->send(AdcCommand(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);
} else {
aSource->setFlag(UserConnection::FLAG_UPLOAD);
addUploadConnection(aSource);
}
}
void ConnectionManager::on(UserConnectionListener::Failed, UserConnection* aSource, const string& aError) throw() {
Lock l(cs);
if(aSource->isSet(UserConnection::FLAG_ASSOCIATED)) {
if(aSource->isSet(UserConnection::FLAG_DOWNLOAD)) {
ConnectionQueueItem::Iter i = find(downloads.begin(), downloads.end(), aSource->getUser());
dcassert(i != downloads.end());
ConnectionQueueItem* cqi = *i;
cqi->setState(ConnectionQueueItem::WAITING);
cqi->setLastAttempt(GET_TICK());
fire(ConnectionManagerListener::Failed(), cqi, aError);
} else if(aSource->isSet(UserConnection::FLAG_UPLOAD)) {
ConnectionQueueItem::Iter i = find(uploads.begin(), uploads.end(), aSource->getUser());
dcassert(i != uploads.end());
ConnectionQueueItem* cqi = *i;
putCQI(cqi);
}
}
putConnection(aSource);
}
void ConnectionManager::disconnect(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(true);
break;
}
}
}
void ConnectionManager::shutdown() {
TimerManager::getInstance()->removeListener(this);
shuttingDown = true;
disconnect();
{
Lock l(cs);
for(UserConnection::Iter j = userConnections.begin(); j != userConnections.end(); ++j) {
(*j)->disconnect(true);
}
}
// 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);
if(conn->getUser())
conn->getUser()->setFlag(User::TTH_GET);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -