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

📄 im.c

📁 AnyQ服务端源代码(2004/10/28)源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  aim_im.c * *  The routines for sending/receiving Instant Messages. * *  Note the term ICBM (Inter-Client Basic Message) which blankets *  all types of genericly routed through-server messages.  Within *  the ICBM types (family 4), a channel is defined.  Each channel *  represents a different type of message.  Channel 1 is used for *  what would commonly be called an "instant message".  Channel 2 *  is used for negotiating "rendezvous".  These transactions end in *  something more complex happening, such as a chat invitation, or *  a file transfer. * *  In addition to the channel, every ICBM contains a cookie.  For *  standard IMs, these are only used for error messages.  However, *  the more complex rendezvous messages make suitably more complex *  use of this field. * */#define FAIM_INTERNAL#include <aim.h>/* * Takes a msghdr (and a length) and returns a client type * code.  Note that this is *only a guess* and has a low likelihood * of actually being accurate. * * Its based on experimental data, with the help of Eric Warmenhoven * who seems to have collected a wide variety of different AIM clients. * * * Heres the current collection: *  0501 0003 0101 0101 01       AOL Mobile Communicator, WinAIM 1.0.414 *  0501 0003 0101 0201 01       WinAIM 2.0.847, 2.1.1187, 3.0.1464,  *                                      4.3.2229, 4.4.2286 *  0501 0004 0101 0102 0101     WinAIM 4.1.2010, libfaim (right here) *  0501 0001 0101 01            AOL v6.0, CompuServe 2000 v6.0, any *                                      TOC client * * Note that in this function, only the feature bytes are tested, since * the rest will always be the same. * */faim_export fu16_t aim_fingerprintclient(fu8_t *msghdr, int len){	static const struct {		fu16_t clientid;		int len;		fu8_t data[10];	} fingerprints[] = {		/* AOL Mobile Communicator, WinAIM 1.0.414 */		{ AIM_CLIENTTYPE_MC, 		  3, {0x01, 0x01, 0x01}},		/* WinAIM 2.0.847, 2.1.1187, 3.0.1464, 4.3.2229, 4.4.2286 */		{ AIM_CLIENTTYPE_WINAIM, 		  3, {0x01, 0x01, 0x02}},		/* WinAIM 4.1.2010, libfaim */		{ AIM_CLIENTTYPE_WINAIM41,		  4, {0x01, 0x01, 0x01, 0x02}},		/* AOL v6.0, CompuServe 2000 v6.0, any TOC client */		{ AIM_CLIENTTYPE_AOL_TOC,		  1, {0x01}},		{ 0, 0}	};	int i;	if (!msghdr || (len <= 0))		return AIM_CLIENTTYPE_UNKNOWN;	for (i = 0; fingerprints[i].len; i++) {		if (fingerprints[i].len != len)			continue;		if (memcmp(fingerprints[i].data, msghdr, fingerprints[i].len) == 0)			return fingerprints[i].clientid;	}	return AIM_CLIENTTYPE_UNKNOWN;}/* This should be endian-safe now... but who knows... */faim_export fu16_t aim_iconsum(const fu8_t *buf, int buflen){	fu32_t sum;	int i;	for (i = 0, sum = 0; i + 1 < buflen; i += 2)		sum += (buf[i+1] << 8) + buf[i];	if (i < buflen)		sum += buf[i];	sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff);	return (fu16_t)sum;}/* * Send an ICBM (instant message).   * * * Possible flags: *   AIM_IMFLAGS_AWAY  -- Marks the message as an autoresponse *   AIM_IMFLAGS_ACK   -- Requests that the server send an ack *                        when the message is received (of type 0x0004/0x000c) *   AIM_IMFLAGS_OFFLINE--If destination is offline, store it until they are *                        online (probably ICQ only). *   AIM_IMFLAGS_UNICODE--Instead of ASCII7, the passed message is *                        made up of UNICODE duples.  If you set *                        this, you'd better be damn sure you know *                        what you're doing. *   AIM_IMFLAGS_ISO_8859_1 -- The message contains the ASCII8 subset *                        known as ISO-8859-1.   * * Generally, you should use the lowest encoding possible to send * your message.  If you only use basic punctuation and the generic * Latin alphabet, use ASCII7 (no flags).  If you happen to use non-ASCII7 * characters, but they are all clearly defined in ISO-8859-1, then  * use that.  Keep in mind that not all characters in the PC ASCII8 * character set are defined in the ISO standard. For those cases (most * notably when the (r) symbol is used), you must use the full UNICODE * encoding for your message.  In UNICODE mode, _all_ characters must * occupy 16bits, including ones that are not special.  (Remember that * the first 128 UNICODE symbols are equivelent to ASCII7, however they * must be prefixed with a zero high order byte.) * * I strongly discourage the use of UNICODE mode, mainly because none * of the clients I use can parse those messages (and besides that, * wchars are difficult and non-portable to handle in most UNIX environments). * If you really need to include special characters, use the HTML UNICODE  * entities.  These are of the form &#2026; where 2026 is the hex  * representation of the UNICODE index (in this case, UNICODE  * "Horizontal Ellipsis", or 133 in in ASCII8). * * Implementation note:  Since this is one of the most-used functions * in all of libfaim, it is written with performance in mind.  As such, * it is not as clear as it could be in respect to how this message is * supposed to be layed out. Most obviously, tlvlists should be used  * instead of writing out the bytes manually.  * * XXX more precise verification that we never send SNACs larger than 8192 * XXX check SNAC size for multipart * */faim_export int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args){	static const fu8_t deffeatures[] = {		0x01, 0x01, 0x01, 0x02	};	aim_conn_t *conn;	int i, msgtlvlen;	aim_frame_t *fr;	aim_snacid_t snacid;	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))		return -EINVAL;	if (!args)		return -EINVAL;	if (args->flags & AIM_IMFLAGS_MULTIPART) {		if (args->mpmsg->numparts <= 0)			return -EINVAL;	} else {		if (!args->msg || (args->msglen <= 0))			return -EINVAL;		if (args->msglen >= MAXMSGLEN)			return -E2BIG;	}	/* Painfully calculate the size of the message TLV */	msgtlvlen = 1 + 1; /* 0501 */	if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES)		msgtlvlen += 2 + args->featureslen;	else		msgtlvlen += 2 + sizeof(deffeatures);	if (args->flags & AIM_IMFLAGS_MULTIPART) {		aim_mpmsg_section_t *sec;		for (sec = args->mpmsg->parts; sec; sec = sec->next) {			msgtlvlen += 2 /* 0101 */ + 2 /* block len */;			msgtlvlen += 4 /* charset */ + sec->datalen;		}	} else {		msgtlvlen += 2 /* 0101 */ + 2 /* block len */;		msgtlvlen += 4 /* charset */ + args->msglen;	}	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, msgtlvlen+128)))		return -ENOMEM;	/* XXX should be optional */		snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, args->destsn, strlen(args->destsn)+1);	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);	/* 	 * Generate a random message cookie 	 *	 * We could cache these like we do SNAC IDs.  (In fact, it 	 * might be a good idea.)  In the message error functions, 	 * the 8byte message cookie is returned as well as the 	 * SNAC ID.	 *	 */	for (i = 0; i < 8; i++)		aimbs_put8(&fr->data, (fu8_t) rand());	/*	 * Channel ID	 */	aimbs_put16(&fr->data, 0x0001);	/*	 * Destination SN (prepended with byte length)	 */	aimbs_put8(&fr->data, strlen(args->destsn));	aimbs_putraw(&fr->data, args->destsn, strlen(args->destsn));	/*	 * Message TLV (type 2).	 */	aimbs_put16(&fr->data, 0x0002);	aimbs_put16(&fr->data, msgtlvlen);	/*	 * Features 	 *	 */	aimbs_put8(&fr->data, 0x05);	aimbs_put8(&fr->data, 0x01);	if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) {		aimbs_put16(&fr->data, args->featureslen);		aimbs_putraw(&fr->data, args->features, args->featureslen);	} else {		aimbs_put16(&fr->data, sizeof(deffeatures));		aimbs_putraw(&fr->data, deffeatures, sizeof(deffeatures));	}	if (args->flags & AIM_IMFLAGS_MULTIPART) {		aim_mpmsg_section_t *sec;		for (sec = args->mpmsg->parts; sec; sec = sec->next) {			aimbs_put16(&fr->data, 0x0101);			aimbs_put16(&fr->data, sec->datalen + 4);			aimbs_put16(&fr->data, sec->charset);			aimbs_put16(&fr->data, sec->charsubset);			aimbs_putraw(&fr->data, sec->data, sec->datalen);		}	} else {		aimbs_put16(&fr->data, 0x0101);		/* 		 * Message block length.		 */		aimbs_put16(&fr->data, args->msglen + 0x04);		/*		 * Character set.		 */		if (args->flags & AIM_IMFLAGS_CUSTOMCHARSET) {			aimbs_put16(&fr->data, args->charset);			aimbs_put16(&fr->data, args->charsubset);		} else {			if (args->flags & AIM_IMFLAGS_UNICODE)				aimbs_put16(&fr->data, 0x0002);			else if (args->flags & AIM_IMFLAGS_ISO_8859_1)				aimbs_put16(&fr->data, 0x0003);			else				aimbs_put16(&fr->data, 0x0000);			aimbs_put16(&fr->data, 0x0000);		}		/*		 * Message.  Not terminated.		 */		aimbs_putraw(&fr->data, args->msg, args->msglen);	}	/*	 * Set the Request Acknowledge flag.  	 */	if (args->flags & AIM_IMFLAGS_ACK) {		aimbs_put16(&fr->data, 0x0003);		aimbs_put16(&fr->data, 0x0000);	}	/*	 * Set the Autoresponse flag.	 */	if (args->flags & AIM_IMFLAGS_AWAY) {		aimbs_put16(&fr->data, 0x0004);		aimbs_put16(&fr->data, 0x0000);	}	if (args->flags & AIM_IMFLAGS_OFFLINE) {		aimbs_put16(&fr->data, 0x0006);		aimbs_put16(&fr->data, 0x0000);	}	/*	 * Set the I HAVE A REALLY PURTY ICON flag.	 */	if (args->flags & AIM_IMFLAGS_HASICON) {		aimbs_put16(&fr->data, 0x0008);		aimbs_put16(&fr->data, 0x000c);		aimbs_put32(&fr->data, args->iconlen);		aimbs_put16(&fr->data, 0x0001);		aimbs_put16(&fr->data, args->iconsum);		aimbs_put32(&fr->data, args->iconstamp);	}	/*	 * Set the Buddy Icon Requested flag.	 */	if (args->flags & AIM_IMFLAGS_BUDDYREQ) {		aimbs_put16(&fr->data, 0x0009);		aimbs_put16(&fr->data, 0x0000);	}	aim_tx_enqueue(sess, fr);	if (!(sess->flags & AIM_SESS_FLAGS_DONTTIMEOUTONICBM))		aim_cleansnacs(sess, 60); /* clean out SNACs over 60sec old */	return 0;}/* * Simple wrapper for aim_send_im_ext()  * * You cannot use aim_send_im if you need the HASICON flag.  You must * use aim_send_im_ext directly for that. * * aim_send_im also cannot be used if you require UNICODE messages, because * that requires an explicit message length.  Use aim_send_im_ext(). * */faim_export int aim_send_im(aim_session_t *sess, const char *destsn, fu16_t flags, const char *msg){	struct aim_sendimext_args args;	args.destsn = destsn;	args.flags = flags;	args.msg = msg;	args.msglen = strlen(msg);	/* Make these don't get set by accident -- they need aim_send_im_ext */	args.flags &= ~(AIM_IMFLAGS_CUSTOMFEATURES | AIM_IMFLAGS_HASICON | AIM_IMFLAGS_MULTIPART);	return aim_send_im_ext(sess, &args);}/* * This is also performance sensitive. (If you can believe it...) * */faim_export int aim_send_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum){	aim_conn_t *conn;	int i;	fu8_t ck[8];	aim_frame_t *fr;	aim_snacid_t snacid;	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))		return -EINVAL;	if (!sn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN))		return -EINVAL;	for (i = 0; i < 8; i++)		aimutil_put8(ck+i, (fu8_t) rand());	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn)+2+2+2+8+16+2+2+2+2+2+2+2+4+4+4+iconlen+strlen(AIM_ICONIDENT)+2+2)))		return -ENOMEM;	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);	/*	 * Cookie	 */	aimbs_putraw(&fr->data, ck, 8);	/*	 * Channel (2)	 */	aimbs_put16(&fr->data, 0x0002);	/*	 * Dest sn	 */	aimbs_put8(&fr->data, strlen(sn));	aimbs_putraw(&fr->data, sn, strlen(sn));	/*	 * TLV t(0005)	 *	 * Encompasses everything below.	 */	aimbs_put16(&fr->data, 0x0005);	aimbs_put16(&fr->data, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT));	aimbs_put16(&fr->data, 0x0000);	aimbs_putraw(&fr->data, ck, 8);	aim_putcap(&fr->data, AIM_CAPS_BUDDYICON);	/* TLV t(000a) */	aimbs_put16(&fr->data, 0x000a);	aimbs_put16(&fr->data, 0x0002);	aimbs_put16(&fr->data, 0x0001);	/* TLV t(000f) */	aimbs_put16(&fr->data, 0x000f);	aimbs_put16(&fr->data, 0x0000);	/* TLV t(2711) */	aimbs_put16(&fr->data, 0x2711);	aimbs_put16(&fr->data, 4+4+4+iconlen+strlen(AIM_ICONIDENT));	aimbs_put16(&fr->data, 0x0000);	aimbs_put16(&fr->data, iconsum);	aimbs_put32(&fr->data, iconlen);	aimbs_put32(&fr->data, stamp);	aimbs_putraw(&fr->data, icon, iconlen);	aimbs_putraw(&fr->data, AIM_ICONIDENT, strlen(AIM_ICONIDENT));	/* TLV t(0003) */	aimbs_put16(&fr->data, 0x0003);	aimbs_put16(&fr->data, 0x0000);	aim_tx_enqueue(sess, fr);	return 0;}faim_internal int aim_request_directim(aim_session_t *sess, const char *destsn, fu8_t *ip, fu16_t port, fu8_t *ckret){	aim_conn_t *conn;

⌨️ 快捷键说明

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