⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udpsession.cpp

📁 MyICQ的源码.MyICQ是一套公开源代码的即时通讯软件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
void UdpSession::onNewUIN(UdpInPacket &in)
{
	const char *pass = in.readString();

	int n = sprintf(sqlStmt, "INSERT INTO basic_tbl (passwd) VALUES(password('%s'))", pass);
	if (mysql_real_query(&mysql, sqlStmt, n) == 0) {
		uin = (uint32) mysql_insert_id(&mysql);
		n = sprintf(sqlStmt, "INSERT INTO ext_tbl (uin) VALUES(%lu)", uin);
		mysql_real_query(&mysql, sqlStmt, n);
	}

	UdpOutPacket *out = createPacket(UDP_NEW_UIN, in.getSeq());
	out->write32(uin);
	sendPacket(out);

	keepAliveList.add(&keepAliveItem);
	SessionHash::addDead(this);
	cout << uin << " has registered." << endl;
}

void UdpSession::onGetContactList(UdpInPacket &in)
{
	MYSQL_RES *res;
	MYSQL_ROW row;

	int n = sprintf(sqlStmt, "SELECT uin2 FROM friend_tbl WHERE uin1=%lu", uin);
	if (mysql_real_query(&mysql, sqlStmt, n) == 0 && (res = mysql_store_result(&mysql))) {
		uint16 num = 0;
		UdpOutPacket *out = createPacket(UDP_GET_CONTACTLIST, in.getSeq());
		char *old = out->skip(sizeof(num));

		while ((row = mysql_fetch_row(res))) {
			out->write32(atol(row[0]));
			num++;
		}
		mysql_free_result(res);

		old = out->setCursor(old);
		out->write16(num);
		out->setCursor(old);
		sendPacket(out);
	}
}

void UdpSession::onLogin(UdpInPacket &in)
{
	uint8 error = LOGIN_INVALID_UIN;
	UdpOutPacket *out;
	uint32 friendUIN;
	MYSQL_RES *res;
	MYSQL_ROW row;

	uin = in.getUIN();
	const char *pass = in.readString();
	status = in.read32();
	tcpVer = in.read16();
	realIP = in.read32();

	int n = sprintf(sqlStmt, "SELECT auth FROM basic_tbl WHERE uin=%lu AND passwd=password('%s')", uin, pass);
	if (mysql_real_query(&mysql, sqlStmt, n) == 0 && (res = mysql_store_result(&mysql))) {
		row = mysql_fetch_row(res);
		if (row) {
			auth = atoi(row[0]);
			error = LOGIN_SUCCESS;
		}
		mysql_free_result(res);
	}

	out = createPacket(UDP_LOGIN, in.getSeq());
	out->write8(error);
	sendPacket(out);

	keepAliveList.add(&keepAliveItem);

	if (error != LOGIN_SUCCESS) {
		cout << uin << " login failed." << endl;
		SessionHash::addDead(this);
		return;
	}

	strncpy(passwd, pass, 8);
	cout << uin << " successfully logged in." << endl;

	UdpSession *session = SessionHash::getAlive(uin);
	if (session) {
		cout << "previous session exists, delete it." << endl;
		delete session;
		session = NULL;
	}
	SessionHash::addAlive(this);

	// inform me of my friends' status.
	n = sprintf(sqlStmt, "SELECT uin2 FROM friend_tbl WHERE uin1=%lu", uin);
	if (mysql_real_query(&mysql, sqlStmt, n) == 0 && (res = mysql_store_result(&mysql))) {
		uint16 num = 0;
		out = createPacket(UDP_SRV_MULTI_ONLINE);
		char *old = out->skip(sizeof(num));

		while ((row = mysql_fetch_row(res))) {
			friendUIN = atol(row[0]);
			UdpSession *session = SessionHash::getAlive(friendUIN);
			if (session && session->status != STATUS_INVIS) {
				num++;
				out->write32(friendUIN);
				out->write32(session->status);
				out->write32(session->ip);
				out->write16(session->port);
				out->write32(session->realIP);
				cout << "friend " << friendUIN << " is online" << endl;
			}
		}
		if (num) {
			old = out->setCursor(old);
			out->write16(num);
			out->setCursor(old);
			sendPacket(out);
		} else {
			sendSeq--;
			delete out;
		}

		mysql_free_result(res);
	}

	// I am now online!
	if (status == STATUS_OFFLINE)
		status = STATUS_ONLINE;
	if (status != STATUS_INVIS)
		onlineNotify();

	// Broadcast messages
	n = sprintf(sqlStmt, "SELECT src, type, time, msg FROM broadmsg_tbl a, broadmsg_content_tbl b "
		"WHERE dst=%lu AND a.id=b.id", uin);
	sendMessages(sqlStmt, n);
	
	// Has someone sent me messages during offline?
	n = sprintf(sqlStmt, "SELECT src, type, time, msg FROM message_tbl WHERE dst=%lu", uin);
	sendMessages(sqlStmt, n);
}

void UdpSession::sendMessages(const char *sql, int n)
{
	MYSQL_RES *res;
	MYSQL_ROW row;

	if (mysql_real_query(&mysql, sql, n) == 0 && (res = mysql_store_result(&mysql))) {
		while ((row = mysql_fetch_row(res))) {
			uint32 friendUIN = atol(row[0]);
			uint8 type = atoi(row[1]);
			time_t sendTime = atol(row[2]);
			const char *text = row[3];

			UdpOutPacket *out = createPacket(UDP_SRV_MESSAGE);
			out->write8(type);
			out->write32(friendUIN);
			out->write32(sendTime);
			out->writeString(text);
			sendPacket(out);
		}
		mysql_free_result(res);
	}
}

void UdpSession::sendMessage(uint8 type, uint32 dst, uint32 src, UdpSession *dstSession, time_t when, const char *text)
{
	if (dstSession) {
		UdpOutPacket *out = dstSession->createPacket(UDP_SRV_MESSAGE);
		out->write8(type);
		out->write32(src);
		out->write32(when);
		out->writeString(text);
		dstSession->sendPacket(out);
	} else {
		int n = sprintf(sqlStmt, "INSERT INTO message_tbl values(%lu, %lu, %d, %lu, '%s')",
			dst, src, (int) type, when, text);
		mysql_real_query(&mysql, sqlStmt, n);
	}
}

void UdpSession::onUpdateContact(UdpInPacket &in)
{
	uint32 dst = in.read32();
	MYSQL_RES *res;
	MYSQL_ROW row;

	int n = sprintf(sqlStmt, "SELECT pic, nick, age, gender, country, province, city, email,"
		"address, zipcode, tel, name, blood, college, profession, homepage, intro "
		"FROM basic_tbl a, ext_tbl b WHERE a.uin=%lu AND a.uin=b.uin", dst);
	if (mysql_real_query(&mysql, sqlStmt, n) == 0 && (res = mysql_store_result(&mysql))) {
		row = mysql_fetch_row(res);
		if (row) {
			UdpOutPacket *out = createPacket(UDP_UPDATE_CONTACT, in.getSeq());
			out->write32(dst);

			out->write8(atoi(row[0]));
			out->writeString(row[1]);
			out->write8(atoi(row[2]));
			out->write8(atoi(row[3]));

			out->writeString(row[4]);
			out->writeString(row[5]);
			out->writeString(row[6]);

			out->writeString(row[7]);
			out->writeString(row[8]);
			out->writeString(row[9]);
			out->writeString(row[10]);

			out->writeString(row[11]);
			out->write8(atoi(row[12]));
			out->writeString(row[13]);
			out->writeString(row[14]);
			out->writeString(row[15]);
			out->writeString(row[16]);

			sendPacket(out);
		}
		mysql_free_result(res);
	}
}

void UdpSession::onUpdateUser(UdpInPacket &in)
{
	MYSQL_RES *res;
	MYSQL_ROW row;

	int n = sprintf(sqlStmt, "SELECT pic, nick, age, gender, country, province, city, email, "
		"address, zipcode, tel, name, blood, college, profession, homepage, intro "
		"FROM basic_tbl a, ext_tbl b WHERE a.uin=%lu AND a.uin=b.uin", uin);
	if (mysql_real_query(&mysql, sqlStmt, n) == 0 && (res = mysql_store_result(&mysql))) {
		row = mysql_fetch_row(res);
		if (row) {
			UdpOutPacket *out = createPacket(UDP_UPDATE_USER, in.getSeq());

			out->write8(atoi(row[0]));
			out->writeString(row[1]);
			out->write8(atoi(row[2]));
			out->write8(atoi(row[3]));
			out->writeString(row[4]);
			out->writeString(row[5]);
			out->writeString(row[6]);

			out->writeString(row[7]);
			out->writeString(row[8]);
			out->writeString(row[9]);
			out->writeString(row[10]);

			out->writeString(row[11]);
			out->write8(atoi(row[12]));
			out->writeString(row[13]);
			out->writeString(row[14]);
			out->writeString(row[15]);
			out->writeString(row[16]);

			out->write8(auth);

			sendPacket(out);
		}
		mysql_free_result(res);
	}
}

void UdpSession::onModifyUser(UdpInPacket &in)
{
	int pic = in.read8();
	const char *nick = in.readString();
	int age = in.read8();
	int gender = in.read8();
	const char *country = in.readString();
	const char *province = in.readString();
	const char *city = in.readString();
	const char *email = in.readString();
	const char *address = in.readString();
	const char *zipcode = in.readString();
	const char *tel = in.readString();
	const char *name = in.readString();
	int blood = in.read8();
	const char *college = in.readString();
	const char *profession = in.readString();
	const char *homepage = in.readString();
	const char *intro = in.readString();
	auth = in.read8();
	uint8 modifyPasswd = in.read8();

	char *p = sqlStmt;
	p += sprintf(p, "UPDATE basic_tbl SET ");
	if (modifyPasswd) {
		const char *pass = in.readString();
		if (*pass)
			p += sprintf(p, "passwd=password('%s'), ", pass);
	}
	p += sprintf(p, "nick='%s', pic=%d, gender=%d, age=%d, country='%s', province='%s', city='%s', email='%s', auth=%d "
		"WHERE uin=%lu", nick, pic, gender, age, country, province, city, email, auth, uin);
	int n = p - sqlStmt;
	mysql_real_query(&mysql, sqlStmt, n);

	n = sprintf(sqlStmt, "UPDATE ext_tbl SET "
		"address='%s', zipcode='%s', tel='%s', "
		"name='%s', blood=%d, college='%s', profession='%s', homepage='%s', intro='%s' WHERE uin=%lu",
		address, zipcode, tel, name, blood, college, profession, homepage, intro, uin);
	mysql_real_query(&mysql, sqlStmt, n);
}

void UdpSession::dead()
{
	if (status != STATUS_INVIS)
		offlineNotify();
	status = STATUS_OFFLINE;
}

void UdpSession::onLogout(UdpInPacket &in)
{
	cout << uin << " logged out." << endl;
	dead();

	if (sendQueue.isEmpty()) {
		// delete all offline messages
		int n = sprintf(sqlStmt, "DELETE FROM message_tbl WHERE dst=%lu", uin);
		mysql_real_query(&mysql, sqlStmt, n);

		n = sprintf(sqlStmt, "DELETE FROM broadmsg_tbl WHERE dst=%lu", uin);
		mysql_real_query(&mysql, sqlStmt, n);
	}
	delete this;
}

void UdpSession::onChangeStatus(UdpInPacket &in)
{
	uint32 oldStatus = status;
	status = in.read32();

	if (oldStatus == STATUS_INVIS && status != STATUS_INVIS)
		onlineNotify();
	else if (oldStatus != STATUS_INVIS && status == STATUS_INVIS)
		offlineNotify();
	else if (status != STATUS_INVIS) {
		MYSQL_RES *res;
		MYSQL_ROW row;

		int n = sprintf(sqlStmt, "SELECT uin1 FROM friend_tbl WHERE uin2=%lu", uin);
		if (mysql_real_query(&mysql, sqlStmt, n) == 0 && (res = mysql_store_result(&mysql))) {
			while ((row = mysql_fetch_row(res))) {
				uint32 friendUIN = atol(row[0]);
				UdpSession *session = SessionHash::getAlive(friendUIN);
				if (session) {
					UdpOutPacket *out = session->createPacket(UDP_SRV_STATUS_CHANGED);
					out->write32(uin);
					out->write32(status);
					session->sendPacket(out);
				}
			}
			mysql_free_result(res);
		}
	}
}

void UdpSession::onKeepAlive(UdpInPacket &in)
{
	cout << uin << " keeps alive" << endl;
	
	expire = time(NULL) + KEEPALIVE_TIMEOUT;
	keepAliveItem.remove();
	keepAliveList.add(&keepAliveItem);

	UdpOutPacket out(this);
	createPacket(out, UDP_KEEPALIVE, in.getSeq());
	out.write32(sessionCount);
	sendDirect(&out);
}

void UdpSession::onSendMessage(UdpInPacket &in)
{
	uint8 type = in.read8();
	uint32 to = in.read32();
	time_t when = in.read32();
	const char *text = in.readString();

	UdpSession *session = SessionHash::getAlive(to);
	sendMessage(type, to, uin, session, when, text);

	if (type == MSG_AUTH_ACCEPTED)
		addFriend(uin, to, this, session);
}

void UdpSession::onBroadcastMsg(UdpInPacket &in)
{
	if (uin >= START_UIN)
		return;
	
	uint8 type = in.read8();
	uint32 when = in.read32();
	time_t expire = in.read32();
	const char *text = in.readString();

	if (expire <= time(NULL) || !*text)
		return;

	int n = sprintf(sqlStmt, "INSERT INTO broadmsg_content_tbl "
		"VALUES(NULL, %lu, %d, %lu, %lu, '%s')", uin, type, when, expire, text);
	mysql_real_query(&mysql, sqlStmt, n);

	BROADCAST_MSG *msg = new BROADCAST_MSG;
	msg->id = (uint32) mysql_insert_id(&mysql);
	msg->type = type;
	msg->src = uin;
	msg->when = when;
	strncpy(msg->text, text, MAX_MSG_LEN);
	msg->expire = expire;
	msg->to = START_UIN;

	MYSQL_RES *res;
	MYSQL_ROW row;
	static const char sql[] = "SELECT MAX(uin) FROM basic_tbl";
	if (mysql_real_query(&mysql, sql, sizeof(sql) - 1) == 0 && (res = mysql_store_result(&mysql))) {
		row = mysql_fetch_row(res);
		if (row)
			msg->maxUIN = atoi(row[0]);
		mysql_free_result(res);
	}

	broadMsgList.add(&msg->listItem);
}

void UdpSession::onGroupSendMessage(UdpInPacket &in)
{
	uint8 type = in.read8();
	time_t when = in.read32();
	const char *text = in.readString();

	int n = in.read16();
	while (n-- > 0) {
		uint32 to = in.read32();
		UdpSession *session = SessionHash::getAlive(to);
		sendMessage(type, to, uin, session, when, text);
	}
}

void UdpSession::onSearchRandom(UdpInPacket &in)
{
	uint32 results[MAX_SEARCH_PER_PAGE];
	uint16 n = SessionHash::random(results, MAX_SEARCH_PER_PAGE);
	UdpOutPacket *out = createPacket(UDP_SRV_SEARCH, in.getSeq());
	out->write16(n);

	if (n > 0) {
		MYSQL_RES *res;
		MYSQL_ROW row;

		static const char sql[] = "SELECT uin, pic, nick, province FROM basic_tbl WHERE uin IN(";
		memcpy(sqlStmt, sql, sizeof(sql));
		char *p = sqlStmt + sizeof(sql) - 1;
		for (int i = 0; i < n; i++)
			p += sprintf(p, "%lu,", results[i]);
		*(p - 1) = ')';

		if (mysql_real_query(&mysql, sqlStmt, p - sqlStmt) == 0 &&
			(res = mysql_store_result(&mysql))) {
			while ((row = mysql_fetch_row(res))) {
				uint32 contactUIN = atoi(row[0]);
				uint8 pic = atoi(row[1]);
				const char *nick = row[2];
				const char *province = row[3];

				out->write32(contactUIN);
				out->write8(1);		// online
				out->write8(pic);
				out->writeString(nick);
				out->writeString(province);
			}
			mysql_free_result(res);
		}
	}

	sendPacket(out);
}

void UdpSession::onSearchCustom(UdpInPacket &in)
{
	uint32 uin = in.read32();
	const char *nick = in.readString();
	const char *email = in.readString();
	uint32 startUIN = in.read32();
	int n;

	if (uin != 0) {
		n = sprintf(sqlStmt, "SELECT uin, pic, nick, province FROM basic_tbl WHERE uin=%lu LIMIT %d",
			uin, MAX_SEARCH_PER_PAGE);
	} else if (*nick || *email) {
		char *p = sqlStmt;
		p += sprintf(p, "SELECT uin, pic, nick, province FROM basic_tbl WHERE uin>%lu AND ", startUIN);

		if (*nick)
			p += sprintf(p, "nick='%s'", nick);
		if (*email) {
			if (*nick)
				p += sprintf(p, " AND ");
			p += sprintf(p, "email='%s'", email);
		}
		p += sprintf(p, " LIMIT %d", MAX_SEARCH_PER_PAGE);
		n = p - sqlStmt;
	} else {
		cout << "unknown search mode" << endl;
		return;
	}

	MYSQL_RES *res;
	MYSQL_ROW row;
	UdpOutPacket *out;

	if (mysql_real_query(&mysql, sqlStmt, n) == 0 && (res = mysql_store_result(&mysql))) {

		uint16 num = 0;
		out = createPacket(UDP_SRV_SEARCH, in.getSeq());
		char *old = out->skip(sizeof(num));

		while ((row = mysql_fetch_row(res))) {
			uint32 contactUIN = atoi(row[0]);
			uint8 pic = atoi(row[1]);
			const char *nick = row[2];
			const char *province = row[3];

			out->write32(contactUIN);
			out->write8(SessionHash::getAlive(contactUIN) ? 1 : 0);
			out->write8(pic);
			out->writeString(nick);
			out->writeString(province);

			num++;
		}
		mysql_free_result(res);

		old = out->setCursor(old);
		out->write16(num);
		out->setCursor(old);
		sendPacket(out);
	}
}

void UdpSession::onAddFriend(UdpInPacket &in)
{
	uint32 dst = in.read32();
	uint8 dstAuth = 0;

	UdpSession *dstSession = SessionHash::getAlive(dst);
	if (dstSession)
		dstAuth = dstSession->auth;
	else {
		MYSQL_RES *res;
		MYSQL_ROW row;
		int n = sprintf(sqlStmt, "SELECT auth FROM basic_tbl WHERE uin=%lu", dst);
		if (mysql_real_query(&mysql, sqlStmt, n) == 0 && (res = mysql_store_result(&mysql))) {
			row = mysql_fetch_row(res);
			if (row)
				dstAuth = atoi(row[0]);
			mysql_free_result(res);
		}
	}

	UdpOutPacket *out = createPacket(UDP_ADD_FRIEND, in.getSeq());
	out->write32(dst);
	out->write8(dstAuth);
	sendPacket(out);

	if (dstAuth == ADD_FRIEND_ACCEPTED) {
		addFriend(dst, uin, dstSession, this);
		sendMessage(MSG_ADDED, dst, uin, dstSession, time(NULL), "");
	}
}

void UdpSession::onDelFriend(UdpInPacket &in)
{
	uint32 dst = in.read32();

	int n = sprintf(sqlStmt, "DELETE FROM friend_tbl WHERE uin1=%lu AND uin2=%lu", uin, dst);
	mysql_real_query(&mysql, sqlStmt, n);
}

⌨️ 快捷键说明

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