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

📄 service.c

📁 oscar message protocol stack
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Family 0x0001 - 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"/* Subtype 0x0002 - Client Online */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;}/* * Subtype 0x0003 - Host Online *  * 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; }/* Subtype 0x0004 - Service request */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);}/* * Join a room of name roomname.  This is the first step to joining an  * already created room.  It's basically a Service Request for  * family 0x000e, with a little added on to specify the exchange and room  * name. */faim_export int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance){	aim_frame_t *fr;	aim_snacid_t snacid;	aim_tlvlist_t *tl = NULL;	struct chatsnacinfo csi;		if (!sess || !conn || !roomname || !strlen(roomname))		return -EINVAL;	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512)))		return -ENOMEM;	memset(&csi, 0, sizeof(csi));	csi.exchange = exchange;	strncpy(csi.name, roomname, sizeof(csi.name));	csi.instance = instance;	snacid = aim_cachesnac(sess, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi));	aim_putsnac(&fr->data, 0x0001, 0x0004, 0x0000, snacid);	/*	 * Requesting service chat (0x000e)	 */	aimbs_put16(&fr->data, 0x000e);	aim_tlvlist_add_chatroom(&tl, 0x0001, exchange, roomname, instance);	aim_tlvlist_write(&fr->data, &tl);	aim_tlvlist_free(&tl);	aim_tx_enqueue(sess, fr);	return 0; }/* Subtype 0x0005 - Redirect */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_tlvlist_read(bs);	if (!aim_tlv_gettlv(tlvlist, 0x000d, 1) ||			!aim_tlv_gettlv(tlvlist, 0x0005, 1) ||			!aim_tlv_gettlv(tlvlist, 0x0006, 1)) {		aim_tlvlist_free(&tlvlist);		return 0;	}	redir.group = aim_tlv_get16(tlvlist, 0x000d, 1);	redir.ip = aim_tlv_getstr(tlvlist, 0x0005, 1);	redir.cookielen = aim_tlv_gettlv(tlvlist, 0x0006, 1)->length;	redir.cookie = aim_tlv_getstr(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_tlvlist_free(&tlvlist);	return ret;}/* Subtype 0x0006 - Request Rate Information. */faim_internal int aim_reqrates(aim_session_t *sess, aim_conn_t *conn){	return aim_genericreq_n_snacid(sess, conn, 0x0001, 0x0006);}/* * OSCAR defines several 'rate classes'.  Each class has separate * 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;}/* Subtype 0x0007 - Rate Parameters */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);

⌨️ 快捷键说明

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