# HG changeset patch # User Elliott Sales de Andrade # Date 1304632161 0 # Node ID 506b77a27a532f9e41abd622fe1e857176469392 # Parent 83c5af53308248b277024477dbd74b3211e7c067 This should fix TLV in from and out of the wire. diff -r 83c5af533082 -r 506b77a27a53 libpurple/protocols/msn/p2p.c --- a/libpurple/protocols/msn/p2p.c Thu May 05 07:21:14 2011 +0000 +++ b/libpurple/protocols/msn/p2p.c Thu May 05 21:49:21 2011 +0000 @@ -204,41 +204,43 @@ case MSN_P2P_VERSION_TWO: { MsnP2Pv2Header *header = &info->header.v2; + char *header_wire = NULL; + char *data_header_wire = NULL; if (header->header_tlv != NULL) - header->header_len = msn_tlvlist_size(header->header_tlv) + 8; + header_wire = msn_tlvlist_write(header->header_tlv, (size_t *)&header->header_len); else - header->header_len = 8; + header->header_len = 0; if (header->data_tlv != NULL) - header->data_header_len = msn_tlvlist_size(header->data_tlv) + 8; + data_header_wire = msn_tlvlist_write(header->data_tlv, (size_t *)&header->data_header_len); else - header->data_header_len = 8; + header->data_header_len = 0; - tmp = wire = g_new(char, header->header_len + header->data_header_len); + tmp = wire = g_new(char, 16 + header->header_len + header->data_header_len); - msn_push8(tmp, header->header_len); + msn_push8(tmp, header->header_len + 8); msn_push8(tmp, header->opcode); - msn_push16be(tmp, header->data_header_len + header->message_len); + msn_push16be(tmp, header->data_header_len + 8 + header->message_len); msn_push32be(tmp, header->base_id); - if (header->header_tlv != NULL) { - msn_tlvlist_write(tmp, header->header_len - 8, header->header_tlv); - tmp += header->header_len - 8; + if (header_wire != NULL) { + memcpy(tmp, header_wire, header->header_len); + tmp += header->header_len; } - msn_push8(tmp, header->data_header_len); + msn_push8(tmp, header->data_header_len + 8); msn_push8(tmp, header->data_tf); msn_push16be(tmp, header->package_number); msn_push32be(tmp, header->session_id); - if (header->data_tlv != NULL) { - msn_tlvlist_write(tmp, header->data_header_len - 8, header->data_tlv); - tmp += header->data_header_len - 8; + if (data_header_wire != NULL) { + memcpy(tmp, data_header_wire, header->data_header_len); + tmp += header->data_header_len; } if (len) - *len = header->header_len + header->data_header_len; + *len = header->header_len + header->data_header_len + 16; break; } @@ -248,7 +250,6 @@ } return wire; - } size_t diff -r 83c5af533082 -r 506b77a27a53 libpurple/protocols/msn/tlv.c --- a/libpurple/protocols/msn/tlv.c Thu May 05 07:21:14 2011 +0000 +++ b/libpurple/protocols/msn/tlv.c Thu May 05 21:49:21 2011 +0000 @@ -45,51 +45,50 @@ g_free(oldtlv); } -static GSList * -msn_tlv_read(GSList *list, const char *bs, size_t *bs_len) -{ - guint8 type, length; - msn_tlv_t *tlv; - - type = msn_read8(bs); - length = msn_read8(bs); - *bs_len -= 2; - - if (length > *bs_len) { - msn_tlvlist_free(list); - return NULL; - } - - tlv = createtlv(type, length, NULL); - if (length > 0) { - tlv->value = g_memdup(bs, length); - if (!tlv->value) { - freetlv(tlv); - msn_tlvlist_free(list); - return NULL; - } - } - - *bs_len -= length; - - return g_slist_prepend(list, tlv); -} - GSList * msn_tlvlist_read(const char *bs, size_t bs_len) { GSList *list = NULL; while (bs_len > 0) { - list = msn_tlv_read(list, bs, &bs_len); - if (list == NULL) + guint8 type, length; + msn_tlv_t *tlv; + + if (bs_len < 2) { + msn_tlvlist_free(list); + return NULL; + } + + type = msn_pop8(bs); + length = msn_pop8(bs); + bs_len -= 2; + + if (length > bs_len) { + msn_tlvlist_free(list); return NULL; + } + + tlv = createtlv(type, length, NULL); + if (length > 0) { + tlv->value = g_memdup(bs, length); + if (!tlv->value) { + freetlv(tlv); + msn_tlvlist_free(list); + return NULL; + } + } + + bs_len -= length; + bs += length; + + list = g_slist_prepend(list, tlv); } return g_slist_reverse(list); } -GSList *msn_tlvlist_copy(GSList *orig) +GSList * +msn_tlvlist_copy(GSList *orig) { GSList *new = NULL; msn_tlv_t *tlv; @@ -302,31 +301,38 @@ } } -int -msn_tlvlist_write(char *bs, size_t bs_len, GSList *list) +char * +msn_tlvlist_write(GSList *list, size_t *out_len) { -#if 0 - int goodbuflen; - GSList *cur; - msn_tlv_t *tlv; + char *buf; + char *tmp; + size_t bytes_left; + size_t total_len; - /* do an initial run to test total length */ - goodbuflen = msn_tlvlist_size(*list); + tmp = buf = g_malloc(256); + bytes_left = total_len = 256; + + for (; list; list = g_slist_next(list)) { + msn_tlv_t *tlv = (msn_tlv_t *)list->data; - if (goodbuflen > byte_stream_bytes_left(bs)) - return 0; /* not enough buffer */ + if (G_UNLIKELY(tlv->length + 2 > bytes_left)) { + buf = g_realloc(buf, total_len + 256); + bytes_left += 256; + total_len += 256; + tmp = buf + (total_len - bytes_left); + } - /* do the real write-out */ - for (cur = *list; cur; cur = cur->next) { - tlv = cur->data; - byte_stream_put16(bs, tlv->type); - byte_stream_put16(bs, tlv->length); - if (tlv->length > 0) - byte_stream_putraw(bs, tlv->value, tlv->length); + msn_push8(tmp, tlv->type); + msn_push8(tmp, tlv->length); + memcpy(tmp, tlv->value, tlv->length); + tmp += tlv->length; + + bytes_left -= (tlv->length + 2); } -#endif - return 0; /* TODO: This is a nonsensical return */ + *out_len = total_len - bytes_left; + + return buf; } msn_tlv_t * diff -r 83c5af533082 -r 506b77a27a53 libpurple/protocols/msn/tlv.h --- a/libpurple/protocols/msn/tlv.h Thu May 05 07:21:14 2011 +0000 +++ b/libpurple/protocols/msn/tlv.h Thu May 05 21:49:21 2011 +0000 @@ -52,7 +52,7 @@ int msn_tlvlist_count(GSList *list); size_t msn_tlvlist_size(GSList *list); gboolean msn_tlvlist_equal(GSList *one, GSList *two); -int msn_tlvlist_write(char *bs, size_t bs_len, GSList *list); +char *msn_tlvlist_write(GSList *list, size_t *out_len); void msn_tlvlist_free(GSList *list); int msn_tlvlist_add_raw(GSList **list, const guint16 type, const guint16 length, const char *value);