adchub.cpp

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

CPP
556
字号
/*
 * 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 "AdcHub.h"
#include "ClientManager.h"
#include "ShareManager.h"
#include "StringTokenizer.h"
#include "AdcCommand.h"
#include "ConnectionManager.h"
#include "version.h"
#include "Util.h"
#include "UserCommand.h"
#include "FavoriteManager.h"
#include "SSLSocket.h"

const string AdcHub::CLIENT_PROTOCOL("ADC/0.10");
const string AdcHub::SECURE_CLIENT_PROTOCOL("ADCS/0.10");
const string AdcHub::ADCS_FEATURE("ADC0");
const string AdcHub::TCP4_FEATURE("TCP4");
const string AdcHub::UDP4_FEATURE("UDP4");

AdcHub::AdcHub(const string& aHubURL, bool secure) : Client(aHubURL, '\n', secure), state(STATE_PROTOCOL), sid(0), reconnect(true) {
	TimerManager::getInstance()->addListener(this);
}

AdcHub::~AdcHub() throw() {
	TimerManager::getInstance()->removeListener(this);
	clearUsers();
}

OnlineUser& AdcHub::getUser(const u_int32_t aSID, const CID& aCID) {
	OnlineUser* u = findUser(aSID);
	if(u) {
		return *u;
	}

	User::Ptr p = ClientManager::getInstance()->getUser(aCID);

	{
		Lock l(cs);
		u = users.insert(make_pair(aSID, new OnlineUser(p, *this, aSID))).first->second;
	}

	if(!aCID.isZero())
		ClientManager::getInstance()->putOnline(*u);
	return *u;
}

OnlineUser* AdcHub::findUser(const u_int32_t aSID) const {
	Lock l(cs);
	SIDMap::const_iterator i = users.find(aSID);
	return i == users.end() ? NULL : i->second;
}

void AdcHub::putUser(const u_int32_t aSID) {
	Lock l(cs);
	SIDIter i = users.find(aSID);
	if(i == users.end())
		return;
	if(aSID != AdcCommand::HUB_SID)
		ClientManager::getInstance()->putOffline(*i->second);
	fire(ClientListener::UserRemoved(), this, *i->second);
	delete i->second;
	users.erase(i);
}

void AdcHub::clearUsers() {
	Lock l(cs);
	for(SIDIter i = users.begin(); i != users.end(); ++i) {
		if(i->first != AdcCommand::HUB_SID)
			ClientManager::getInstance()->putOffline(*i->second);
		delete i->second;
	}
	users.clear();
}


void AdcHub::handle(AdcCommand::INF, AdcCommand& c) throw() {
	if(c.getParameters().empty())
		return;

	string cid;
	
	OnlineUser* u = 0;
	if(c.getParam("ID", 0, cid))
		u = &getUser(c.getFrom(), CID(cid));
	else if(c.getFrom() == AdcCommand::HUB_SID)
		u = &getUser(c.getFrom(), CID());
	else
		u = findUser(c.getFrom());

	if(!u) {
		dcdebug("AdcHub::INF Unknown user / no ID\n");
		return;
	}

	for(StringIterC i = c.getParameters().begin(); i != c.getParameters().end(); ++i) {
		if(i->length() < 2)
			continue;
			
		u->getIdentity().set(i->c_str(), i->substr(2));
	}

	if(u->getIdentity().isBot()) {
		u->getUser()->setFlag(User::BOT);
	} else {
		u->getUser()->unsetFlag(User::BOT);
	}

	if(u->getUser()->getFirstNick().empty()) {
		u->getUser()->setFirstNick(u->getIdentity().getNick());
	}

	if(u->getIdentity().supports(ADCS_FEATURE)) {
		u->getUser()->setFlag(User::SSL);
	}

	if(u->getIdentity().isHub()) {
		setHubIdentity(u->getIdentity());
		fire(ClientListener::HubUpdated(), this);
	}

	if(u->getUser() == ClientManager::getInstance()->getMe()) {
		state = STATE_NORMAL;
		setMyIdentity(u->getIdentity());
		updateCounts(false);
	}
	fire(ClientListener::UserUpdated(), this, *u);
}

void AdcHub::handle(AdcCommand::SUP, AdcCommand& c) throw() {
	if(state != STATE_PROTOCOL) /** @todo SUP changes */
		return;
	if(find(c.getParameters().begin(), c.getParameters().end(), "ADBASE") == c.getParameters().end()
		&& find(c.getParameters().begin(), c.getParameters().end(), "ADBAS0") == c.getParameters().end())
	{
		fire(ClientListener::StatusMessage(), this, "Failed to negotiate base protocol"); // @todo internationalize
		socket->disconnect(false);
		return;
	}
}

void AdcHub::handle(AdcCommand::SID, AdcCommand& c) throw() {
	if(state != STATE_PROTOCOL) {
		dcdebug("Invalid state for SID\n");
		return;
	}

	if(c.getParameters().empty())
		return;

	sid = AdcCommand::toSID(c.getParam(0));

	state = STATE_IDENTIFY;
	info(true);
}

void AdcHub::handle(AdcCommand::MSG, AdcCommand& c) throw() {
	if(c.getParameters().empty())
		return;

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

	string pmFrom;
	if(c.getParam("PM", 1, pmFrom)) { // add PM<group-cid> as well
		OnlineUser* to = findUser(c.getTo());
		if(!to)
			return;

		OnlineUser* replyTo = findUser(AdcCommand::toSID(pmFrom));
		if(!replyTo)
			return;

		fire(ClientListener::PrivateMessage(), this, *from, *to, *replyTo, c.getParam(0));
	} else {
		fire(ClientListener::Message(), this, *from, c.getParam(0));
	}		
}

void AdcHub::handle(AdcCommand::GPA, AdcCommand& c) throw() {
	if(c.getParameters().empty())
		return;
	salt = c.getParam(0);
	state = STATE_VERIFY;

	fire(ClientListener::GetPassword(), this);
}

void AdcHub::handle(AdcCommand::QUI, AdcCommand& c) throw() {
	putUser(AdcCommand::toSID(c.getParam(0)));
}

void AdcHub::handle(AdcCommand::CTM, AdcCommand& c) throw() {
	OnlineUser* u = findUser(c.getFrom());
	if(!u || u->getUser() == ClientManager::getInstance()->getMe())
		return;
	if(c.getParameters().size() < 3)
		return;

	bool secure;
	if(c.getParam(0) == CLIENT_PROTOCOL) {
		secure = false;
	} else if(c.getParam(0) == SECURE_CLIENT_PROTOCOL) {
		secure = true;
	} else {
		send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_UNSUPPORTED, "Protocol unknown", AdcCommand::TYPE_DIRECT).setTo(c.getFrom()));
		return;
	}

	if(!u->getIdentity().isTcpActive()) {
		send(AdcCommand(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_GENERIC, "IP unknown", AdcCommand::TYPE_DIRECT).setTo(c.getFrom()));
		return;
	}

	string token;
	c.getParam("TO", 2, token);
	ConnectionManager::getInstance()->adcConnect(*u, (short)Util::toInt(c.getParameters()[1]), token, secure);
}

void AdcHub::handle(AdcCommand::RCM, AdcCommand& c) throw() {
	if(!ClientManager::getInstance()->isActive())
		return;
	OnlineUser* u = findUser(c.getFrom());
	if(!u || u->getUser() == ClientManager::getInstance()->getMe())
		return;
	if(c.getParameters().empty() || (c.getParameters()[0] != CLIENT_PROTOCOL && c.getParameters()[0] != SECURE_CLIENT_PROTOCOL))
		return;
	string token;
	c.getParam("TO", 1, token);
    connect(*u, token, c.getParameters()[0] == SECURE_CLIENT_PROTOCOL);
}

void AdcHub::handle(AdcCommand::CMD, AdcCommand& c) throw() {
	if(c.getParameters().size() < 1)
		return;
	const string& name = c.getParam(0);
	bool rem = c.hasFlag("RM", 1);
	if(rem) {
		int cmd = FavoriteManager::getInstance()->findUserCommand(name);
		if(cmd != -1)
			FavoriteManager::getInstance()->removeUserCommand(cmd);
	}
	bool sep = c.hasFlag("SP", 1);
	string sctx;
	if(!c.getParam("CT", 1, sctx))
		return;
	int ctx = Util::toInt(sctx);
	if(ctx <= 0)
		return;
	if(sep) {
		FavoriteManager::getInstance()->addUserCommand(UserCommand::TYPE_SEPARATOR, ctx, UserCommand::FLAG_NOSAVE, name, "", getHubUrl());
		return;
	}
	bool once = c.hasFlag("CO", 1);
	string txt;
	if(!c.getParam("TT", 1, txt))
		return;
	FavoriteManager::getInstance()->addUserCommand(once ? UserCommand::TYPE_RAW_ONCE : UserCommand::TYPE_RAW, ctx, UserCommand::FLAG_NOSAVE, name, txt, getHubUrl());

⌨️ 快捷键说明

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