adchub.cpp

来自「一个不错的关于手机模块程序This page contains everythi」· C++ 代码 · 共 556 行 · 第 1/2 页

CPP
556
字号
}

void AdcHub::sendUDP(const AdcCommand& cmd) {
	try {
		Socket s;
		s.create(Socket::TYPE_UDP);

		Lock l(cs);
		SIDMap::const_iterator i = users.find(cmd.getTo());
		if(i == users.end()) {
			dcdebug("AdcHub::sendUDP: invalid user\n");
			return;
		}
		OnlineUser& u = *i->second;
		string tmp = cmd.toString(u.getUser()->getCID());
		if(u.getIdentity().isUdpActive()) {
			try {
				s.writeTo(u.getIdentity().getIp(), (short)Util::toInt(u.getIdentity().getUdpPort()), tmp);
			} catch(const SocketException& e) {
				dcdebug("AdcHub::sendUDP: write failed: %s\n", e.getError().c_str());
			}
		}
	} catch(SocketException&) {
		dcdebug("Can't create UDP socket\n");
	}
}

void AdcHub::handle(AdcCommand::STA, AdcCommand& c) throw() {
	if(c.getParameters().size() < 2)
		return;

	OnlineUser* u = findUser(c.getFrom());
	if(!u)
		return;

	// @todo Check for invalid protocol and unset SSL if necessary
	fire(ClientListener::Message(), this, *u, c.getParam(1));
}

void AdcHub::handle(AdcCommand::SCH, AdcCommand& c) throw() {
	OnlineUser* ou = findUser(c.getFrom());
	if(!ou) {
		dcdebug("Invalid user in AdcHub::onSCH\n");
		return;
	}

	fire(ClientListener::AdcSearch(), this, c, ou->getUser()->getCID());
}

void AdcHub::handle(AdcCommand::RES, AdcCommand& c) throw() {
	OnlineUser* ou = findUser(c.getFrom());
	if(!ou) {
		dcdebug("Invalid user in AdcHub::onRES\n");
		return;
	}
	SearchManager::getInstance()->onRES(c, ou->getUser());
}

void AdcHub::connect(const OnlineUser& user) {
	u_int32_t r = Util::rand();
	connect(user, Util::toString(r), BOOLSETTING(USE_SSL) && user.getUser()->isSet(User::SSL));
}

void AdcHub::connect(const OnlineUser& user, string const& token, bool secure) {
	if(state != STATE_NORMAL)
		return;

	const string& proto = secure ? SECURE_CLIENT_PROTOCOL : CLIENT_PROTOCOL;
	short port = secure ? ConnectionManager::getInstance()->getSecurePort() : ConnectionManager::getInstance()->getPort();

	if(ClientManager::getInstance()->isActive()) {
		send(AdcCommand(AdcCommand::CMD_CTM, user.getIdentity().getSID()).addParam(proto).addParam(Util::toString(port)).addParam(token));
	} else {
		send(AdcCommand(AdcCommand::CMD_RCM, user.getIdentity().getSID()).addParam(proto));
	}
}

void AdcHub::disconnect(bool graceless) {
	Client::disconnect(graceless);
	state = STATE_PROTOCOL;
	clearUsers();
}

void AdcHub::hubMessage(const string& aMessage) {
	if(state != STATE_NORMAL)
		return;
	send(AdcCommand(AdcCommand::CMD_MSG, AdcCommand::TYPE_BROADCAST).addParam(aMessage)); 
}

void AdcHub::privateMessage(const OnlineUser& user, const string& aMessage) { 
	if(state != STATE_NORMAL)
		return;
	send(AdcCommand(AdcCommand::CMD_MSG, user.getIdentity().getSID()).addParam(aMessage).addParam("PM", getMySID())); 
}

void AdcHub::search(int aSizeMode, int64_t aSize, int aFileType, const string& aString, const string& aToken) { 
	if(state != STATE_NORMAL)
		return;

	AdcCommand c(AdcCommand::CMD_SCH, AdcCommand::TYPE_BROADCAST);

	if(aFileType == SearchManager::TYPE_TTH) {
		c.addParam("TR", aString);
	} else {
		if(aSizeMode == SearchManager::SIZE_ATLEAST) {
			c.addParam("GE", Util::toString(aSize));
		} else if(aSizeMode == SearchManager::SIZE_ATMOST) {
			c.addParam("LE", Util::toString(aSize));
		}
		StringTokenizer<string> st(aString, ' ');
		for(StringIter i = st.getTokens().begin(); i != st.getTokens().end(); ++i) {
			c.addParam("AN", *i);
		}
		if(aFileType == SearchManager::TYPE_DIRECTORY) {
			c.addParam("TY", "2");
		}
	}

	if(!aToken.empty())
		c.addParam("TO", aToken);

	if(ClientManager::getInstance()->isActive()) {
		send(c);
	} else {
		c.setType(AdcCommand::TYPE_FEATURE);
		c.setFeatures("+TCP4");
		send(c);
	}
}

void AdcHub::password(const string& pwd) { 
	if(state != STATE_VERIFY)
		return;
	if(!salt.empty()) {
		size_t saltBytes = salt.size() * 5 / 8;
		AutoArray<u_int8_t> buf(saltBytes);
		Encoder::fromBase32(salt.c_str(), buf, saltBytes);
		TigerHash th;
		CID cid = getMyIdentity().getUser()->getCID();
		th.update(cid.data(), CID::SIZE);
		th.update(pwd.data(), pwd.length());
		th.update(buf, saltBytes);
		send(AdcCommand(AdcCommand::CMD_PAS, AdcCommand::TYPE_HUB).addParam(Encoder::toBase32(th.finalize(), TigerHash::HASH_SIZE)));
		salt.clear();
	}
}

void AdcHub::info(bool /*alwaysSend*/) {
	if(state != STATE_IDENTIFY && state != STATE_NORMAL)
		return;

	reloadSettings(false);

	AdcCommand c(AdcCommand::CMD_INF, AdcCommand::TYPE_BROADCAST);
	string tmp;

	StringMapIter i;
#define ADDPARAM(var, content) \
	tmp = content; \
	if((i = lastInfoMap.find(var)) != lastInfoMap.end()) { \
		if(i->second != tmp) { \
			if(tmp.empty()) \
				lastInfoMap.erase(i); \
			else \
				i->second = tmp; \
			c.addParam(var, tmp); \
		} \
	} else if(!tmp.empty()) { \
		c.addParam(var, tmp); \
		lastInfoMap[var] = tmp; \
	}

	updateCounts(false); \

	ADDPARAM("ID", ClientManager::getInstance()->getMyCID().toBase32());
	ADDPARAM("PD", ClientManager::getInstance()->getMyPID().toBase32());
	ADDPARAM("NI", getMyIdentity().getNick());
	ADDPARAM("DE", getMyIdentity().getDescription());
	ADDPARAM("SL", Util::toString(SETTING(SLOTS)));
	ADDPARAM("SS", ShareManager::getInstance()->getShareSizeString());
	ADDPARAM("SF", Util::toString(ShareManager::getInstance()->getSharedFiles()));
	ADDPARAM("EM", SETTING(EMAIL));
	ADDPARAM("HN", Util::toString(counts.normal));
	ADDPARAM("HR", Util::toString(counts.registered));
	ADDPARAM("HO", Util::toString(counts.op));
	ADDPARAM("VE", "++ " VERSIONSTRING);

	string su;
	if(SSLSocketFactory::getInstance()->hasCerts()) {
		su += ADCS_FEATURE + ",";
	} 
	
	if(ClientManager::getInstance()->isActive()) {
		if(BOOLSETTING(NO_IP_OVERRIDE) && !SETTING(EXTERNAL_IP).empty()) {
			ADDPARAM("I4", Socket::resolve(SETTING(EXTERNAL_IP)));
		} else {
			ADDPARAM("I4", "0.0.0.0");
		}
		ADDPARAM("U4", Util::toString(SearchManager::getInstance()->getPort()));
		su += TCP4_FEATURE + ",";
		su += UDP4_FEATURE + ",";
	} else {
		ADDPARAM("I4", "");
		ADDPARAM("U4", "");
	}

	if(!su.empty()) {
		su.erase(su.size() - 1);
	}
	ADDPARAM("SU", su);

#undef ADDPARAM

	if(c.getParameters().size() > 0) {
		send(c);
	}
}

int64_t AdcHub::getAvailable() const {
	Lock l(cs);
	int64_t x = 0;
	for(SIDMap::const_iterator i = users.begin(); i != users.end(); ++i) {
		x+=i->second->getIdentity().getBytesShared();
	}
	return x;
}

string AdcHub::checkNick(const string& aNick) {
	string tmp = aNick;
	string::size_type i = 0;
	while( (i = tmp.find_first_of(" ", i)) != string::npos) {
		tmp[i++]='_';
	}
	return tmp;
}

void AdcHub::on(Connected) throw() { 
	dcassert(state == STATE_PROTOCOL);
	lastInfoMap.clear();
	reconnect = true;
	send(AdcCommand(AdcCommand::CMD_SUP, AdcCommand::TYPE_HUB).addParam("ADBAS0"));
	
	fire(ClientListener::Connected(), this);
}

void AdcHub::on(Line, const string& aLine) throw() { 
	if(BOOLSETTING(ADC_DEBUG)) {
		fire(ClientListener::StatusMessage(), this, "<ADC>" + aLine + "</ADC>");
	}
	dispatch(aLine); 
}

void AdcHub::on(Failed, const string& aLine) throw() { 
	clearUsers();
	state = STATE_PROTOCOL;
	fire(ClientListener::Failed(), this, aLine);
}

void AdcHub::on(TimerManagerListener::Second, u_int32_t aTick) throw() {
	if(socket && (getLastActivity() + getReconnDelay() * 1000) < aTick) {
		// Nothing's happened for ~120 seconds, check if we're connected, if not, try to connect...
		if(!isConnected()) {
			// Try to reconnect...
			if(reconnect && !getAddress().empty())
				Client::connect();
		}
	}
}

void AdcHub::send(const AdcCommand& cmd) {
	dcassert(socket);
	if(!socket)
		return;
	if(cmd.getType() == AdcCommand::TYPE_UDP)
		sendUDP(cmd);
	send(cmd.toString(sid));
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?