Browse Source

fix the silly thing about bencoded lists being backwards

git.mgm/mediaproxy-ng/2.2
Richard Fuchs 13 years ago
parent
commit
589c271d52
3 changed files with 66 additions and 93 deletions
  1. +53
    -79
      daemon/bencode.c
  2. +9
    -10
      daemon/bencode.h
  3. +4
    -4
      daemon/call.c

+ 53
- 79
daemon/bencode.c View File

@ -47,7 +47,7 @@ static bencode_item_t *__bencode_decode(bencode_buffer_t *buf, const char *s, co
static void __bencode_item_init(bencode_item_t *item) {
item->parent = item->child = item->sibling = NULL;
item->last_child = item->parent = item->child = item->sibling = NULL;
}
static void __bencode_container_init(bencode_item_t *cont) {
@ -179,8 +179,11 @@ static void __bencode_container_add(bencode_item_t *parent, bencode_item_t *chil
assert(child->sibling == NULL);
child->parent = parent;
child->sibling = parent->child;
parent->child = child;
if (parent->last_child)
parent->last_child->sibling = child;
parent->last_child = child;
if (!parent->child)
parent->child = child;
while (parent) {
parent->iov_cnt += child->iov_cnt;
@ -288,91 +291,66 @@ bencode_item_t *bencode_list_add(bencode_item_t *list, bencode_item_t *item) {
}
static int __bencode_iovec_cpy(struct iovec *out, const struct iovec *in, int num) {
out -= num;
memcpy(out, in, num * sizeof(*out));
return num;
}
static int __bencode_iovec_dump_rev(struct iovec *out, bencode_item_t *item) {
static int __bencode_str_cpy(char *out, const struct iovec *in, int num) {
char *orig = out;
while (--num >= 0) {
memcpy(out, in->iov_base, in->iov_len);
out += in->iov_len;
in++;
}
return out - orig;
}
static int __bencode_iovec_dump(struct iovec *out, bencode_item_t *item) {
bencode_item_t *child;
struct iovec *orig = out;
if (item->type == BENCODE_IOVEC)
out -= __bencode_iovec_cpy(out, item->iov[1].iov_base, item->iov[1].iov_len);
else if (item->iov[1].iov_base)
out -= __bencode_iovec_cpy(out, &item->iov[1], 1);
assert(item->iov[0].iov_base != NULL);
out += __bencode_iovec_cpy(out, &item->iov[0], 1);
child = item->child;
while (child) {
out -= __bencode_iovec_dump_rev(out, child);
out += __bencode_iovec_dump(out, child);
child = child->sibling;
}
assert(item->iov[0].iov_base != NULL);
out -= __bencode_iovec_cpy(out, &item->iov[0], 1);
if (item->type == BENCODE_IOVEC)
out += __bencode_iovec_cpy(out, item->iov[1].iov_base, item->iov[1].iov_len);
else if (item->iov[1].iov_base)
out += __bencode_iovec_cpy(out, &item->iov[1], 1);
assert((orig - out) == item->iov_cnt);
assert((out - orig) == item->iov_cnt);
return item->iov_cnt;
}
static int __bencode_str_cpy(char *out, const struct iovec *in, int num) {
static int __bencode_str_dump(char *out, bencode_item_t *item) {
char *orig = out;
in += num;
while (--num >= 0) {
in--;
out -= in->iov_len;
memcpy(out, in->iov_base, in->iov_len);
}
return orig - out;
}
static int __bencode_str_dump_rev(char *out, bencode_item_t *item) {
bencode_item_t *child;
char *orig = out;
if (item->type == BENCODE_IOVEC)
out -= __bencode_str_cpy(out, item->iov[1].iov_base, item->iov[1].iov_len);
else if (item->iov[1].iov_base)
out -= __bencode_str_cpy(out, &item->iov[1], 1);
assert(item->iov[0].iov_base != NULL);
out += __bencode_str_cpy(out, &item->iov[0], 1);
child = item->child;
while (child) {
out -= __bencode_str_dump_rev(out, child);
out += __bencode_str_dump(out, child);
child = child->sibling;
}
assert(item->iov[0].iov_base != NULL);
out -= __bencode_str_cpy(out, &item->iov[0], 1);
if (item->type == BENCODE_IOVEC)
out += __bencode_str_cpy(out, item->iov[1].iov_base, item->iov[1].iov_len);
else if (item->iov[1].iov_base)
out += __bencode_str_cpy(out, &item->iov[1], 1);
assert((orig - out) == item->str_len);
assert((out - orig) == item->str_len);
*out = '\0';
return item->str_len;
}
static int __bencode_iovec_dump(struct iovec *out, bencode_item_t *item) {
int len;
/* sibling lists are built in reverse, so dump everything
out backwards, end to start */
out += item->iov_cnt;
len = __bencode_iovec_dump_rev(out, item);
assert(len == item->iov_cnt);
return len;
}
static int __bencode_str_dump(char *out, bencode_item_t *item) {
int len;
char *orig = out;
/* sibling lists are built in reverse, so dump everything
out backwards, end to start */
out += item->str_len;
len = __bencode_str_dump_rev(out, item);
assert(len == item->str_len);
orig[len] = '\0';
return len;
}
struct iovec *bencode_iovec(bencode_item_t *root, int *cnt, unsigned int head, unsigned int tail) {
struct iovec *ret;
@ -451,14 +429,14 @@ static unsigned int __bencode_hash_str(bencode_item_t *str) {
return __bencode_hash_str_len(str->iov[1].iov_base, str->iov[1].iov_len);
}
static void __bencode_hash_insert(bencode_item_t *key, bencode_item_t *value, struct __bencode_hash *hash) {
static void __bencode_hash_insert(bencode_item_t *key, struct __bencode_hash *hash) {
unsigned int bucket, i;
i = bucket = __bencode_hash_str(key);
while (1) {
if (!hash->buckets[i]) {
hash->buckets[i] = value;
hash->buckets[i] = key;
break;
}
i++;
@ -506,7 +484,7 @@ static bencode_item_t *__bencode_decode_dictionary(bencode_buffer_t *buf, const
return NULL;
__bencode_container_add(ret, value);
__bencode_hash_insert(key, value, hash);
__bencode_hash_insert(key, hash);
}
return ret;
@ -659,23 +637,19 @@ bencode_item_t *bencode_decode(bencode_buffer_t *buf, const char *s, int len) {
}
static bencode_item_t *__bencode_dictionary_key_test(bencode_item_t *val, const char *keystr, int keylen) {
bencode_item_t *key;
key = val->sibling;
assert(key != NULL);
static int __bencode_dictionary_key_match(bencode_item_t *key, const char *keystr, int keylen) {
assert(key->type == BENCODE_STRING);
if (keylen != key->iov[1].iov_len)
return key;
return 0;
if (memcmp(keystr, key->iov[1].iov_base, keylen))
return key;
return 0;
return NULL;
return 1;
}
bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *keystr, int keylen) {
bencode_item_t *key, *val;
bencode_item_t *key;
unsigned int bucket, i;
struct __bencode_hash *hash;
@ -689,12 +663,12 @@ bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *key
hash = (void *) dict->__buf;
i = bucket = __bencode_hash_str_len((const unsigned char *) keystr, keylen);
while (1) {
val = hash->buckets[i];
if (!val)
return NULL; /* would be there, but isn't */
key = __bencode_dictionary_key_test(val, keystr, keylen);
key = hash->buckets[i];
if (!key)
return val;
return NULL; /* would be there, but isn't */
assert(key->sibling != NULL);
if (__bencode_dictionary_key_match(key, keystr, keylen))
return key->sibling;
i++;
if (i >= BENCODE_HASH_BUCKETS)
i = 0;
@ -703,10 +677,10 @@ bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *key
}
}
for (val = dict->child; val; val = key->sibling) {
key = __bencode_dictionary_key_test(val, keystr, keylen);
if (!key)
return val;
for (key = dict->child; key; key = key->sibling->sibling) {
assert(key->sibling != NULL);
if (__bencode_dictionary_key_match(key, keystr, keylen))
return key->sibling;
}
return NULL;


+ 9
- 10
daemon/bencode.h View File

@ -48,7 +48,7 @@ struct bencode_item {
unsigned int iov_cnt;
unsigned int str_len; /* length of the whole ENCODED object. NOT the length of a byte string */
long long int value; /* when decoding an integer, contains the value; otherwise used internally */
bencode_item_t *parent, *child, *sibling;
bencode_item_t *parent, *child, *last_child, *sibling;
bencode_buffer_t *buffer;
char __buf[0];
};
@ -257,17 +257,16 @@ char *bencode_collapse_dup(bencode_item_t *root, int *len);
*
* The document tree can be traversed through the ->child and ->sibling pointers in each object. The
* ->child pointer will be NULL for string and integer objects, as they don't contain other objects.
* For lists and dictionaries, ->child will be a pointer to the LAST contained object. This last
* contained object's ->sibling pointer will point to the last-but-one contained object of the list
* or the dictionary, and so on. The FIRST contained element of a list of dictionary will have a
* For lists and dictionaries, ->child will be a pointer to the first contained object. This first
* contained object's ->sibling pointer will point to the next (second) contained object of the list
* or the dictionary, and so on. The last contained element of a list of dictionary will have a
* NULL ->sibling pointer.
*
* Lists are built in reverse and so traversing a list by following the ->sibling pointers will
* traverse all the elements in reverse as well. This includes the ordering of key/value pairs in
* dictionary: The first element in the list (where ->child points to) will be the VALUE of the LAST
* key/value pair. The next element (following one ->sibling) will be the KEY of the LAST key/value
* pair (guaranteed to be a string and guaranteed to be present). Following another ->sibling will
* point to the VALUE of the last-but-one key/value pair, and so on.
* Dictionaries are like lists with ordered key/value pairs. When traversing dictionaries like
* lists, the following applies: The first element in the list (where ->child points to) will be the
* key of the first key/value pair (guaranteed to be a string and guaranteed to be present). The
* next element (following one ->sibling) will be the value of the first key/value pair. Following
* another ->sibling will point to the key of the next (second) key/value pair, and so on.
*
* However, to access children objects of dictionaries, the special functions following the naming
* scheme bencode_dictionary_get_* below should be used. They perform key lookup through a simple


+ 4
- 4
daemon/call.c View File

@ -2285,15 +2285,15 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, GQueue *streams, ben
for (gl = streams->head; gl; gl = gl->next) {
si = gl->data;
si->direction[0] = dirs[1]; /* bencode list is traversed backwards */
si->direction[1] = dirs[0];
si->direction[0] = dirs[0];
si->direction[1] = dirs[1];
}
}
list = bencode_dictionary_get_expect(input, "received-from", BENCODE_LIST);
if (list && (it = list->child)) {
bencode_get_str(it, &out->received_from_address);
bencode_get_str(it->sibling, &out->received_from_family);
bencode_get_str(it, &out->received_from_family);
bencode_get_str(it->sibling, &out->received_from_address);
}
if (bencode_dictionary_get_str(input, "ICE", &s)) {


Loading…
Cancel
Save