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

📄 im.c

📁 AnyQ服务端源代码(2004/10/28)源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* 	 * XXX: there are a couple of different request packets for	 *          different things 	 */	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))		ret = userfunc(sess, rx, 0x0002, userinfo, args);	return ret;}/* XXX Ugh.  I think its obvious. */static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, fu16_t channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, fu8_t *cookie){	aim_tlv_t *block1;	aim_tlvlist_t *list2;	int ret = 0;	struct aim_incomingim_ch2_args args;	aim_bstream_t bbs;	fu8_t *cookie2;	memset(&args, 0, sizeof(args));	/*	 * There's another block of TLVs embedded in the type 5 here. 	 */	if (!(block1 = aim_gettlv(tlvlist, 0x0005, 1)) || !block1->value) {		faimdprintf(sess, 0, "no tlv 0x0005 in rendezvous transaction!\n");		return 0;	}	aim_bstream_init(&bbs, block1->value, block1->length);	/*	 * First two bytes represent the status of the connection.	 *	 * 0 is a request, 2 is an accept	 */ 	args.status = aimbs_get16(&bbs);	/*	 * Next comes the cookie.  Should match the ICBM cookie.	 */	cookie2 = aimbs_getraw(&bbs, 8);	if (memcmp(cookie, cookie2, 8) != 0) 		faimdprintf(sess, 0, "rend: warning cookies don't match!\n");	memcpy(args.cookie, cookie2, 8);	free(cookie2);	/*	 * The next 16bytes are a capability block so we can	 * identify what type of rendezvous this is.	 *	 * Thanks to Eric Warmenhoven <warmenhoven@linux.com> (of GAIM)	 * for pointing some of this out to me.  In fact, a lot of 	 * the client-to-client info comes from the work of the GAIM 	 * developers. Thanks!	 *	 * Read off one capability string and we should have it ID'd.	 * 	 */	if ((args.reqclass = aim_getcap(sess, &bbs, 0x10)) == 0x0000) {		faimdprintf(sess, 0, "rend: no ID block\n");		return 0;	}	/* 	 * What follows may be TLVs or nothing, depending on the	 * purpose of the message.	 *	 * Ack packets for instance have nothing more to them.	 */	list2 = aim_readtlvchain(&bbs);#if 0 /* this should be in the per-type blocks */	if (!list2 || ((args.reqclass != AIM_CAPS_IMIMAGE) && !(aim_gettlv(list2, 0x2711, 1)))) {		aim_msgcookie_t *cook;		int type;		type = aim_msgcookie_gettype(args.reqclass); /* XXX: fix this shitty code */		if ((cook = aim_checkcookie(sess, cookie, type)) == NULL) {			faimdprintf(sess, 0, "non-data rendezvous thats not in cache (type %d)\n", type);			aim_freetlvchain(&list2);			return 1;		}		if (cook->type == AIM_COOKIETYPE_OFTGET) {			struct aim_filetransfer_priv *ft;			if (cook->data) {				int errorcode = -1; /* XXX shouldnt this be 0? */				ft = (struct aim_filetransfer_priv *)cook->data;				if (args.status != 0x0002) {					if (aim_gettlv(list2, 0x000b, 1))						errorcode = aim_gettlv16(list2, 0x000b, 1);					/* XXX this should make it up to the client, you know.. */					if (errorcode)						faimdprintf(sess, 0, "transfer from %s (%s) for %s cancelled (error code %d)\n", ft->sn, ft->ip, ft->fh.name, errorcode);				} /* args.status != 0x0002 */			} else {				faimdprintf(sess, 0, "no data attached to file transfer\n");			} /* !cook->data */		} else if (cook->type == AIM_CAPS_VOICE) {			faimdprintf(sess, 0, "voice request cancelled\n");				} else {					faimdprintf(sess, 0, "unknown cookie cache type %d\n", cook->type);		}		aim_freetlvchain(&list2);		return 1;	}#endif	/*	 * The rest of the handling depends on what type it is.	 */	if (args.reqclass & AIM_CAPS_BUDDYICON)		ret = incomingim_ch2_buddyicon(sess, mod, rx, snac, userinfo, &args, list2);	else if (args.reqclass & AIM_CAPS_SENDBUDDYLIST)		ret = incomingim_ch2_buddylist(sess, mod, rx, snac, userinfo, &args, list2);	else if (args.reqclass & AIM_CAPS_VOICE)		ret = incomingim_ch2_voice(sess, mod, rx, snac, userinfo, &args, list2);	else if (args.reqclass & AIM_CAPS_IMIMAGE)		ret = incomingim_ch2_imimage(sess, mod, rx, snac, userinfo, &args, list2);	else if (args.reqclass & AIM_CAPS_CHAT)		ret = incomingim_ch2_chat(sess, mod, rx, snac, userinfo, &args, list2);	else if (args.reqclass & AIM_CAPS_GETFILE)		ret = incomingim_ch2_getfile(sess, mod, rx, snac, userinfo, &args, list2);	else if (args.reqclass & AIM_CAPS_SENDFILE)		ret = incomingim_ch2_sendfile(sess, mod, rx, snac, userinfo, &args, list2);	else		faimdprintf(sess, 0, "rend: unknown rendezvous 0x%04x\n", args.reqclass);	aim_freetlvchain(&list2);	return ret;}/* * It can easily be said that parsing ICBMs is THE single * most difficult thing to do in the in AIM protocol.  In * fact, I think I just did say that. * * Below is the best damned solution I've come up with * over the past sixteen months of battling with it. This * can parse both away and normal messages from every client * I have access to.  Its not fast, its not clean.  But it works. * */static int incomingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	int i, ret = 0;	fu8_t cookie[8];	fu16_t channel;	aim_userinfo_t userinfo;	memset(&userinfo, 0x00, sizeof(aim_userinfo_t));	/*	 * Read ICBM Cookie.  And throw away.	 */	for (i = 0; i < 8; i++)		cookie[i] = aimbs_get8(bs);	/*	 * Channel ID.	 *	 * Channel 0x0001 is the message channel.  There are 	 * other channels for things called "rendevous"	 * which represent chat and some of the other new	 * features of AIM2/3/3.5. 	 *	 * Channel 0x0002 is the Rendevous channel, which	 * is where Chat Invitiations and various client-client	 * connection negotiations come from.	 * 	 */	channel = aimbs_get16(bs);	/*	 * Extract the standard user info block.	 *	 * Note that although this contains TLVs that appear contiguous	 * with the TLVs read below, they are two different pieces.  The	 * userinfo block contains the number of TLVs that contain user	 * information, the rest are not even though there is no seperation.	 * aim_extractuserinfo() returns the number of bytes used by the	 * userinfo tlvs, so you can start reading the rest of them right	 * afterward.  	 *	 * That also means that TLV types can be duplicated between the	 * userinfo block and the rest of the message, however there should	 * never be two TLVs of the same type in one block.	 * 	 */	aim_extractuserinfo(sess, bs, &userinfo);	/*	 * From here on, its depends on what channel we're on.	 *	 * Technically all channels have a TLV list have this, however,	 * for the common channel 1 case, in-place parsing is used for	 * performance reasons (less memory allocation).	 */	if (channel == 1) {		ret = incomingim_ch1(sess, mod, rx, snac, channel, &userinfo, bs, cookie);	} else if (channel == 0x0002) {		aim_tlvlist_t *tlvlist;		/*		 * Read block of TLVs (not including the userinfo data).  All 		 * further data is derived from what is parsed here.		 */		tlvlist = aim_readtlvchain(bs);		ret = incomingim_ch2(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie);		/*		 * Free up the TLV chain.		 */		aim_freetlvchain(&tlvlist);	} else {		faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel.  Ignoring.\n (chan = %04x)", channel);		return 0;	}	return ret;}/* * Possible codes: *    AIM_TRANSFER_DENY_NOTSUPPORTED -- "client does not support" *    AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer" *    AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers" *  */faim_export int aim_denytransfer(aim_session_t *sess, const char *sender, const char *cookie, fu16_t code){	aim_conn_t *conn;	aim_frame_t *fr;	aim_snacid_t snacid;	aim_tlvlist_t *tl = NULL;		if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))		return -EINVAL;	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sender)+6)))		return -ENOMEM;	snacid = aim_cachesnac(sess, 0x0004, 0x000b, 0x0000, NULL, 0);	aim_putsnac(&fr->data, 0x0004, 0x000b, 0x0000, snacid);		aimbs_putraw(&fr->data, cookie, 8);	aimbs_put16(&fr->data, 0x0002); /* channel */	aimbs_put8(&fr->data, strlen(sender));	aimbs_putraw(&fr->data, sender, strlen(sender));	aim_addtlvtochain16(&tl, 0x0003, code);	aim_writetlvchain(&fr->data, &tl);	aim_freetlvchain(&tl);	aim_tx_enqueue(sess, fr);	return 0;}/* * aim_reqicbmparaminfo() * * Request ICBM parameter information. * */faim_export int aim_reqicbmparams(aim_session_t *sess){	aim_conn_t *conn;	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))		return -EINVAL;	return aim_genericreq_n(sess, conn, 0x0004, 0x0004);}/* * * I definitly recommend sending this.  If you don't, you'll be stuck * with the rather unreasonable defaults.  You don't want those.  Send this. *  */faim_export int aim_seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params){	aim_conn_t *conn;	aim_frame_t *fr;	aim_snacid_t snacid;	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))		return -EINVAL;	if (!params)		return -EINVAL;	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+16)))		return -ENOMEM;	snacid = aim_cachesnac(sess, 0x0004, 0x0002, 0x0000, NULL, 0);	aim_putsnac(&fr->data, 0x0004, 0x0002, 0x0000, snacid);	/* This is read-only (see Parameter Reply). Must be set to zero here. */	aimbs_put16(&fr->data, 0x0000);	/* These are all read-write */	aimbs_put32(&fr->data, params->flags); 	aimbs_put16(&fr->data, params->maxmsglen);	aimbs_put16(&fr->data, params->maxsenderwarn); 	aimbs_put16(&fr->data, params->maxrecverwarn); 	aimbs_put32(&fr->data, params->minmsginterval);	aim_tx_enqueue(sess, fr);	return 0;}static int paraminfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	struct aim_icbmparameters params;	aim_rxcallback_t userfunc;	params.maxchan = aimbs_get16(bs);	params.flags = aimbs_get32(bs);	params.maxmsglen = aimbs_get16(bs);	params.maxsenderwarn = aimbs_get16(bs);	params.maxrecverwarn = aimbs_get16(bs);	params.minmsginterval = aimbs_get32(bs);		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))		return userfunc(sess, rx, &params);	return 0;}static int missedcall(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	int ret = 0;	aim_rxcallback_t userfunc;	fu16_t channel, nummissed, reason;	aim_userinfo_t userinfo;	while (aim_bstream_empty(bs)) {			channel = aimbs_get16(bs);		aim_extractuserinfo(sess, bs, &userinfo);		nummissed = aimbs_get16(bs);		reason = aimbs_get16(bs);		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))			 ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason);	}	return ret;}static int clienterr(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	int ret = 0;	aim_rxcallback_t userfunc;	fu16_t channel, reason;	char *sn;	fu8_t *ck, snlen;	ck = aimbs_getraw(bs, 8);	channel = aimbs_get16(bs);	snlen = aimbs_get8(bs);	sn = aimbs_getstr(bs, snlen);	reason = aimbs_get16(bs);	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))		 ret = userfunc(sess, rx, channel, sn, reason);	free(ck);	free(sn);	return ret;}static int msgack(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 type;	fu8_t snlen, *ck;	char *sn;	int ret = 0;	ck = aimbs_getraw(bs, 8);	type = aimbs_get16(bs);	snlen = aimbs_get8(bs);	sn = aimbs_getstr(bs, snlen);	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))		ret = userfunc(sess, rx, type, sn);	free(sn);	free(ck);	return ret;}static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){	if (snac->subtype == 0x0005)		return paraminfo(sess, mod, rx, snac, bs);	else if (snac->subtype == 0x0006)		return outgoingim(sess, mod, rx, snac, bs);	else if (snac->subtype == 0x0007)		return incomingim(sess, mod, rx, snac, bs);	else if (snac->subtype == 0x000a)		return missedcall(sess, mod, rx, snac, bs);	else if (snac->subtype == 0x000b)		return clienterr(sess, mod, rx, snac, bs);	else if (snac->subtype == 0x000c)		return msgack(sess, mod, rx, snac, bs);	return 0;}faim_internal int msg_modfirst(aim_session_t *sess, aim_module_t *mod){	mod->family = 0x0004;	mod->version = 0x0001;	mod->toolid = 0x0110;	mod->toolversion = 0x047b;	mod->flags = 0;	strncpy(mod->name, "messaging", sizeof(mod->name));	mod->snachandler = snachandler;	return 0;}

⌨️ 快捷键说明

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