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

📄 tlv.c

📁 oscar message protocol stack
💻 C
📖 第 1 页 / 共 2 页
字号:
#define FAIM_INTERNAL#include <aim.h>static aim_tlv_t *createtlv(fu16_t type, fu16_t length, fu8_t *value){	aim_tlv_t *ret;	if (!(ret = (aim_tlv_t *)malloc(sizeof(aim_tlv_t))))		return NULL;	ret->type = type;	ret->length = length;	ret->value = value;	return ret;}static void freetlv(aim_tlv_t **oldtlv){	if (!oldtlv || !*oldtlv)		return;		free((*oldtlv)->value);	free(*oldtlv);	*oldtlv = NULL;	return;}/** * Read a TLV chain from a buffer. * * Reads and parses a series of TLV patterns from a data buffer; the * returned structure is manipulatable with the rest of the TLV * routines.  When done with a TLV chain, aim_tlvlist_free() should * be called to free the dynamic substructures. * * XXX There should be a flag setable here to have the tlvlist contain * bstream references, so that at least the ->value portion of each  * element doesn't need to be malloc/memcpy'd.  This could prove to be * just as efficient as the in-place TLV parsing used in a couple places * in libfaim. * * @param bs Input bstream * @return Return the TLV chain read */faim_internal aim_tlvlist_t *aim_tlvlist_read(aim_bstream_t *bs){	aim_tlvlist_t *list = NULL, *cur;		while (aim_bstream_empty(bs) > 0) {		fu16_t type, length;		type = aimbs_get16(bs);		length = aimbs_get16(bs);#if 0 /* temporarily disabled until I know if they're still doing it or not */		/*		 * Okay, so now AOL has decided that any TLV of		 * type 0x0013 can only be two bytes, despite		 * what the actual given length is.  So here 		 * we dump any invalid TLVs of that sort.  Hopefully		 * there's no special cases to this special case.		 *   - mid (30jun2000)		 */		if ((type == 0x0013) && (length != 0x0002))			length = 0x0002;#else		if (0)			;#endif		else {			if (length > aim_bstream_empty(bs)) {				aim_tlvlist_free(&list);				return NULL;			}			cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));			if (!cur) {				aim_tlvlist_free(&list);				return NULL;			}			memset(cur, 0, sizeof(aim_tlvlist_t));			cur->tlv = createtlv(type, length, NULL);			if (!cur->tlv) {				free(cur);				aim_tlvlist_free(&list);				return NULL;			}			if (cur->tlv->length > 0) {				cur->tlv->value = aimbs_getraw(bs, length);					if (!cur->tlv->value) {					freetlv(&cur->tlv);					free(cur);					aim_tlvlist_free(&list);					return NULL;				}			}			cur->next = list;			list = cur;		}	}	return list;}/** * Read a TLV chain from a buffer. * * Reads and parses a series of TLV patterns from a data buffer; the * returned structure is manipulatable with the rest of the TLV * routines.  When done with a TLV chain, aim_tlvlist_free() should * be called to free the dynamic substructures. * * XXX There should be a flag setable here to have the tlvlist contain * bstream references, so that at least the ->value portion of each  * element doesn't need to be malloc/memcpy'd.  This could prove to be * just as efficient as the in-place TLV parsing used in a couple places * in libfaim. * * @param bs Input bstream * @param num The max number of TLVs that will be read, or -1 if unlimited.   *        There are a number of places where you want to read in a tlvchain,  *        but the chain is not at the end of the SNAC, and the chain is  *        preceded by the number of TLVs.  So you can limit that with this. * @return Return the TLV chain read */faim_internal aim_tlvlist_t *aim_tlvlist_readnum(aim_bstream_t *bs, fu16_t num){	aim_tlvlist_t *list = NULL, *cur;	while ((aim_bstream_empty(bs) > 0) && (num != 0)) {		fu16_t type, length;		type = aimbs_get16(bs);		length = aimbs_get16(bs);		if (length > aim_bstream_empty(bs)) {			aim_tlvlist_free(&list);			return NULL;		}		cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));		if (!cur) {			aim_tlvlist_free(&list);			return NULL;		}		memset(cur, 0, sizeof(aim_tlvlist_t));		cur->tlv = createtlv(type, length, NULL);		if (!cur->tlv) {			free(cur);			aim_tlvlist_free(&list);			return NULL;		}		if (cur->tlv->length > 0) {			cur->tlv->value = aimbs_getraw(bs, length);			if (!cur->tlv->value) {				freetlv(&cur->tlv);				free(cur);				aim_tlvlist_free(&list);				return NULL;			}		}		if (num > 0)			num--;		cur->next = list;		list = cur;	}	return list;}/** * Read a TLV chain from a buffer. * * Reads and parses a series of TLV patterns from a data buffer; the * returned structure is manipulatable with the rest of the TLV * routines.  When done with a TLV chain, aim_tlvlist_free() should * be called to free the dynamic substructures. * * XXX There should be a flag setable here to have the tlvlist contain * bstream references, so that at least the ->value portion of each  * element doesn't need to be malloc/memcpy'd.  This could prove to be * just as efficient as the in-place TLV parsing used in a couple places * in libfaim. * * @param bs Input bstream * @param len The max length in bytes that will be read. *        There are a number of places where you want to read in a tlvchain,  *        but the chain is not at the end of the SNAC, and the chain is  *        preceded by the length of the TLVs.  So you can limit that with this. * @return Return the TLV chain read */faim_internal aim_tlvlist_t *aim_tlvlist_readlen(aim_bstream_t *bs, fu16_t len){	aim_tlvlist_t *list = NULL, *cur;	while ((aim_bstream_empty(bs) > 0) && (len > 0)) {		fu16_t type, length;		type = aimbs_get16(bs);		length = aimbs_get16(bs);		if (length > aim_bstream_empty(bs)) {			aim_tlvlist_free(&list);			return NULL;		}		cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));		if (!cur) {			aim_tlvlist_free(&list);			return NULL;		}		memset(cur, 0, sizeof(aim_tlvlist_t));		cur->tlv = createtlv(type, length, NULL);		if (!cur->tlv) {			free(cur);			aim_tlvlist_free(&list);			return NULL;		}		if (cur->tlv->length > 0) {			cur->tlv->value = aimbs_getraw(bs, length);			if (!cur->tlv->value) {				freetlv(&cur->tlv);				free(cur);				aim_tlvlist_free(&list);				return NULL;			}		}		len -= aim_tlvlist_size(&cur);		cur->next = list;		list = cur;	}	return list;}/** * Duplicate a TLV chain. * This is pretty self explanatory. * * @param orig The TLV chain you want to make a copy of. * @return A newly allocated TLV chain. */faim_internal aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig){	aim_tlvlist_t *new = NULL;	while (orig) {		aim_tlvlist_add_raw(&new, orig->tlv->type, orig->tlv->length, orig->tlv->value);		orig = orig->next;	}	return new;}/* * Compare two TLV lists for equality.  This probably is not the most  * efficient way to do this. * * @param one One of the TLV chains to compare. * @param two The other TLV chain to compare. * @return Return 0 if the lists are the same, return 1 if they are different. */faim_internal int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two){	aim_bstream_t bs1, bs2;	if (aim_tlvlist_size(&one) != aim_tlvlist_size(&two))		return 1;	aim_bstream_init(&bs1, ((fu8_t *)malloc(aim_tlvlist_size(&one)*sizeof(fu8_t))), aim_tlvlist_size(&one));	aim_bstream_init(&bs2, ((fu8_t *)malloc(aim_tlvlist_size(&two)*sizeof(fu8_t))), aim_tlvlist_size(&two));	aim_tlvlist_write(&bs1, &one);	aim_tlvlist_write(&bs2, &two);	if (memcmp(bs1.data, bs2.data, bs1.len)) {		free(bs1.data);		free(bs2.data);		return 1;	}	free(bs1.data);	free(bs2.data);	return 0;}/** * Free a TLV chain structure * * Walks the list of TLVs in the passed TLV chain and * frees each one. Note that any references to this data * should be removed before calling this. * * @param list Chain to be freed */faim_internal void aim_tlvlist_free(aim_tlvlist_t **list){	aim_tlvlist_t *cur;	if (!list || !*list)		return;	for (cur = *list; cur; ) {		aim_tlvlist_t *tmp;				freetlv(&cur->tlv);		tmp = cur->next;		free(cur);		cur = tmp;	}	list = NULL;	return;}/** * Count the number of TLVs in a chain. * * @param list Chain to be counted. * @return The number of TLVs stored in the passed chain. */faim_internal int aim_tlvlist_count(aim_tlvlist_t **list){	aim_tlvlist_t *cur;	int count;	if (!list || !*list)		return 0;	for (cur = *list, count = 0; cur; cur = cur->next)		count++;	return count;}/** * Count the number of bytes in a TLV chain. * * @param list Chain to be sized * @return The number of bytes that would be needed to  *         write the passed TLV chain to a data buffer. */faim_internal int aim_tlvlist_size(aim_tlvlist_t **list){	aim_tlvlist_t *cur;	int size;	if (!list || !*list)		return 0;	for (cur = *list, size = 0; cur; cur = cur->next)		size += (4 + cur->tlv->length);	return size;}/** * Adds the passed string as a TLV element of the passed type * to the TLV chain. * * @param list Desination chain (%NULL pointer if empty). * @param type TLV type. * @param length Length of string to add (not including %NULL). * @param value String to add. * @return The size of the value added. */faim_internal int aim_tlvlist_add_raw(aim_tlvlist_t **list, const fu16_t type, const fu16_t length, const fu8_t *value){	aim_tlvlist_t *newtlv, *cur;	if (list == NULL)		return 0;	if (!(newtlv = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t))))		return 0;	memset(newtlv, 0x00, sizeof(aim_tlvlist_t));	if (!(newtlv->tlv = createtlv(type, length, NULL))) {		free(newtlv);		return 0;	}	if (newtlv->tlv->length > 0) {		newtlv->tlv->value = (fu8_t *)malloc(newtlv->tlv->length);		memcpy(newtlv->tlv->value, value, newtlv->tlv->length);	}	if (!*list)		*list = newtlv;	else {		for(cur = *list; cur->next; cur = cur->next)			;		cur->next = newtlv;	}	return newtlv->tlv->length;}/** * Add a one byte integer to a TLV chain. * * @param list Destination chain. * @param type TLV type to add. * @param value Value to add. * @return The size of the value added. */faim_internal int aim_tlvlist_add_8(aim_tlvlist_t **list, const fu16_t type, const fu8_t value){	fu8_t v8[1];	aimutil_put8(v8, value);	return aim_tlvlist_add_raw(list, type, 1, v8);}/** * Add a two byte integer to a TLV chain. * * @param list Destination chain. * @param type TLV type to add. * @param value Value to add. * @return The size of the value added. */faim_internal int aim_tlvlist_add_16(aim_tlvlist_t **list, const fu16_t type, const fu16_t value){	fu8_t v16[2];	aimutil_put16(v16, value);	return aim_tlvlist_add_raw(list, type, 2, v16);}

⌨️ 快捷键说明

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