📄 nmdchub.cpp
字号:
/*
* Copyright (C) 2001-2006 Jacek Sieka, arnetheduck on gmail point com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "stdinc.h"
#include "DCPlusPlus.h"
#include "NmdcHub.h"
#include "ResourceManager.h"
#include "ClientManager.h"
#include "SearchManager.h"
#include "ShareManager.h"
#include "CryptoManager.h"
#include "ConnectionManager.h"
#include "Socket.h"
#include "UserCommand.h"
#include "StringTokenizer.h"
NmdcHub::NmdcHub(const string& aHubURL) : Client(aHubURL, '|', false), supportFlags(0), state(STATE_CONNECT),
reconnect(true), lastUpdate(0)
{
TimerManager::getInstance()->addListener(this);
}
NmdcHub::~NmdcHub() throw() {
TimerManager::getInstance()->removeListener(this);
clearUsers();
}
void NmdcHub::connect() {
reconnect = true;
supportFlags = 0;
lastMyInfoA.clear();
lastMyInfoB.clear();
lastUpdate = 0;
state = STATE_LOCK;
Client::connect();
}
#define checkstate() if(state != STATE_CONNECTED) return
void NmdcHub::connect(const OnlineUser& aUser) {
checkstate();
dcdebug("NmdcHub::connect %s\n", aUser.getIdentity().getNick().c_str());
if(ClientManager::getInstance()->isActive()) {
connectToMe(aUser);
} else {
revConnectToMe(aUser);
}
}
int64_t NmdcHub::getAvailable() const {
Lock l(cs);
int64_t x = 0;
for(NickMap::const_iterator i = users.begin(); i != users.end(); ++i) {
x+=i->second->getIdentity().getBytesShared();
}
return x;
}
OnlineUser& NmdcHub::getUser(const string& aNick) {
OnlineUser* u = NULL;
{
Lock l(cs);
NickIter i = users.find(aNick);
if(i != users.end())
return *i->second;
}
User::Ptr p;
if(aNick == getMyNick()) {
p = ClientManager::getInstance()->getMe();
getMyIdentity().setUser(p);
getMyIdentity().setHubUrl(getHubUrl());
} else {
p = ClientManager::getInstance()->getUser(aNick, getHubUrl());
}
{
Lock l(cs);
u = users.insert(make_pair(aNick, new OnlineUser(p, *this, 0))).first->second;
u->getIdentity().setNick(aNick);
}
ClientManager::getInstance()->putOnline(*u);
return *u;
}
void NmdcHub::supports(const StringList& feat) {
string x;
for(StringList::const_iterator i = feat.begin(); i != feat.end(); ++i) {
x+= *i + ' ';
}
send("$Supports " + x + '|');
}
OnlineUser* NmdcHub::findUser(const string& aNick) {
Lock l(cs);
NickIter i = users.find(aNick);
return i == users.end() ? NULL : i->second;
}
void NmdcHub::putUser(const string& aNick) {
OnlineUser* u = NULL;
{
Lock l(cs);
NickIter i = users.find(aNick);
if(i == users.end())
return;
u = i->second;
users.erase(i);
}
ClientManager::getInstance()->putOffline(*u);
delete u;
}
void NmdcHub::clearUsers() {
NickMap u2;
{
Lock l(cs);
u2 = users;
users.clear();
}
for(NickIter i = u2.begin(); i != u2.end(); ++i) {
ClientManager::getInstance()->putOffline(*i->second);
delete i->second;
}
}
void NmdcHub::updateFromTag(Identity& id, const string& tag) {
StringTokenizer<string> tok(tag, ',');
for(StringIter i = tok.getTokens().begin(); i != tok.getTokens().end(); ++i) {
if(i->length() < 2)
continue;
if(i->compare(0, 2, "H:") == 0) {
StringTokenizer<string> t(i->substr(2), '/');
if(t.getTokens().size() != 3)
continue;
id.set("HN", t.getTokens()[0]);
id.set("HR", t.getTokens()[1]);
id.set("HO", t.getTokens()[2]);
} else if(i->compare(0, 2, "S:") == 0) {
id.set("SL", i->substr(2));
} else if(i->find("V:") != string::npos) {
string::size_type j = i->find("V:");
i->erase(i->begin() + j, i->begin() + j + 2);
id.set("VE", *i);
} else if(i->compare(0, 2, "M:") == 0) {
if(i->size() == 3) {
if((*i)[2] == 'A')
id.getUser()->unsetFlag(User::PASSIVE);
else
id.getUser()->setFlag(User::PASSIVE);
}
}
}
/// @todo Think about this
id.set("TA", '<' + tag + '>');
}
void NmdcHub::onLine(const string& aLine) throw() {
updateActivity();
if(aLine.length() == 0)
return;
if(aLine[0] != '$') {
// Check if we're being banned...
if(state != STATE_CONNECTED) {
if(Util::findSubString(aLine, "banned") != string::npos) {
reconnect = false;
}
}
string line = fromNmdc(aLine);
// @todo Decrypt who the message is from...
fire(ClientListener::StatusMessage(), this, Util::validateMessage(fromNmdc(aLine), true));
return;
}
string cmd;
string param;
string::size_type x;
if( (x = aLine.find(' ')) == string::npos) {
cmd = aLine;
} else {
cmd = aLine.substr(0, x);
param = fromNmdc(aLine.substr(x+1));
}
if(cmd == "$Search") {
if(state != STATE_CONNECTED) {
return;
}
string::size_type i = 0;
string::size_type j = param.find(' ', i);
if(j == string::npos || i == j)
return;
string seeker = param.substr(i, j-i);
// Filter own searches
if(ClientManager::getInstance()->isActive()) {
if(seeker == (ClientManager::getInstance()->getCachedIp() + ":" + Util::toString(SearchManager::getInstance()->getPort()))) {
return;
}
} else {
// Hub:seeker
if(Util::stricmp(seeker.c_str() + 4, getMyNick().c_str()) == 0) {
return;
}
}
i = j + 1;
{
Lock l(cs);
u_int32_t tick = GET_TICK();
seekers.push_back(make_pair(seeker, tick));
// First, check if it's a flooder
for(FloodIter fi = flooders.begin(); fi != flooders.end(); ++fi) {
if(fi->first == seeker) {
return;
}
}
int count = 0;
for(FloodIter fi = seekers.begin(); fi != seekers.end(); ++fi) {
if(fi->first == seeker)
count++;
if(count > 7) {
if(seeker.compare(0, 4, "Hub:") == 0)
fire(ClientListener::SearchFlood(), this, seeker.substr(4));
else
fire(ClientListener::SearchFlood(), this, seeker + STRING(NICK_UNKNOWN));
flooders.push_back(make_pair(seeker, tick));
return;
}
}
}
int a;
if(param[i] == 'F') {
a = SearchManager::SIZE_DONTCARE;
} else if(param[i+2] == 'F') {
a = SearchManager::SIZE_ATLEAST;
} else {
a = SearchManager::SIZE_ATMOST;
}
i += 4;
j = param.find('?', i);
if(j == string::npos || i == j)
return;
string size = param.substr(i, j-i);
i = j + 1;
j = param.find('?', i);
if(j == string::npos || i == j)
return;
int type = Util::toInt(param.substr(i, j-i)) - 1;
i = j + 1;
param = param.substr(i);
if(param.size() > 0) {
if(seeker.compare(0, 4, "Hub:") == 0) {
OnlineUser* u = findUser(seeker.substr(4));
if(u == NULL) {
return;
}
if(!u->getUser()->isSet(User::PASSIVE)) {
u->getUser()->setFlag(User::PASSIVE);
updated(*u);
}
}
fire(ClientListener::NmdcSearch(), this, seeker, a, Util::toInt64(size), type, param);
}
} else if(cmd == "$MyINFO") {
string::size_type i, j;
i = 5;
j = param.find(' ', i);
if( (j == string::npos) || (j == i) )
return;
string nick = param.substr(i, j-i);
if(nick.empty())
return;
i = j + 1;
OnlineUser& u = getUser(nick);
j = param.find('$', i);
if(j == string::npos)
return;
string tmpDesc = Util::validateMessage(param.substr(i, j-i), true);
// Look for a tag...
if(tmpDesc.size() > 0 && tmpDesc[tmpDesc.size()-1] == '>') {
x = tmpDesc.rfind('<');
if(x != string::npos) {
// Hm, we have something...disassemble it...
updateFromTag(u.getIdentity(), tmpDesc.substr(x + 1, tmpDesc.length() - x - 2));
tmpDesc.erase(x);
}
}
u.getIdentity().setDescription(tmpDesc);
i = j + 3;
j = param.find('$', i);
if(j == string::npos)
return;
string connection = param.substr(i, j-i-1);
if(connection.empty()) {
// No connection = bot...
u.getUser()->setFlag(User::BOT);
} else {
u.getUser()->unsetFlag(User::BOT);
}
u.getIdentity().setConnection(connection);
i = j + 1;
j = param.find('$', i);
if(j == string::npos)
return;
u.getIdentity().setEmail(Util::validateMessage(param.substr(i, j-i), true));
i = j + 1;
j = param.find('$', i);
if(j == string::npos)
return;
u.getIdentity().setBytesShared(param.substr(i, j-i));
if(u.getUser() == getMyIdentity().getUser())
setMyIdentity(u.getIdentity());
fire(ClientListener::UserUpdated(), this, u);
} else if(cmd == "$Quit") {
if(!param.empty()) {
string nick = param;
OnlineUser* u = findUser(nick);
if(u == NULL)
return;
fire(ClientListener::UserRemoved(), this, *u);
putUser(nick);
}
} else if(cmd == "$ConnectToMe") {
if(state != STATE_CONNECTED) {
return;
}
string::size_type i = param.find(' ');
string::size_type j;
if( (i == string::npos) || ((i + 1) >= param.size()) ) {
return;
}
i++;
j = param.find(':', i);
if(j == string::npos) {
return;
}
string server = param.substr(i, j-i);
if(j+1 >= param.size()) {
return;
}
string port = param.substr(j+1);
ConnectionManager::getInstance()->nmdcConnect(server, (short)Util::toInt(port), getMyNick(), getHubUrl());
} else if(cmd == "$RevConnectToMe") {
if(state != STATE_CONNECTED) {
return;
}
string::size_type j = param.find(' ');
if(j == string::npos) {
return;
}
OnlineUser* u = findUser(param.substr(0, j));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -