diff --git a/daemon/bencode.c b/daemon/bencode.c index f97d40582..7f0bfee4a 100644 --- a/daemon/bencode.c +++ b/daemon/bencode.c @@ -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; diff --git a/daemon/bencode.h b/daemon/bencode.h index ac3d5a2f5..dff73d0d8 100644 --- a/daemon/bencode.h +++ b/daemon/bencode.h @@ -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 diff --git a/daemon/call.c b/daemon/call.c index 4d56030b3..fa6a07269 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -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)) {