~ubuntu-branches/debian/sid/kamailio/sid

« back to all changes in this revision

Viewing changes to modules/rtpproxy-ng/bencode.c

  • Committer: Package Import Robot
  • Author(s): Victor Seva
  • Date: 2014-01-06 11:47:13 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20140106114713-t8xidp4arzrnyeya
Tags: 4.1.1-1
* New upstream release
* debian/patches:
  - add upstream fixes
* Added tls outbound websocket autheph dnssec modules
  - openssl exception added to their license
* removing sparc and ia64 from supported archs
  for mono module (Closes: #728915)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "bencode.h"
 
2
#include <stdio.h>
 
3
#include <sys/uio.h>
 
4
#include <unistd.h>
 
5
#include <stdlib.h>
 
6
#include <assert.h>
 
7
#include <string.h>
 
8
 
 
9
 
 
10
/* set to 0 for alloc debugging, e.g. through valgrind */
 
11
#define BENCODE_MIN_BUFFER_PIECE_LEN    512
 
12
 
 
13
#define BENCODE_HASH_BUCKETS            31 /* prime numbers work best */
 
14
 
 
15
struct __bencode_buffer_piece {
 
16
        char *tail;
 
17
        unsigned int left;
 
18
        struct __bencode_buffer_piece *next;
 
19
        char buf[0];
 
20
};
 
21
struct __bencode_free_list {
 
22
        void *ptr;
 
23
        free_func_t func;
 
24
        struct __bencode_free_list *next;
 
25
};
 
26
struct __bencode_hash {
 
27
        struct bencode_item *buckets[BENCODE_HASH_BUCKETS];
 
28
};
 
29
 
 
30
 
 
31
 
 
32
 
 
33
 
 
34
static bencode_item_t __bencode_end_marker = {
 
35
        .type = BENCODE_END_MARKER,
 
36
        .iov[0].iov_base = "e",
 
37
        .iov[0].iov_len = 1,
 
38
        .iov_cnt = 1,
 
39
        .str_len = 1,
 
40
};
 
41
 
 
42
 
 
43
 
 
44
 
 
45
static bencode_item_t *__bencode_decode(bencode_buffer_t *buf, const char *s, const char *end);
 
46
 
 
47
 
 
48
 
 
49
static void __bencode_item_init(bencode_item_t *item) {
 
50
        item->last_child = item->parent = item->child = item->sibling = NULL;
 
51
}
 
52
 
 
53
static void __bencode_container_init(bencode_item_t *cont) {
 
54
        cont->iov[0].iov_len = 1;
 
55
        cont->iov[1].iov_base = "e";
 
56
        cont->iov[1].iov_len = 1;
 
57
        cont->iov_cnt = 2;
 
58
        cont->str_len = 2;
 
59
}
 
60
 
 
61
static void __bencode_dictionary_init(bencode_item_t *dict) {
 
62
        dict->type = BENCODE_DICTIONARY;
 
63
        dict->iov[0].iov_base = "d";
 
64
        dict->value = 0;
 
65
        __bencode_container_init(dict);
 
66
}
 
67
 
 
68
static void __bencode_list_init(bencode_item_t *list) {
 
69
        list->type = BENCODE_LIST;
 
70
        list->iov[0].iov_base = "l";
 
71
        __bencode_container_init(list);
 
72
}
 
73
 
 
74
static struct __bencode_buffer_piece *__bencode_piece_new(unsigned int size) {
 
75
        struct __bencode_buffer_piece *ret;
 
76
 
 
77
        if (size < BENCODE_MIN_BUFFER_PIECE_LEN)
 
78
                size = BENCODE_MIN_BUFFER_PIECE_LEN;
 
79
        ret = BENCODE_MALLOC(sizeof(*ret) + size);
 
80
        if (!ret)
 
81
                return NULL;
 
82
 
 
83
        ret->tail = ret->buf;
 
84
        ret->left = size;
 
85
        ret->next = NULL;
 
86
 
 
87
        return ret;
 
88
}
 
89
 
 
90
int bencode_buffer_init(bencode_buffer_t *buf) {
 
91
        buf->pieces = __bencode_piece_new(0);
 
92
        if (!buf->pieces)
 
93
                return -1;
 
94
        buf->free_list = NULL;
 
95
        buf->error = 0;
 
96
        return 0;
 
97
}
 
98
 
 
99
static void *__bencode_alloc(bencode_buffer_t *buf, unsigned int size) {
 
100
        struct __bencode_buffer_piece *piece;
 
101
        void *ret;
 
102
 
 
103
        if (!buf)
 
104
                return NULL;
 
105
        if (buf->error)
 
106
                return NULL;
 
107
 
 
108
        piece = buf->pieces;
 
109
 
 
110
        if (size <= piece->left)
 
111
                goto alloc;
 
112
 
 
113
        piece = __bencode_piece_new(size);
 
114
        if (!piece) {
 
115
                buf->error = 1;
 
116
                return NULL;
 
117
        }
 
118
        piece->next = buf->pieces;
 
119
        buf->pieces = piece;
 
120
 
 
121
        assert(size <= piece->left);
 
122
 
 
123
alloc:
 
124
        piece->left -= size;
 
125
        ret = piece->tail;
 
126
        piece->tail += size;
 
127
        return ret;
 
128
}
 
129
 
 
130
void bencode_buffer_free(bencode_buffer_t *buf) {
 
131
        struct __bencode_free_list *fl;
 
132
        struct __bencode_buffer_piece *piece, *next;
 
133
 
 
134
        for (fl = buf->free_list; fl; fl = fl->next)
 
135
                fl->func(fl->ptr);
 
136
 
 
137
        for (piece = buf->pieces; piece; piece = next) {
 
138
                next = piece->next;
 
139
                BENCODE_FREE(piece);
 
140
        }
 
141
}
 
142
 
 
143
static bencode_item_t *__bencode_item_alloc(bencode_buffer_t *buf, unsigned int payload) {
 
144
        bencode_item_t *ret;
 
145
 
 
146
        ret = __bencode_alloc(buf, sizeof(struct bencode_item) + payload);
 
147
        if (!ret)
 
148
                return NULL;
 
149
        ret->buffer = buf;
 
150
        __bencode_item_init(ret);
 
151
        return ret;
 
152
}
 
153
 
 
154
bencode_item_t *bencode_dictionary(bencode_buffer_t *buf) {
 
155
        bencode_item_t *ret;
 
156
 
 
157
        ret = __bencode_item_alloc(buf, 0);
 
158
        if (!ret)
 
159
                return NULL;
 
160
        __bencode_dictionary_init(ret);
 
161
        return ret;
 
162
}
 
163
 
 
164
bencode_item_t *bencode_list(bencode_buffer_t *buf) {
 
165
        bencode_item_t *ret;
 
166
 
 
167
        ret = __bencode_item_alloc(buf, 0);
 
168
        if (!ret)
 
169
                return NULL;
 
170
        __bencode_list_init(ret);
 
171
        return ret;
 
172
}
 
173
 
 
174
static void __bencode_container_add(bencode_item_t *parent, bencode_item_t *child) {
 
175
        if (!parent)
 
176
                return;
 
177
        if (!child)
 
178
                return;
 
179
 
 
180
        assert(child->parent == NULL);
 
181
        assert(child->sibling == NULL);
 
182
 
 
183
        child->parent = parent;
 
184
        if (parent->last_child)
 
185
                parent->last_child->sibling = child;
 
186
        parent->last_child = child;
 
187
        if (!parent->child)
 
188
                parent->child = child;
 
189
 
 
190
        while (parent) {
 
191
                parent->iov_cnt += child->iov_cnt;
 
192
                parent->str_len += child->str_len;
 
193
                parent = parent->parent;
 
194
        }
 
195
}
 
196
 
 
197
static bencode_item_t *__bencode_string_alloc(bencode_buffer_t *buf, const void *base,
 
198
                int str_len, int iov_len, int iov_cnt, bencode_type_t type)
 
199
{
 
200
        bencode_item_t *ret;
 
201
        int len_len;
 
202
 
 
203
        assert((str_len <= 99999) && (str_len >= 0));
 
204
        ret = __bencode_item_alloc(buf, 7);
 
205
        if (!ret)
 
206
                return NULL;
 
207
        len_len = sprintf(ret->__buf, "%d:", str_len);
 
208
 
 
209
        ret->type = type;
 
210
        ret->iov[0].iov_base = ret->__buf;
 
211
        ret->iov[0].iov_len = len_len;
 
212
        ret->iov[1].iov_base = (void *) base;
 
213
        ret->iov[1].iov_len = iov_len;
 
214
        ret->iov_cnt = iov_cnt + 1;
 
215
        ret->str_len = len_len + str_len;
 
216
 
 
217
        return ret;
 
218
}
 
219
 
 
220
bencode_item_t *bencode_string_len_dup(bencode_buffer_t *buf, const char *s, int len) {
 
221
        char *sd = __bencode_alloc(buf, len);
 
222
        if (!sd)
 
223
                return NULL;
 
224
        memcpy(sd, s, len);
 
225
        return bencode_string_len(buf, sd, len);
 
226
}
 
227
 
 
228
bencode_item_t *bencode_string_len(bencode_buffer_t *buf, const char *s, int len) {
 
229
        return __bencode_string_alloc(buf, s, len, len, 1, BENCODE_STRING);
 
230
}
 
231
 
 
232
bencode_item_t *bencode_string_iovec(bencode_buffer_t *buf, const struct iovec *iov, int iov_cnt, int str_len) {
 
233
        int i;
 
234
 
 
235
        if (iov_cnt < 0)
 
236
                return NULL;
 
237
        if (str_len < 0) {
 
238
                str_len = 0;
 
239
                for (i = 0; i < iov_cnt; i++)
 
240
                        str_len += iov[i].iov_len;
 
241
        }
 
242
 
 
243
        return __bencode_string_alloc(buf, iov, str_len, iov_cnt, iov_cnt, BENCODE_IOVEC);
 
244
}
 
245
 
 
246
bencode_item_t *bencode_integer(bencode_buffer_t *buf, long long int i) {
 
247
        bencode_item_t *ret;
 
248
        int alen, rlen;
 
249
 
 
250
        alen = 8;
 
251
        while (1) {
 
252
                ret = __bencode_item_alloc(buf, alen + 3);
 
253
                if (!ret)
 
254
                        return NULL;
 
255
                rlen = snprintf(ret->__buf, alen, "i%llde", i);
 
256
                if (rlen < alen)
 
257
                        break;
 
258
                alen <<= 1;
 
259
        }
 
260
 
 
261
        ret->type = BENCODE_INTEGER;
 
262
        ret->iov[0].iov_base = ret->__buf;
 
263
        ret->iov[0].iov_len = rlen;
 
264
        ret->iov[1].iov_base = NULL;
 
265
        ret->iov[1].iov_len = 0;
 
266
        ret->iov_cnt = 1;
 
267
        ret->str_len = rlen;
 
268
 
 
269
        return ret;
 
270
}
 
271
 
 
272
bencode_item_t *bencode_dictionary_add_len(bencode_item_t *dict, const char *key, int keylen, bencode_item_t *val) {
 
273
        bencode_item_t *str;
 
274
 
 
275
        if (!dict || !val)
 
276
                return NULL;
 
277
        assert(dict->type == BENCODE_DICTIONARY);
 
278
 
 
279
        str = bencode_string_len(dict->buffer, key, keylen);
 
280
        if (!str)
 
281
                return NULL;
 
282
        __bencode_container_add(dict, str);
 
283
        __bencode_container_add(dict, val);
 
284
        return val;
 
285
}
 
286
 
 
287
bencode_item_t *bencode_list_add(bencode_item_t *list, bencode_item_t *item) {
 
288
        if (!list || !item)
 
289
                return NULL;
 
290
        assert(list->type == BENCODE_LIST);
 
291
        __bencode_container_add(list, item);
 
292
        return item;
 
293
}
 
294
 
 
295
static int __bencode_iovec_cpy(struct iovec *out, const struct iovec *in, int num) {
 
296
        memcpy(out, in, num * sizeof(*out));
 
297
        return num;
 
298
}
 
299
 
 
300
static int __bencode_str_cpy(char *out, const struct iovec *in, int num) {
 
301
        char *orig = out;
 
302
 
 
303
        while (--num >= 0) {
 
304
                memcpy(out, in->iov_base, in->iov_len);
 
305
                out += in->iov_len;
 
306
                in++;
 
307
        }
 
308
        return out - orig;
 
309
}
 
310
 
 
311
static int __bencode_iovec_dump(struct iovec *out, bencode_item_t *item) {
 
312
        bencode_item_t *child;
 
313
        struct iovec *orig = out;
 
314
 
 
315
        assert(item->iov[0].iov_base != NULL);
 
316
        out += __bencode_iovec_cpy(out, &item->iov[0], 1);
 
317
 
 
318
        child = item->child;
 
319
        while (child) {
 
320
                out += __bencode_iovec_dump(out, child);
 
321
                child = child->sibling;
 
322
        }
 
323
 
 
324
        if (item->type == BENCODE_IOVEC)
 
325
                out += __bencode_iovec_cpy(out, item->iov[1].iov_base, item->iov[1].iov_len);
 
326
        else if (item->iov[1].iov_base)
 
327
                out += __bencode_iovec_cpy(out, &item->iov[1], 1);
 
328
 
 
329
        assert((out - orig) == item->iov_cnt);
 
330
        return item->iov_cnt;
 
331
}
 
332
 
 
333
static int __bencode_str_dump(char *out, bencode_item_t *item) {
 
334
        char *orig = out;
 
335
        bencode_item_t *child;
 
336
 
 
337
        assert(item->iov[0].iov_base != NULL);
 
338
        out += __bencode_str_cpy(out, &item->iov[0], 1);
 
339
 
 
340
        child = item->child;
 
341
        while (child) {
 
342
                out += __bencode_str_dump(out, child);
 
343
                child = child->sibling;
 
344
        }
 
345
 
 
346
        if (item->type == BENCODE_IOVEC)
 
347
                out += __bencode_str_cpy(out, item->iov[1].iov_base, item->iov[1].iov_len);
 
348
        else if (item->iov[1].iov_base)
 
349
                out += __bencode_str_cpy(out, &item->iov[1], 1);
 
350
 
 
351
        assert((out - orig) == item->str_len);
 
352
        *out = '\0';
 
353
        return item->str_len;
 
354
}
 
355
 
 
356
struct iovec *bencode_iovec(bencode_item_t *root, int *cnt, unsigned int head, unsigned int tail) {
 
357
        struct iovec *ret;
 
358
 
 
359
        if (!root)
 
360
                return NULL;
 
361
        assert(cnt != NULL);
 
362
        assert(root->iov_cnt > 0);
 
363
 
 
364
        ret = __bencode_alloc(root->buffer, sizeof(*ret) * (root->iov_cnt + head + tail));
 
365
        if (!ret)
 
366
                return NULL;
 
367
        *cnt = __bencode_iovec_dump(ret + head, root);
 
368
        return ret;
 
369
}
 
370
 
 
371
char *bencode_collapse(bencode_item_t *root, int *len) {
 
372
        char *ret;
 
373
        int l;
 
374
 
 
375
        if (!root)
 
376
                return NULL;
 
377
        assert(root->str_len > 0);
 
378
 
 
379
        ret = __bencode_alloc(root->buffer, root->str_len + 1);
 
380
        if (!ret)
 
381
                return NULL;
 
382
        l = __bencode_str_dump(ret, root);
 
383
        if (len)
 
384
                *len = l;
 
385
        return ret;
 
386
}
 
387
 
 
388
char *bencode_collapse_dup(bencode_item_t *root, int *len) {
 
389
        char *ret;
 
390
        int l;
 
391
 
 
392
        if (!root)
 
393
                return NULL;
 
394
        assert(root->str_len > 0);
 
395
 
 
396
        ret = BENCODE_MALLOC(root->str_len + 1);
 
397
        if (!ret)
 
398
                return NULL;
 
399
 
 
400
        l = __bencode_str_dump(ret, root);
 
401
        if (len)
 
402
                *len = l;
 
403
        return ret;
 
404
}
 
405
 
 
406
static unsigned int __bencode_hash_str_len(const unsigned char *s, int len) {
 
407
        unsigned long *ul;
 
408
        unsigned int *ui;
 
409
        unsigned short *us;
 
410
 
 
411
        if (len >= sizeof(*ul)) {
 
412
                ul = (void *) s;
 
413
                return *ul % BENCODE_HASH_BUCKETS;
 
414
        }
 
415
        if (len >= sizeof(*ui)) {
 
416
                ui = (void *) s;
 
417
                return *ui % BENCODE_HASH_BUCKETS;
 
418
        }
 
419
        if (len >= sizeof(*us)) {
 
420
                us = (void *) s;
 
421
                return *us % BENCODE_HASH_BUCKETS;
 
422
        }
 
423
        if (len >= sizeof(*s))
 
424
                return *s % BENCODE_HASH_BUCKETS;
 
425
 
 
426
        return 0;
 
427
}
 
428
 
 
429
static unsigned int __bencode_hash_str(bencode_item_t *str) {
 
430
        assert(str->type == BENCODE_STRING);
 
431
        return __bencode_hash_str_len(str->iov[1].iov_base, str->iov[1].iov_len);
 
432
}
 
433
 
 
434
static void __bencode_hash_insert(bencode_item_t *key, struct __bencode_hash *hash) {
 
435
        unsigned int bucket, i;
 
436
 
 
437
        i = bucket = __bencode_hash_str(key);
 
438
 
 
439
        while (1) {
 
440
                if (!hash->buckets[i]) {
 
441
                        hash->buckets[i] = key;
 
442
                        break;
 
443
                }
 
444
                i++;
 
445
                if (i >= BENCODE_HASH_BUCKETS)
 
446
                        i = 0;
 
447
                if (i == bucket)
 
448
                        break;
 
449
        }
 
450
}
 
451
 
 
452
static bencode_item_t *__bencode_decode_dictionary(bencode_buffer_t *buf, const char *s, const char *end) {
 
453
        bencode_item_t *ret, *key, *value;
 
454
        struct __bencode_hash *hash;
 
455
 
 
456
        if (*s != 'd')
 
457
                return NULL;
 
458
        s++;
 
459
 
 
460
        ret = __bencode_item_alloc(buf, sizeof(*hash));
 
461
        if (!ret)
 
462
                return NULL;
 
463
        __bencode_dictionary_init(ret);
 
464
        ret->value = 1;
 
465
        hash = (void *) ret->__buf;
 
466
        memset(hash, 0, sizeof(*hash));
 
467
 
 
468
        while (s < end) {
 
469
                key = __bencode_decode(buf, s, end);
 
470
                if (!key)
 
471
                        return NULL;
 
472
                s += key->str_len;
 
473
                if (key->type == BENCODE_END_MARKER)
 
474
                        break;
 
475
                if (key->type != BENCODE_STRING)
 
476
                        return NULL;
 
477
                __bencode_container_add(ret, key);
 
478
 
 
479
                if (s >= end)
 
480
                        return NULL;
 
481
                value = __bencode_decode(buf, s, end);
 
482
                if (!value)
 
483
                        return NULL;
 
484
                s += value->str_len;
 
485
                if (value->type == BENCODE_END_MARKER)
 
486
                        return NULL;
 
487
                __bencode_container_add(ret, value);
 
488
 
 
489
                __bencode_hash_insert(key, hash);
 
490
        }
 
491
 
 
492
        return ret;
 
493
}
 
494
 
 
495
static bencode_item_t *__bencode_decode_list(bencode_buffer_t *buf, const char *s, const char *end) {
 
496
        bencode_item_t *ret, *item;
 
497
 
 
498
        if (*s != 'l')
 
499
                return NULL;
 
500
        s++;
 
501
 
 
502
        ret = __bencode_item_alloc(buf, 0);
 
503
        if (!ret)
 
504
                return NULL;
 
505
        __bencode_list_init(ret);
 
506
 
 
507
        while (s < end) {
 
508
                item = __bencode_decode(buf, s, end);
 
509
                if (!item)
 
510
                        return NULL;
 
511
                s += item->str_len;
 
512
                if (item->type == BENCODE_END_MARKER)
 
513
                        break;
 
514
                __bencode_container_add(ret, item);
 
515
        }
 
516
 
 
517
        return ret;
 
518
}
 
519
 
 
520
static bencode_item_t *__bencode_decode_integer(bencode_buffer_t *buf, const char *s, const char *end) {
 
521
        long long int i;
 
522
        const char *orig = s;
 
523
        char *convend;
 
524
        bencode_item_t *ret;
 
525
 
 
526
        if (*s != 'i')
 
527
                return NULL;
 
528
        s++;
 
529
 
 
530
        if (s >= end)
 
531
                return NULL;
 
532
 
 
533
        if (*s == '0') {
 
534
                i = 0;
 
535
                s++;
 
536
                goto done;
 
537
        }
 
538
 
 
539
        i = strtoll(s, &convend, 10);
 
540
        if (convend == s)
 
541
                return NULL;
 
542
        s += (convend - s);
 
543
 
 
544
done:
 
545
        if (s >= end)
 
546
                return NULL;
 
547
        if (*s != 'e')
 
548
                return NULL;
 
549
        s++;
 
550
 
 
551
        ret = __bencode_item_alloc(buf, 0);
 
552
        if (!ret)
 
553
                return NULL;
 
554
        ret->type = BENCODE_INTEGER;
 
555
        ret->iov[0].iov_base = (void *) orig;
 
556
        ret->iov[0].iov_len = s - orig;
 
557
        ret->iov[1].iov_base = NULL;
 
558
        ret->iov[1].iov_len = 0;
 
559
        ret->iov_cnt = 1;
 
560
        ret->str_len = s - orig;
 
561
        ret->value = i;
 
562
 
 
563
        return ret;
 
564
}
 
565
 
 
566
static bencode_item_t *__bencode_decode_string(bencode_buffer_t *buf, const char *s, const char *end) {
 
567
        unsigned long int sl;
 
568
        char *convend;
 
569
        const char *orig = s;
 
570
        bencode_item_t *ret;
 
571
 
 
572
        if (*s == '0') {
 
573
                sl = 0;
 
574
                s++;
 
575
                goto colon;
 
576
        }
 
577
 
 
578
        sl = strtoul(s, &convend, 10);
 
579
        if (convend == s)
 
580
                return NULL;
 
581
        s += (convend - s);
 
582
 
 
583
colon:
 
584
        if (s >= end)
 
585
                return NULL;
 
586
        if (*s != ':')
 
587
                return NULL;
 
588
        s++;
 
589
 
 
590
        if (s + sl > end)
 
591
                return NULL;
 
592
 
 
593
        ret = __bencode_item_alloc(buf, 0);
 
594
        if (!ret)
 
595
                return NULL;
 
596
        ret->type = BENCODE_STRING;
 
597
        ret->iov[0].iov_base = (void *) orig;
 
598
        ret->iov[0].iov_len = s - orig;
 
599
        ret->iov[1].iov_base = (void *) s;
 
600
        ret->iov[1].iov_len = sl;
 
601
        ret->iov_cnt = 2;
 
602
        ret->str_len = s - orig + sl;
 
603
 
 
604
        return ret;
 
605
}
 
606
 
 
607
static bencode_item_t *__bencode_decode(bencode_buffer_t *buf, const char *s, const char *end) {
 
608
        if (s >= end)
 
609
                return NULL;
 
610
 
 
611
        switch (*s) {
 
612
                case 'd':
 
613
                        return __bencode_decode_dictionary(buf, s, end);
 
614
                case 'l':
 
615
                        return __bencode_decode_list(buf, s, end);
 
616
                case 'i':
 
617
                        return __bencode_decode_integer(buf, s, end);
 
618
                case 'e':
 
619
                        return &__bencode_end_marker;
 
620
                case '0':
 
621
                case '1':
 
622
                case '2':
 
623
                case '3':
 
624
                case '4':
 
625
                case '5':
 
626
                case '6':
 
627
                case '7':
 
628
                case '8':
 
629
                case '9':
 
630
                        return __bencode_decode_string(buf, s, end);
 
631
                default:
 
632
                        return NULL;
 
633
        }
 
634
}
 
635
 
 
636
bencode_item_t *bencode_decode(bencode_buffer_t *buf, const char *s, int len) {
 
637
        assert(s != NULL);
 
638
        return __bencode_decode(buf, s, s + len);
 
639
}
 
640
 
 
641
 
 
642
static int __bencode_dictionary_key_match(bencode_item_t *key, const char *keystr, int keylen) {
 
643
        assert(key->type == BENCODE_STRING);
 
644
 
 
645
        if (keylen != key->iov[1].iov_len)
 
646
                return 0;
 
647
        if (memcmp(keystr, key->iov[1].iov_base, keylen))
 
648
                return 0;
 
649
 
 
650
        return 1;
 
651
}
 
652
 
 
653
bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *keystr, int keylen) {
 
654
        bencode_item_t *key;
 
655
        unsigned int bucket, i;
 
656
        struct __bencode_hash *hash;
 
657
 
 
658
        if (!dict)
 
659
                return NULL;
 
660
        if (dict->type != BENCODE_DICTIONARY)
 
661
                return NULL;
 
662
 
 
663
        /* try hash lookup first if possible */
 
664
        if (dict->value == 1) {
 
665
                hash = (void *) dict->__buf;
 
666
                i = bucket = __bencode_hash_str_len((const unsigned char *) keystr, keylen);
 
667
                while (1) {
 
668
                        key = hash->buckets[i];
 
669
                        if (!key)
 
670
                                return NULL; /* would be there, but isn't */
 
671
                        assert(key->sibling != NULL);
 
672
                        if (__bencode_dictionary_key_match(key, keystr, keylen))
 
673
                                return key->sibling;
 
674
                        i++;
 
675
                        if (i >= BENCODE_HASH_BUCKETS)
 
676
                                i = 0;
 
677
                        if (i == bucket)
 
678
                                break; /* fall back to regular lookup */
 
679
                }
 
680
        }
 
681
 
 
682
        for (key = dict->child; key; key = key->sibling->sibling) {
 
683
                assert(key->sibling != NULL);
 
684
                if (__bencode_dictionary_key_match(key, keystr, keylen))
 
685
                        return key->sibling;
 
686
        }
 
687
 
 
688
        return NULL;
 
689
}
 
690
 
 
691
void bencode_buffer_destroy_add(bencode_buffer_t *buf, free_func_t func, void *p) {
 
692
        struct __bencode_free_list *li;
 
693
 
 
694
        if (!p)
 
695
                return;
 
696
        li = __bencode_alloc(buf, sizeof(*li));
 
697
        if (!li)
 
698
                return;
 
699
        li->ptr = p;
 
700
        li->func = func;
 
701
        li->next = buf->free_list;
 
702
        buf->free_list = li;
 
703
}