bencode.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. #ifndef _BENCODE_H_
  2. #define _BENCODE_H_
  3. #include <sys/uio.h>
  4. #include <string.h>
  5. #if defined(SHM_MEM) || defined(PKG_MALLOC) || defined(pkg_malloc)
  6. /* kamailio */
  7. # include "../../mem/mem.h"
  8. # include "../../str.h"
  9. # ifndef BENCODE_MALLOC
  10. # define BENCODE_MALLOC pkg_malloc
  11. # define BENCODE_FREE pkg_free
  12. # endif
  13. # define INLINE static inline
  14. #else
  15. /* rtpengine */
  16. # include "compat.h"
  17. # include "str.h"
  18. # ifndef BENCODE_MALLOC
  19. # define BENCODE_MALLOC malloc
  20. # define BENCODE_FREE free
  21. # endif
  22. #endif
  23. struct bencode_buffer;
  24. enum bencode_type;
  25. struct bencode_item;
  26. struct __bencode_buffer_piece;
  27. struct __bencode_free_list;
  28. typedef enum bencode_type bencode_type_t;
  29. typedef struct bencode_buffer bencode_buffer_t;
  30. typedef struct bencode_item bencode_item_t;
  31. typedef void (*free_func_t)(void *);
  32. enum bencode_type {
  33. BENCODE_INVALID = 0,
  34. BENCODE_STRING, /* byte string */
  35. BENCODE_INTEGER, /* long long int */
  36. BENCODE_LIST, /* flat list of other objects */
  37. BENCODE_DICTIONARY, /* dictionary of key/values pairs. keys are always strings */
  38. BENCODE_IOVEC, /* special case of a string, built through bencode_string_iovec() */
  39. BENCODE_END_MARKER, /* used internally only */
  40. };
  41. struct bencode_item {
  42. bencode_type_t type;
  43. struct iovec iov[2]; /* when decoding, iov[1] contains the contents of a string object */
  44. unsigned int iov_cnt;
  45. unsigned int str_len; /* length of the whole ENCODED object. NOT the length of a byte string */
  46. long long int value; /* when decoding an integer, contains the value; otherwise used internally */
  47. bencode_item_t *parent, *child, *last_child, *sibling;
  48. bencode_buffer_t *buffer;
  49. char __buf[0];
  50. };
  51. struct bencode_buffer {
  52. struct __bencode_buffer_piece *pieces;
  53. struct __bencode_free_list *free_list;
  54. int error:1; /* set to !0 if allocation failed at any point */
  55. };
  56. /* to embed BENCODE_STRING objects into printf-like functions */
  57. #define BENCODE_FORMAT "%.*s"
  58. #define BENCODE_FMT(b) (int) (b)->iov[1].iov_len, (char *) (b)->iov[1].iov_base
  59. /*** INIT & DESTROY ***/
  60. /* Initializes a bencode_buffer_t object. This object is used to group together all memory allocations
  61. * made when encoding or decoding. Its memory usage is always growing, until it is freed, at which point
  62. * all objects created through it become invalid. The actual object must be allocated separately, for
  63. * example by being put on the stack.
  64. * Returns 0 on success or -1 on failure (if no memory could be allocated). */
  65. int bencode_buffer_init(bencode_buffer_t *buf);
  66. /* Allocate a piece of memory from the given buffer object */
  67. void *bencode_buffer_alloc(bencode_buffer_t *, unsigned int);
  68. /* Destroys a previously initialized bencode_buffer_t object. All memory used by the object is freed
  69. * and all objects created through it become invalid. */
  70. void bencode_buffer_free(bencode_buffer_t *buf);
  71. /* Creates a new empty dictionary object. Memory will be allocated from the bencode_buffer_t object.
  72. * Returns NULL if no memory could be allocated. */
  73. bencode_item_t *bencode_dictionary(bencode_buffer_t *buf);
  74. /* Creates a new empty list object. Memory will be allocated from the bencode_buffer_t object.
  75. * Returns NULL if no memory could be allocated. */
  76. bencode_item_t *bencode_list(bencode_buffer_t *buf);
  77. /* Adds a pointer to the bencode_buffer_t object's internal free list. When the bencode_buffer_t
  78. * object is destroyed, the specified function will be called on this pointer. */
  79. void bencode_buffer_destroy_add(bencode_buffer_t *buf, free_func_t, void *);
  80. /* Returns the buffer associated with an item, or NULL if pointer given is NULL */
  81. INLINE bencode_buffer_t *bencode_item_buffer(bencode_item_t *);
  82. /*** DICTIONARY BUILDING ***/
  83. /* Adds a new key/value pair to a dictionary. Memory will be allocated from the same bencode_buffer_t
  84. * object as the dictionary was allocated from. Returns NULL if no memory could be allocated, otherwise
  85. * returns "val".
  86. * The function does not check whether the key being added is already present in the dictionary.
  87. * Also, the function does not reorder keys into lexicographical order; keys will be encoded in
  88. * the same order as they've been added. The key must a null-terminated string.
  89. * The value to be added must not have been previously linked into any other dictionary or list. */
  90. INLINE bencode_item_t *bencode_dictionary_add(bencode_item_t *dict, const char *key, bencode_item_t *val);
  91. INLINE bencode_item_t *bencode_dictionary_str_add(bencode_item_t *dict, const str *key, bencode_item_t *val);
  92. /* Identical to bencode_dictionary_add() but doesn't require the key string to be null-terminated */
  93. bencode_item_t *bencode_dictionary_add_len(bencode_item_t *dict, const char *key, int keylen, bencode_item_t *val);
  94. /* Convenience function to add a string value to a dictionary, possibly duplicated into the
  95. * bencode_buffer_t object. */
  96. INLINE bencode_item_t *bencode_dictionary_add_string(bencode_item_t *dict, const char *key, const char *val);
  97. INLINE bencode_item_t *bencode_dictionary_add_string_dup(bencode_item_t *dict, const char *key, const char *val);
  98. /* Ditto, but for a "str" object */
  99. INLINE bencode_item_t *bencode_dictionary_add_str(bencode_item_t *dict, const char *key, const str *val);
  100. INLINE bencode_item_t *bencode_dictionary_str_add_str(bencode_item_t *dict, const str *key, const str *val);
  101. INLINE bencode_item_t *bencode_dictionary_add_str_dup(bencode_item_t *dict, const char *key, const str *val);
  102. /* Ditto, but adds a string created through an iovec array to the dictionary. See
  103. * bencode_string_iovec(). */
  104. INLINE bencode_item_t *bencode_dictionary_add_iovec(bencode_item_t *dict, const char *key,
  105. const struct iovec *iov, int iov_cnt, int str_len);
  106. /* Convenience functions to add the respective (newly created) objects to a dictionary */
  107. INLINE bencode_item_t *bencode_dictionary_add_integer(bencode_item_t *dict, const char *key, long long int val);
  108. INLINE bencode_item_t *bencode_dictionary_add_dictionary(bencode_item_t *dict, const char *key);
  109. INLINE bencode_item_t *bencode_dictionary_add_list(bencode_item_t *dict, const char *key);
  110. /*** LIST BUILDING ***/
  111. /* Adds a new item to a list. Returns "item".
  112. * The item to be added must not have been previously linked into any other dictionary or list. */
  113. bencode_item_t *bencode_list_add(bencode_item_t *list, bencode_item_t *item);
  114. /* Convenience function to add the respective (newly created) objects to a list */
  115. INLINE bencode_item_t *bencode_list_add_string(bencode_item_t *list, const char *s);
  116. INLINE bencode_item_t *bencode_list_add_str(bencode_item_t *list, const str *s);
  117. INLINE bencode_item_t *bencode_list_add_list(bencode_item_t *list);
  118. INLINE bencode_item_t *bencode_list_add_dictionary(bencode_item_t *list);
  119. /*** STRING BUILDING & HANDLING ***/
  120. /* Creates a new byte-string object. The given string does not have to be null-terminated, instead
  121. * the length of the string is specified by the "len" parameter. Returns NULL if no memory could
  122. * be allocated.
  123. * Strings are not copied or duplicated, so the string pointed to by "s" must remain valid until
  124. * the complete document is finally encoded or sent out. */
  125. bencode_item_t *bencode_string_len(bencode_buffer_t *buf, const char *s, int len);
  126. /* Creates a new byte-string object. The given string must be null-terminated. Otherwise identical
  127. * to bencode_string_len(). */
  128. INLINE bencode_item_t *bencode_string(bencode_buffer_t *buf, const char *s);
  129. /* Creates a new byte-string object from a "str" object. The string does not have to be null-
  130. * terminated. */
  131. INLINE bencode_item_t *bencode_str(bencode_buffer_t *buf, const str *s);
  132. /* Identical to the above three functions, but copies the string into the bencode_buffer_t object.
  133. * Thus, the given string doesn't have to remain valid and accessible afterwards. */
  134. bencode_item_t *bencode_string_len_dup(bencode_buffer_t *buf, const char *s, int len);
  135. INLINE bencode_item_t *bencode_string_dup(bencode_buffer_t *buf, const char *s);
  136. INLINE bencode_item_t *bencode_str_dup(bencode_buffer_t *buf, const str *s);
  137. /* Creates a new byte-string object from an iovec array. The created object has different internal
  138. * semantics (not a BENCODE_STRING, but a BENCODE_IOVEC) and must not be treated like other string
  139. * objects. The array pointer and contents must still be valid and accessible when the complete
  140. * document is encoded. The full length of the string composed of the iovec array is given in the
  141. * "str_len" parameter, which can be negative, in which case the array is iterated to calculate the
  142. * length. */
  143. bencode_item_t *bencode_string_iovec(bencode_buffer_t *buf, const struct iovec *iov, int iov_cnt, int str_len);
  144. /* Convenience function to compare a string object to a regular C string. Returns 2 if object
  145. * isn't a string object, otherwise returns according to strcmp(). */
  146. INLINE int bencode_strcmp(bencode_item_t *a, const char *b);
  147. /* Converts the string object "in" into a str object "out". Returns "out" on success, or NULL on
  148. * error ("in" was NULL or not a string object). */
  149. INLINE str *bencode_get_str(bencode_item_t *in, str *out);
  150. /*** INTEGER BUILDING ***/
  151. /* Creates a new integer object. Returns NULL if no memory could be allocated. */
  152. bencode_item_t *bencode_integer(bencode_buffer_t *buf, long long int i);
  153. /*** COLLAPSING & ENCODING ***/
  154. /* Collapses and encodes the complete document structure under the "root" element (which normally
  155. * is either a dictionary or a list) into an array of "iovec" structures. This array can then be
  156. * passed to functions ala writev() or sendmsg() to output the encoded document as a whole. Memory
  157. * is allocated from the same bencode_buffer_t object as the "root" object was allocated from.
  158. * The "head" and "tail" parameters specify additional "iovec" structures that should be included
  159. * in the allocated array before or after (respectively) the iovec structures used by the encoded
  160. * document. Both parameters can be zero if no additional elements in the array are required.
  161. * Returns a pointer to the allocated array or NULL if no memory could be allocated. The number of
  162. * array elements is returned in "cnt" which must be a valid pointer to an int. This number does
  163. * not include any additional elements allocated through the "head" or "tail" parameters.
  164. *
  165. * Therefore, the contents of the returned array are:
  166. * [0 .. (head - 1)] = unused and uninitialized iovec structures
  167. * [(head) .. (head + cnt - 1)] = the encoded document
  168. * [(head + cnt) .. (head + cnt + tail - 1)] = unused and uninitialized iovec structures
  169. *
  170. * The returned array will be freed when the corresponding bencode_buffer_t object is destroyed. */
  171. struct iovec *bencode_iovec(bencode_item_t *root, int *cnt, unsigned int head, unsigned int tail);
  172. /* Similar to bencode_iovec(), but instead returns the encoded document as a null-terminated string.
  173. * Memory for the string is allocated from the same bencode_buffer_t object as the "root" object
  174. * was allocated from. If "len" is a non-NULL pointer, the length of the genrated string is returned
  175. * in *len. This is important if the encoded document contains binary data, in which case null
  176. * termination cannot be trusted. The returned string is freed when the corresponding
  177. * bencode_buffer_t object is destroyed. */
  178. char *bencode_collapse(bencode_item_t *root, int *len);
  179. /* Identical to bencode_collapse() but fills in a "str" object. Returns "out". */
  180. static str *bencode_collapse_str(bencode_item_t *root, str *out);
  181. /* Identical to bencode_collapse(), but the memory for the returned string is not allocated from
  182. * a bencode_buffer_t object, but instead using the function defined as BENCODE_MALLOC (normally
  183. * malloc() or pkg_malloc()), similar to strdup(). Using this function, the bencode_buffer_t
  184. * object can be destroyed, but the returned string remains valid and usable. */
  185. char *bencode_collapse_dup(bencode_item_t *root, int *len);
  186. /*** DECODING ***/
  187. /* Decodes an encoded document from a string into a tree of bencode_item_t objects. The string does
  188. * not need to be null-terminated, instead the length of the string is given through the "len"
  189. * parameter. Memory is allocated from the bencode_buffer_t object. Returns NULL if no memory could
  190. * be allocated or if the document could not be successfully decoded.
  191. *
  192. * The returned element is the "root" of the document tree and normally is either a list object or
  193. * a dictionary object, but can also be a single string or integer object with no other objects
  194. * underneath or besides it (no childred and no siblings). The type of the object can be determined
  195. * by its ->type property.
  196. *
  197. * The number of bytes that could successfully be decoded into an object tree can be accessed through
  198. * the root element's ->str_len property. Normally, this number should be equal to the "len" parameter
  199. * passed, in which case the full string could be decoded. If ->str_len is less than "len", then there
  200. * was additional stray byte data after the end of the encoded document.
  201. *
  202. * The document tree can be traversed through the ->child and ->sibling pointers in each object. The
  203. * ->child pointer will be NULL for string and integer objects, as they don't contain other objects.
  204. * For lists and dictionaries, ->child will be a pointer to the first contained object. This first
  205. * contained object's ->sibling pointer will point to the next (second) contained object of the list
  206. * or the dictionary, and so on. The last contained element of a list of dictionary will have a
  207. * NULL ->sibling pointer.
  208. *
  209. * Dictionaries are like lists with ordered key/value pairs. When traversing dictionaries like
  210. * lists, the following applies: The first element in the list (where ->child points to) will be the
  211. * key of the first key/value pair (guaranteed to be a string and guaranteed to be present). The
  212. * next element (following one ->sibling) will be the value of the first key/value pair. Following
  213. * another ->sibling will point to the key of the next (second) key/value pair, and so on.
  214. *
  215. * However, to access children objects of dictionaries, the special functions following the naming
  216. * scheme bencode_dictionary_get_* below should be used. They perform key lookup through a simple
  217. * hash built into the dictionary object and so perform the lookup much faster. Only dictionaries
  218. * created through a decoding process (i.e. not ones created from bencode_dictionary()) have this
  219. * property. The hash is efficient only up to a certain number of elements (BENCODE_HASH_BUCKETS
  220. * in bencode.c) contained in the dictionary. If the number of children object exceeds this number,
  221. * key lookup will be slower than simply linearily traversing the list.
  222. *
  223. * The decoding function for dictionary object does not check whether keys are unique within the
  224. * dictionary. It also does not care about lexicographical order of the keys.
  225. *
  226. * Decoded string objects will contain the raw decoded byte string in ->iov[1] (including the correct
  227. * length). Strings are NOT null-terminated. Decoded integer objects will contain the decoded value
  228. * in ->value.
  229. *
  230. * All memory is freed when the bencode_buffer_t object is destroyed.
  231. */
  232. bencode_item_t *bencode_decode(bencode_buffer_t *buf, const char *s, int len);
  233. /* Identical to bencode_decode(), but returns successfully only if the type of the decoded object match
  234. * "expect". */
  235. INLINE bencode_item_t *bencode_decode_expect(bencode_buffer_t *buf, const char *s, int len, bencode_type_t expect);
  236. /* Identical to bencode_decode_expect() but takes a "str" argument. */
  237. INLINE bencode_item_t *bencode_decode_expect_str(bencode_buffer_t *buf, const str *s, bencode_type_t expect);
  238. /*** DICTIONARY LOOKUP & EXTRACTION ***/
  239. /* Searches the given dictionary object for the given key and returns the respective value. Returns
  240. * NULL if the given object isn't a dictionary or if the key doesn't exist. The key must be a
  241. * null-terminated string. */
  242. INLINE bencode_item_t *bencode_dictionary_get(bencode_item_t *dict, const char *key);
  243. /* Identical to bencode_dictionary_get() but doesn't require the key to be null-terminated. */
  244. bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *key, int key_len);
  245. /* Identical to bencode_dictionary_get() but returns the value only if its type is a string, and
  246. * returns it as a pointer to the string itself. Returns NULL if the value is of some other type. The
  247. * returned string is NOT null-terminated. Length of the string is returned in *len, which must be a
  248. * valid pointer. The returned string will be valid until dict's bencode_buffer_t object is destroyed. */
  249. INLINE char *bencode_dictionary_get_string(bencode_item_t *dict, const char *key, int *len);
  250. /* Identical to bencode_dictionary_get_string() but fills in a "str" struct. Returns str->s, which
  251. * may be NULL. */
  252. INLINE char *bencode_dictionary_get_str(bencode_item_t *dict, const char *key, str *str);
  253. /* Looks up the given key in the dictionary and compares the corresponding value to the given
  254. * null-terminated string. Returns 2 if the key isn't found or if the value isn't a string, otherwise
  255. * returns according to strcmp(). */
  256. INLINE int bencode_dictionary_get_strcmp(bencode_item_t *dict, const char *key, const char *str);
  257. /* Identical to bencode_dictionary_get() but returns the string in a newly allocated buffer (using the
  258. * BENCODE_MALLOC function), which remains valid even after bencode_buffer_t is destroyed. */
  259. INLINE char *bencode_dictionary_get_string_dup(bencode_item_t *dict, const char *key, int *len);
  260. /* Combines bencode_dictionary_get_str() and bencode_dictionary_get_string_dup(). Fills in a "str"
  261. * struct, but copies the string into a newly allocated buffer. Returns str->s. */
  262. INLINE char *bencode_dictionary_get_str_dup(bencode_item_t *dict, const char *key, str *str);
  263. /* Identical to bencode_dictionary_get_string() but expects an integer object. The parameter "defval"
  264. * specified which value should be returned if the key is not found or if the value is not an integer. */
  265. INLINE long long int bencode_dictionary_get_integer(bencode_item_t *dict, const char *key, long long int defval);
  266. /* Identical to bencode_dictionary_get(), but returns the object only if its type matches "expect". */
  267. INLINE bencode_item_t *bencode_dictionary_get_expect(bencode_item_t *dict, const char *key, bencode_type_t expect);
  268. /**************************/
  269. INLINE bencode_buffer_t *bencode_item_buffer(bencode_item_t *i) {
  270. if (!i)
  271. return NULL;
  272. return i->buffer;
  273. }
  274. INLINE bencode_item_t *bencode_string(bencode_buffer_t *buf, const char *s) {
  275. return bencode_string_len(buf, s, strlen(s));
  276. }
  277. INLINE bencode_item_t *bencode_string_dup(bencode_buffer_t *buf, const char *s) {
  278. return bencode_string_len_dup(buf, s, strlen(s));
  279. }
  280. INLINE bencode_item_t *bencode_str(bencode_buffer_t *buf, const str *s) {
  281. return bencode_string_len(buf, s->s, s->len);
  282. }
  283. INLINE bencode_item_t *bencode_str_dup(bencode_buffer_t *buf, const str *s) {
  284. return bencode_string_len_dup(buf, s->s, s->len);
  285. }
  286. INLINE bencode_item_t *bencode_dictionary_add(bencode_item_t *dict, const char *key, bencode_item_t *val) {
  287. if (!key)
  288. return NULL;
  289. return bencode_dictionary_add_len(dict, key, strlen(key), val);
  290. }
  291. INLINE bencode_item_t *bencode_dictionary_str_add(bencode_item_t *dict, const str *key, bencode_item_t *val) {
  292. if (!key)
  293. return NULL;
  294. return bencode_dictionary_add_len(dict, key->s, key->len, val);
  295. }
  296. INLINE bencode_item_t *bencode_dictionary_add_string(bencode_item_t *dict, const char *key, const char *val) {
  297. if (!val)
  298. return NULL;
  299. return bencode_dictionary_add(dict, key, bencode_string(bencode_item_buffer(dict), val));
  300. }
  301. INLINE bencode_item_t *bencode_dictionary_add_string_dup(bencode_item_t *dict, const char *key, const char *val) {
  302. if (!val)
  303. return NULL;
  304. return bencode_dictionary_add(dict, key, bencode_string_dup(bencode_item_buffer(dict), val));
  305. }
  306. INLINE bencode_item_t *bencode_dictionary_add_str(bencode_item_t *dict, const char *key, const str *val) {
  307. if (!val)
  308. return NULL;
  309. return bencode_dictionary_add(dict, key, bencode_str(bencode_item_buffer(dict), val));
  310. }
  311. INLINE bencode_item_t *bencode_dictionary_str_add_str(bencode_item_t *dict, const str *key, const str *val) {
  312. if (!val)
  313. return NULL;
  314. return bencode_dictionary_str_add(dict, key, bencode_str(bencode_item_buffer(dict), val));
  315. }
  316. INLINE bencode_item_t *bencode_dictionary_add_str_dup(bencode_item_t *dict, const char *key, const str *val) {
  317. if (!val)
  318. return NULL;
  319. return bencode_dictionary_add(dict, key, bencode_str_dup(bencode_item_buffer(dict), val));
  320. }
  321. INLINE bencode_item_t *bencode_dictionary_add_integer(bencode_item_t *dict, const char *key, long long int val) {
  322. return bencode_dictionary_add(dict, key, bencode_integer(bencode_item_buffer(dict), val));
  323. }
  324. INLINE bencode_item_t *bencode_dictionary_add_dictionary(bencode_item_t *dict, const char *key) {
  325. return bencode_dictionary_add(dict, key, bencode_dictionary(bencode_item_buffer(dict)));
  326. }
  327. INLINE bencode_item_t *bencode_dictionary_add_list(bencode_item_t *dict, const char *key) {
  328. return bencode_dictionary_add(dict, key, bencode_list(bencode_item_buffer(dict)));
  329. }
  330. INLINE bencode_item_t *bencode_list_add_string(bencode_item_t *list, const char *s) {
  331. return bencode_list_add(list, bencode_string(bencode_item_buffer(list), s));
  332. }
  333. INLINE bencode_item_t *bencode_list_add_str(bencode_item_t *list, const str *s) {
  334. return bencode_list_add(list, bencode_str(bencode_item_buffer(list), s));
  335. }
  336. INLINE bencode_item_t *bencode_list_add_list(bencode_item_t *list) {
  337. return bencode_list_add(list, bencode_list(bencode_item_buffer(list)));
  338. }
  339. INLINE bencode_item_t *bencode_list_add_dictionary(bencode_item_t *list) {
  340. return bencode_list_add(list, bencode_dictionary(bencode_item_buffer(list)));
  341. }
  342. INLINE bencode_item_t *bencode_dictionary_get(bencode_item_t *dict, const char *key) {
  343. if (!key)
  344. return NULL;
  345. return bencode_dictionary_get_len(dict, key, strlen(key));
  346. }
  347. INLINE char *bencode_dictionary_get_string(bencode_item_t *dict, const char *key, int *len) {
  348. bencode_item_t *val;
  349. val = bencode_dictionary_get(dict, key);
  350. if (!val || val->type != BENCODE_STRING)
  351. return NULL;
  352. *len = val->iov[1].iov_len;
  353. return val->iov[1].iov_base;
  354. }
  355. INLINE char *bencode_dictionary_get_str(bencode_item_t *dict, const char *key, str *str) {
  356. str->s = bencode_dictionary_get_string(dict, key, &str->len);
  357. if (!str->s)
  358. str->len = 0;
  359. return str->s;
  360. }
  361. INLINE char *bencode_dictionary_get_string_dup(bencode_item_t *dict, const char *key, int *len) {
  362. const char *s;
  363. char *ret;
  364. s = bencode_dictionary_get_string(dict, key, len);
  365. if (!s)
  366. return NULL;
  367. ret = BENCODE_MALLOC(*len);
  368. if (!ret)
  369. return NULL;
  370. memcpy(ret, s, *len);
  371. return ret;
  372. }
  373. INLINE char *bencode_dictionary_get_str_dup(bencode_item_t *dict, const char *key, str *str) {
  374. str->s = bencode_dictionary_get_string_dup(dict, key, &str->len);
  375. return str->s;
  376. }
  377. INLINE long long int bencode_dictionary_get_integer(bencode_item_t *dict, const char *key, long long int defval) {
  378. bencode_item_t *val;
  379. val = bencode_dictionary_get(dict, key);
  380. if (!val || val->type != BENCODE_INTEGER)
  381. return defval;
  382. return val->value;
  383. }
  384. INLINE bencode_item_t *bencode_decode_expect(bencode_buffer_t *buf, const char *s, int len, bencode_type_t expect) {
  385. bencode_item_t *ret;
  386. ret = bencode_decode(buf, s, len);
  387. if (!ret || ret->type != expect)
  388. return NULL;
  389. return ret;
  390. }
  391. INLINE bencode_item_t *bencode_decode_expect_str(bencode_buffer_t *buf, const str *s, bencode_type_t expect) {
  392. return bencode_decode_expect(buf, s->s, s->len, expect);
  393. }
  394. INLINE bencode_item_t *bencode_dictionary_get_expect(bencode_item_t *dict, const char *key, bencode_type_t expect) {
  395. bencode_item_t *ret;
  396. ret = bencode_dictionary_get(dict, key);
  397. if (!ret || ret->type != expect)
  398. return NULL;
  399. return ret;
  400. }
  401. INLINE str *bencode_collapse_str(bencode_item_t *root, str *out) {
  402. out->s = bencode_collapse(root, &out->len);
  403. return out;
  404. }
  405. INLINE int bencode_strcmp(bencode_item_t *a, const char *b) {
  406. int len;
  407. if (a->type != BENCODE_STRING)
  408. return 2;
  409. len = strlen(b);
  410. if (a->iov[1].iov_len < len)
  411. return -1;
  412. if (a->iov[1].iov_len > len)
  413. return 1;
  414. return memcmp(a->iov[1].iov_base, b, len);
  415. }
  416. INLINE int bencode_dictionary_get_strcmp(bencode_item_t *dict, const char *key, const char *str) {
  417. bencode_item_t *i;
  418. i = bencode_dictionary_get(dict, key);
  419. if (!i)
  420. return 2;
  421. return bencode_strcmp(i, str);
  422. }
  423. INLINE str *bencode_get_str(bencode_item_t *in, str *out) {
  424. if (!in || in->type != BENCODE_STRING)
  425. return NULL;
  426. out->s = in->iov[1].iov_base;
  427. out->len = in->iov[1].iov_len;
  428. return out;
  429. }
  430. INLINE bencode_item_t *bencode_dictionary_add_iovec(bencode_item_t *dict, const char *key,
  431. const struct iovec *iov, int iov_cnt, int str_len)
  432. {
  433. return bencode_dictionary_add(dict, key, bencode_string_iovec(bencode_item_buffer(dict), iov, iov_cnt, str_len));
  434. }
  435. #endif