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

📄 service.c

📁 AnyQ服务端源代码(2004/10/28)源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Group 1.  This is a very special group.  All connections support * this group, as it does some particularly good things (like rate limiting). */#define FAIM_INTERNAL#define FAIM_NEED_CONN_INTERNAL#include <aim.h>#include "md5.h"/* Client Online (group 1, subtype 2) */faim_export int aim_clientready(aim_session_t *sess, aim_conn_t *conn){	aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;	struct snacgroup *sg;	aim_frame_t *fr;	aim_snacid_t snacid;	if (!ins)		return -EINVAL;	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))		return -ENOMEM;	snacid = aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0);	aim_putsnac(&fr->data, 0x0001, 0x0002, 0x0000, snacid);	/*	 * Send only the tool versions that the server cares about (that it	 * marked as supporting in the server ready SNAC).  	 */	for (sg = ins->groups; sg; sg = sg->next) {		aim_module_t *mod;		if ((mod = aim__findmodulebygroup(sess, sg->group))) {			aimbs_put16(&fr->data, mod->family);			aimbs_put16(&fr->data, mod->version);			aimbs_put16(&fr->data, mod->toolid);			aimbs_put16(&fr->data, mod->toolversion);		} else			faimdprintf(sess, 1, "aim_clientready: server supports group 0x%04x but we don't!\n", sg->group);	}	aim_tx_enqueue(sess, fr);	return 0;}/* * Host Online (group 1, type 3) *  * See comments in conn.c about how the group associations are supposed * to work, and how they really work. * * This info probably doesn't even need to make it to the client. * * We don't actually call the client here.  This starts off the connection * initialization routine required by all AIM connections.  The next time * the client is called is the CONNINITDONE callback, which should be  * shortly after the rate information is acknowledged. *  */static int hostonline(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	fu16_t *families;	int famcount;	if (!(families = malloc(aim_bstream_empty(bs))))		return 0;	for (famcount = 0; aim_bstream_empty(bs); famcount++) {		families[famcount] = aimbs_get16(bs);		aim_conn_addgroup(rx->conn, families[famcount]);	}	free(families);	/*	 * Next step is in the Host Versions handler.	 *	 * Note that we must send this before we request rates, since	 * the format of the rate information depends on the versions we	 * give it.	 *	 */	aim_setversions(sess, rx->conn);	return 1; }/* Service request (group 1, type 4) */faim_export int aim_reqservice(aim_session_t *sess, aim_conn_t *conn, fu16_t serviceid){	return aim_genericreq_s(sess, conn, 0x0001, 0x0004, &serviceid);}/* Redirect (group 1, type 5) */static int redirect(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	struct aim_redirect_data redir;	aim_rxcallback_t userfunc;	aim_tlvlist_t *tlvlist;	aim_snac_t *origsnac = NULL;	int ret = 0;	memset(&redir, 0, sizeof(redir));	tlvlist = aim_readtlvchain(bs);	if (!aim_gettlv(tlvlist, 0x000d, 1) ||			!aim_gettlv(tlvlist, 0x0005, 1) ||			!aim_gettlv(tlvlist, 0x0006, 1)) {		aim_freetlvchain(&tlvlist);		return 0;	}	redir.group = aim_gettlv16(tlvlist, 0x000d, 1);	redir.ip = aim_gettlv_str(tlvlist, 0x0005, 1);	redir.cookie = aim_gettlv_str(tlvlist, 0x0006, 1);	/* Fetch original SNAC so we can get csi if needed */	origsnac = aim_remsnac(sess, snac->id);	if ((redir.group == AIM_CONN_TYPE_CHAT) && origsnac) {		struct chatsnacinfo *csi = (struct chatsnacinfo *)origsnac->data;		redir.chat.exchange = csi->exchange;		redir.chat.room = csi->name;		redir.chat.instance = csi->instance;	}	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))		ret = userfunc(sess, rx, &redir);	free((void *)redir.ip);	free((void *)redir.cookie);	if (origsnac)		free(origsnac->data);	free(origsnac);	aim_freetlvchain(&tlvlist);	return ret;}/* Request Rate Information. (group 1, type 6) */faim_internal int aim_reqrates(aim_session_t *sess, aim_conn_t *conn){	return aim_genericreq_n(sess, conn, 0x0001, 0x0006);}/* * OSCAR defines several 'rate classes'.  Each class has seperate * rate limiting properties (limit level, alert level, disconnect * level, etc), and a set of SNAC family/type pairs associated with * it.  The rate classes, their limiting properties, and the definitions * of which SNACs are belong to which class, are defined in the * Rate Response packet at login to each host.   * * Logically, all rate offenses within one class count against further * offenses for other SNACs in the same class (ie, sending messages * too fast will limit the number of user info requests you can send, * since those two SNACs are in the same rate class). * * Since the rate classes are defined dynamically at login, the values * below may change. But they seem to be fairly constant. * * Currently, BOS defines five rate classes, with the commonly used * members as follows... * *  Rate class 0x0001: *  	- Everything thats not in any of the other classes * *  Rate class 0x0002: * 	- Buddy list add/remove *	- Permit list add/remove *	- Deny list add/remove * *  Rate class 0x0003: *	- User information requests *	- Outgoing ICBMs * *  Rate class 0x0004: *	- A few unknowns: 2/9, 2/b, and f/2 * *  Rate class 0x0005: *	- Chat room create *	- Outgoing chat ICBMs * * The only other thing of note is that class 5 (chat) has slightly looser * limiting properties than class 3 (normal messages).  But thats just a  * small bit of trivia for you. * * The last thing that needs to be learned about the rate limiting * system is how the actual numbers relate to the passing of time.  This * seems to be a big mystery. *  */static void rc_addclass(struct rateclass **head, struct rateclass *inrc){	struct rateclass *rc, *rc2;	if (!(rc = malloc(sizeof(struct rateclass))))		return;	memcpy(rc, inrc, sizeof(struct rateclass));	rc->next = NULL;	for (rc2 = *head; rc2 && rc2->next; rc2 = rc2->next)		;	if (!rc2)		*head = rc;	else		rc2->next = rc;	return;}static struct rateclass *rc_findclass(struct rateclass **head, fu16_t id){	struct rateclass *rc;	for (rc = *head; rc; rc = rc->next) {		if (rc->classid == id)			return rc;	}	return NULL;}static void rc_addpair(struct rateclass *rc, fu16_t group, fu16_t type){	struct snacpair *sp, *sp2;	if (!(sp = malloc(sizeof(struct snacpair))))		return;	memset(sp, 0, sizeof(struct snacpair));	sp->group = group;	sp->subtype = type;	sp->next = NULL;	for (sp2 = rc->members; sp2 && sp2->next; sp2 = sp2->next)		;	if (!sp2)		rc->members = sp;	else		sp2->next = sp;	return;}/* Rate Parameters (group 1, type 7) */static int rateresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	aim_conn_inside_t *ins = (aim_conn_inside_t *)rx->conn->inside;	fu16_t numclasses, i;	aim_rxcallback_t userfunc;	/*	 * First are the parameters for each rate class.	 */	numclasses = aimbs_get16(bs);	for (i = 0; i < numclasses; i++) {		struct rateclass rc;		memset(&rc, 0, sizeof(struct rateclass));		rc.classid = aimbs_get16(bs);		rc.windowsize = aimbs_get32(bs);		rc.clear = aimbs_get32(bs);		rc.alert = aimbs_get32(bs);		rc.limit = aimbs_get32(bs);		rc.disconnect = aimbs_get32(bs);		rc.current = aimbs_get32(bs);		rc.max = aimbs_get32(bs);		/*		 * The server will send an extra five bytes of parameters		 * depending on the version we advertised in 1/17.  If we		 * didn't send 1/17 (evil!), then this will crash and you		 * die, as it will default to the old version but we have 		 * the new version hardcoded here. 		 */		if (mod->version >= 3)			aimbs_getrawbuf(bs, rc.unknown, sizeof(rc.unknown));		faimdprintf(sess, 1, "--- Adding rate class %d to connection type %d: window size = %ld, clear = %ld, alert = %ld, limit = %ld, disconnect = %ld, current = %ld, max = %ld\n", rx->conn->type, rc.classid, rc.windowsize, rc.clear, rc.alert, rc.limit, rc.disconnect, rc.current, rc.max);		rc_addclass(&ins->rates, &rc);	}	/*	 * Then the members of each class.	 */	for (i = 0; i < numclasses; i++) {		fu16_t classid, count;		struct rateclass *rc;		int j;		classid = aimbs_get16(bs);		count = aimbs_get16(bs);		rc = rc_findclass(&ins->rates, classid);		for (j = 0; j < count; j++) {			fu16_t group, subtype;			group = aimbs_get16(bs);			subtype = aimbs_get16(bs);			if (rc)				rc_addpair(rc, group, subtype);		}	}	/*	 * We don't pass the rate information up to the client, as it really	 * doesn't care.  The information is stored in the connection, however	 * so that we can do more fun stuff later (not really).	 */	/*	 * Last step in the conn init procedure is to acknowledge that we	 * agree to these draconian limitations.	 */	aim_rates_addparam(sess, rx->conn);	/*	 * Finally, tell the client it's ready to go...	 */	if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE)))		userfunc(sess, rx);	return 1;}/* Add Rate Parameter (group 1, type 8) */faim_internal int aim_rates_addparam(aim_session_t *sess, aim_conn_t *conn){	aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;	aim_frame_t *fr;		aim_snacid_t snacid;	struct rateclass *rc;	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512)))		return -ENOMEM; 	snacid = aim_cachesnac(sess, 0x0001, 0x0008, 0x0000, NULL, 0);	aim_putsnac(&fr->data, 0x0001, 0x0008, 0x0000, snacid);	for (rc = ins->rates; rc; rc = rc->next)		aimbs_put16(&fr->data, rc->classid);	aim_tx_enqueue(sess, fr);	return 0;}/* Delete Rate Parameter (group 1, type 9) */faim_internal int aim_rates_delparam(aim_session_t *sess, aim_conn_t *conn){	aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;	aim_frame_t *fr;		aim_snacid_t snacid;	struct rateclass *rc;	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512)))		return -ENOMEM; 	snacid = aim_cachesnac(sess, 0x0001, 0x0009, 0x0000, NULL, 0);	aim_putsnac(&fr->data, 0x0001, 0x0009, 0x0000, snacid);	for (rc = ins->rates; rc; rc = rc->next)		aimbs_put16(&fr->data, rc->classid);	aim_tx_enqueue(sess, fr);	return 0;}/* Rate Change (group 1, type 0x0a) */static int ratechange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	aim_rxcallback_t userfunc;	fu16_t code, rateclass;	fu32_t currentavg, maxavg, windowsize, clear, alert, limit, disconnect;	code = aimbs_get16(bs);	rateclass = aimbs_get16(bs);		windowsize = aimbs_get32(bs);	clear = aimbs_get32(bs);	alert = aimbs_get32(bs);	limit = aimbs_get32(bs);	disconnect = aimbs_get32(bs);	currentavg = aimbs_get32(bs);	maxavg = aimbs_get32(bs);	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))		return userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);	return 0;}/* * How Migrations work.   * * The server sends a Server Pause message, which the client should respond to  * with a Server Pause Ack, which contains the families it needs on this  * connection. The server will send a Migration Notice with an IP address, and  * then disconnect. Next the client should open the connection and send the  * cookie.  Repeat the normal login process and pretend this never happened. * * The Server Pause contains no data. * *//* Service Pause (group 1, type 0x0b) */static int serverpause(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	aim_rxcallback_t userfunc;	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))		return userfunc(sess, rx);	return 0;}/* * Service Pause Acknowledgement (group 1, type 0x0c) * * It is rather important that aim_sendpauseack() gets called for the exact * same connection that the Server Pause callback was called for, since * libfaim extracts the data for the SNAC from the connection structure. * * Of course, if you don't do that, more bad things happen than just what * libfaim can cause. * */faim_export int aim_sendpauseack(aim_session_t *sess, aim_conn_t *conn){	aim_frame_t *fr;	aim_snacid_t snacid;	aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;	struct snacgroup *sg;	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1024)))		return -ENOMEM;	snacid = aim_cachesnac(sess, 0x0001, 0x000c, 0x0000, NULL, 0);	aim_putsnac(&fr->data, 0x0001, 0x000c, 0x0000, snacid);	/*	 * This list should have all the groups that the original 	 * Host Online / Server Ready said this host supports.  And 	 * we want them all back after the migration.	 */	for (sg = ins->groups; sg; sg = sg->next)		aimbs_put16(&fr->data, sg->group);	aim_tx_enqueue(sess, fr);	return 0;}/* Service Resume (group 1, type 0x0d) */static int serverresume(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	aim_rxcallback_t userfunc;	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))		return userfunc(sess, rx);	return 0;}/* Request self-info (group 1, type 0x0e) */

⌨️ 快捷键说明

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