Mercurial > pidgin
comparison libpurple/protocols/msn/tlv.c @ 31558:ce968e115c95
propagate from branch 'im.pidgin.cpw.masca.p2p' (head 33ca865dacb9e5bcf763d06f6a42cbaca337cc64)
to branch 'im.pidgin.pidgin' (head 92f47f4e8b0cbb107fd97e1ab814d1cedbf109ad)
author | Elliott Sales de Andrade <qulogic@pidgin.im> |
---|---|
date | Fri, 06 May 2011 06:25:14 +0000 |
parents | dfc2a8e98430 |
children | bd59044a9100 |
comparison
equal
deleted
inserted
replaced
31557:f021d93a1f9b | 31558:ce968e115c95 |
---|---|
43 { | 43 { |
44 g_free(oldtlv->value); | 44 g_free(oldtlv->value); |
45 g_free(oldtlv); | 45 g_free(oldtlv); |
46 } | 46 } |
47 | 47 |
48 static GSList * | 48 GSList * |
49 msn_tlv_read(GSList *list, char *bs, size_t *bs_len) | 49 msn_tlvlist_read(const char *bs, size_t bs_len) |
50 { | 50 { |
51 guint8 type, length; | 51 GSList *list = NULL; |
52 msn_tlv_t *tlv; | 52 |
53 | 53 while (bs_len > 0) { |
54 type = msn_read8(bs); | 54 guint8 type, length; |
55 length = msn_read8(bs); | 55 msn_tlv_t *tlv; |
56 *bs_len -= 2; | 56 |
57 | 57 if (bs_len == 3 && *bs == 0) { |
58 if (length > *bs_len) { | 58 /* Padding to multiple of 4 */ |
59 msn_tlvlist_free(list); | 59 break; |
60 return NULL; | 60 } else if (bs_len == 2 && *bs == 0) { |
61 } | 61 /* Padding to multiple of 4 */ |
62 | 62 break; |
63 tlv = createtlv(type, length, NULL); | 63 } else if (bs_len == 1) { |
64 if (length > 0) { | 64 if (*bs == 0) { |
65 tlv->value = g_memdup(bs, length); | 65 /* Padding to multiple of 4 */ |
66 if (!tlv->value) { | 66 break; |
67 freetlv(tlv); | 67 } else { |
68 /* TLV is not small enough to fit here */ | |
69 msn_tlvlist_free(list); | |
70 return NULL; | |
71 } | |
72 } | |
73 | |
74 type = msn_pop8(bs); | |
75 length = msn_pop8(bs); | |
76 bs_len -= 2; | |
77 | |
78 if (length > bs_len) { | |
68 msn_tlvlist_free(list); | 79 msn_tlvlist_free(list); |
69 return NULL; | 80 return NULL; |
70 } | 81 } |
71 } | 82 |
72 | 83 tlv = createtlv(type, length, NULL); |
73 *bs_len -= length; | 84 if (length > 0) { |
74 | 85 tlv->value = g_memdup(bs, length); |
75 return g_slist_prepend(list, tlv); | 86 if (!tlv->value) { |
87 freetlv(tlv); | |
88 msn_tlvlist_free(list); | |
89 return NULL; | |
90 } | |
91 } | |
92 | |
93 bs_len -= length; | |
94 bs += length; | |
95 | |
96 list = g_slist_prepend(list, tlv); | |
97 } | |
98 | |
99 return g_slist_reverse(list); | |
76 } | 100 } |
77 | 101 |
78 GSList * | 102 GSList * |
79 msn_tlvlist_read(char *bs, size_t bs_len) | 103 msn_tlvlist_copy(GSList *orig) |
80 { | |
81 GSList *list = NULL; | |
82 | |
83 while (bs_len > 0) { | |
84 list = msn_tlv_read(list, bs, &bs_len); | |
85 if (list == NULL) | |
86 return NULL; | |
87 } | |
88 | |
89 return g_slist_reverse(list); | |
90 } | |
91 | |
92 GSList *msn_tlvlist_copy(GSList *orig) | |
93 { | 104 { |
94 GSList *new = NULL; | 105 GSList *new = NULL; |
95 msn_tlv_t *tlv; | 106 msn_tlv_t *tlv; |
96 | 107 |
97 while (orig != NULL) { | 108 while (orig != NULL) { |
265 msn_write8(v8, value); | 276 msn_write8(v8, value); |
266 | 277 |
267 return msn_tlvlist_replace_raw(list, type, 1, v8); | 278 return msn_tlvlist_replace_raw(list, type, 1, v8); |
268 } | 279 } |
269 | 280 |
270 int | 281 int |
271 msn_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value) | 282 msn_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value) |
272 { | 283 { |
273 char v32[4]; | 284 char v32[4]; |
274 | 285 |
275 msn_write32be(v32, value); | 286 msn_write32be(v32, value); |
300 | 311 |
301 cur = next; | 312 cur = next; |
302 } | 313 } |
303 } | 314 } |
304 | 315 |
305 #if 0 | 316 char * |
306 int | 317 msn_tlvlist_write(GSList *list, size_t *out_len) |
307 msn_tlvlist_write(ByteStream *bs, GSList **list) | 318 { |
308 { | 319 char *buf; |
309 int goodbuflen; | 320 char *tmp; |
310 GSList *cur; | 321 size_t bytes_left; |
311 msn_tlv_t *tlv; | 322 size_t total_len; |
312 | 323 |
313 /* do an initial run to test total length */ | 324 tmp = buf = g_malloc(256); |
314 goodbuflen = msn_tlvlist_size(*list); | 325 bytes_left = total_len = 256; |
315 | 326 |
316 if (goodbuflen > byte_stream_bytes_left(bs)) | 327 for (; list; list = g_slist_next(list)) { |
317 return 0; /* not enough buffer */ | 328 msn_tlv_t *tlv = (msn_tlv_t *)list->data; |
318 | 329 |
319 /* do the real write-out */ | 330 if (G_UNLIKELY(tlv->length + 2 > bytes_left)) { |
320 for (cur = *list; cur; cur = cur->next) { | 331 buf = g_realloc(buf, total_len + 256); |
321 tlv = cur->data; | 332 bytes_left += 256; |
322 byte_stream_put16(bs, tlv->type); | 333 total_len += 256; |
323 byte_stream_put16(bs, tlv->length); | 334 tmp = buf + (total_len - bytes_left); |
324 if (tlv->length > 0) | 335 } |
325 byte_stream_putraw(bs, tlv->value, tlv->length); | 336 |
326 } | 337 msn_push8(tmp, tlv->type); |
327 | 338 msn_push8(tmp, tlv->length); |
328 return 1; /* TODO: This is a nonsensical return */ | 339 memcpy(tmp, tlv->value, tlv->length); |
329 } | 340 tmp += tlv->length; |
330 #endif | 341 |
342 bytes_left -= (tlv->length + 2); | |
343 } | |
344 | |
345 /* Align length to multiple of 4 */ | |
346 total_len = total_len - bytes_left; | |
347 bytes_left = 4 - total_len % 4; | |
348 if (bytes_left != 4) | |
349 memset(tmp, 0, bytes_left); | |
350 else | |
351 bytes_left = 0; | |
352 | |
353 *out_len = total_len + bytes_left; | |
354 | |
355 return buf; | |
356 } | |
331 | 357 |
332 msn_tlv_t * | 358 msn_tlv_t * |
333 msn_tlv_gettlv(GSList *list, const guint16 type, const int nth) | 359 msn_tlv_gettlv(GSList *list, const guint16 type, const int nth) |
334 { | 360 { |
335 msn_tlv_t *tlv; | 361 msn_tlv_t *tlv; |