nghttp2_buf.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * nghttp2 - HTTP/2 C Library
  3. *
  4. * Copyright (c) 2014 Tatsuhiro Tsujikawa
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sublicense, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  21. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. */
  25. #ifndef NGHTTP2_BUF_H
  26. #define NGHTTP2_BUF_H
  27. #ifdef HAVE_CONFIG_H
  28. #include <config.h>
  29. #endif /* HAVE_CONFIG_H */
  30. #include <nghttp2/nghttp2.h>
  31. #include "nghttp2_int.h"
  32. #include "nghttp2_mem.h"
  33. typedef struct {
  34. /* This points to the beginning of the buffer. The effective range
  35. of buffer is [begin, end). */
  36. uint8_t *begin;
  37. /* This points to the memory one byte beyond the end of the
  38. buffer. */
  39. uint8_t *end;
  40. /* The position indicator for effective start of the buffer. pos <=
  41. last must be hold. */
  42. uint8_t *pos;
  43. /* The position indicator for effective one beyond of the end of the
  44. buffer. last <= end must be hold. */
  45. uint8_t *last;
  46. /* Mark arbitrary position in buffer [begin, end) */
  47. uint8_t *mark;
  48. } nghttp2_buf;
  49. #define nghttp2_buf_len(BUF) ((size_t)((BUF)->last - (BUF)->pos))
  50. #define nghttp2_buf_avail(BUF) ((size_t)((BUF)->end - (BUF)->last))
  51. #define nghttp2_buf_mark_avail(BUF) ((size_t)((BUF)->mark - (BUF)->last))
  52. #define nghttp2_buf_cap(BUF) ((size_t)((BUF)->end - (BUF)->begin))
  53. #define nghttp2_buf_pos_offset(BUF) ((size_t)((BUF)->pos - (BUF)->begin))
  54. #define nghttp2_buf_last_offset(BUF) ((size_t)((BUF)->last - (BUF)->begin))
  55. #define nghttp2_buf_shift_right(BUF, AMT) \
  56. do { \
  57. (BUF)->pos += AMT; \
  58. (BUF)->last += AMT; \
  59. } while (0)
  60. #define nghttp2_buf_shift_left(BUF, AMT) \
  61. do { \
  62. (BUF)->pos -= AMT; \
  63. (BUF)->last -= AMT; \
  64. } while (0)
  65. /*
  66. * Initializes the |buf|. No memory is allocated in this function. Use
  67. * nghttp2_buf_reserve() to allocate memory.
  68. */
  69. void nghttp2_buf_init(nghttp2_buf *buf);
  70. /*
  71. * Initializes the |buf| and allocates at least |initial| bytes of
  72. * memory.
  73. *
  74. * This function returns 0 if it succeeds, or one of the following
  75. * negative error codes:
  76. *
  77. * NGHTTP2_ERR_NOMEM
  78. * Out of memory
  79. */
  80. int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem);
  81. /*
  82. * Frees buffer in |buf|.
  83. */
  84. void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem);
  85. /*
  86. * Extends buffer so that nghttp2_buf_cap() returns at least
  87. * |new_cap|. If extensions took place, buffer pointers in |buf| will
  88. * change.
  89. *
  90. * This function returns 0 if it succeeds, or one of the followings
  91. * negative error codes:
  92. *
  93. * NGHTTP2_ERR_NOMEM
  94. * Out of memory
  95. */
  96. int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem);
  97. /*
  98. * Resets pos, last, mark member of |buf| to buf->begin.
  99. */
  100. void nghttp2_buf_reset(nghttp2_buf *buf);
  101. /*
  102. * Initializes |buf| using supplied buffer |begin| of length
  103. * |len|. Semantically, the application should not call *_reserve() or
  104. * nghttp2_free() functions for |buf|.
  105. */
  106. void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len);
  107. struct nghttp2_buf_chain;
  108. typedef struct nghttp2_buf_chain nghttp2_buf_chain;
  109. /* Chains 2 buffers */
  110. struct nghttp2_buf_chain {
  111. /* Points to the subsequent buffer. NULL if there is no such
  112. buffer. */
  113. nghttp2_buf_chain *next;
  114. nghttp2_buf buf;
  115. };
  116. typedef struct {
  117. /* Points to the first buffer */
  118. nghttp2_buf_chain *head;
  119. /* Buffer pointer where write occurs. */
  120. nghttp2_buf_chain *cur;
  121. /* Memory allocator */
  122. nghttp2_mem *mem;
  123. /* The buffer capacity of each buf */
  124. size_t chunk_length;
  125. /* The maximum number of nghttp2_buf_chain */
  126. size_t max_chunk;
  127. /* The number of nghttp2_buf_chain allocated */
  128. size_t chunk_used;
  129. /* The number of nghttp2_buf_chain to keep on reset */
  130. size_t chunk_keep;
  131. /* pos offset from begin in each buffers. On initialization and
  132. reset, buf->pos and buf->last are positioned at buf->begin +
  133. offset. */
  134. size_t offset;
  135. } nghttp2_bufs;
  136. /*
  137. * This is the same as calling nghttp2_bufs_init2 with the given
  138. * arguments and offset = 0.
  139. */
  140. int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk,
  141. nghttp2_mem *mem);
  142. /*
  143. * This is the same as calling nghttp2_bufs_init3 with the given
  144. * arguments and chunk_keep = max_chunk.
  145. */
  146. int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
  147. size_t max_chunk, size_t offset, nghttp2_mem *mem);
  148. /*
  149. * Initializes |bufs|. Each buffer size is given in the
  150. * |chunk_length|. The maximum number of buffers is given in the
  151. * |max_chunk|. On reset, first |chunk_keep| buffers are kept and
  152. * remaining buffers are deleted. Each buffer will have bufs->pos and
  153. * bufs->last shifted to left by |offset| bytes on creation and reset.
  154. *
  155. * This function allocates first buffer. bufs->head and bufs->cur
  156. * will point to the first buffer after this call.
  157. *
  158. * This function returns 0 if it succeeds, or one of the following
  159. * negative error codes:
  160. *
  161. * NGHTTP2_ERR_NOMEM
  162. * Out of memory.
  163. * NGHTTP2_ERR_INVALID_ARGUMENT
  164. * chunk_keep is 0; or max_chunk < chunk_keep; or offset is too
  165. * long.
  166. */
  167. int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
  168. size_t max_chunk, size_t chunk_keep, size_t offset,
  169. nghttp2_mem *mem);
  170. /*
  171. * Frees any related resources to the |bufs|.
  172. */
  173. void nghttp2_bufs_free(nghttp2_bufs *bufs);
  174. /*
  175. * Initializes |bufs| using supplied buffer |begin| of length |len|.
  176. * The first buffer bufs->head uses buffer |begin|. The buffer size
  177. * is fixed and no allocate extra chunk buffer is allocated. In other
  178. * words, max_chunk = chunk_keep = 1. To free the resource allocated
  179. * for |bufs|, use nghttp2_bufs_wrap_free().
  180. *
  181. * This function returns 0 if it succeeds, or one of the following
  182. * negative error codes:
  183. *
  184. * NGHTTP2_ERR_NOMEM
  185. * Out of memory.
  186. */
  187. int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
  188. nghttp2_mem *mem);
  189. /*
  190. * Frees any related resource to the |bufs|. This function does not
  191. * free supplied buffer provided in nghttp2_bufs_wrap_init().
  192. */
  193. void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs);
  194. /*
  195. * Reallocates internal buffer using |chunk_length|. The max_chunk,
  196. * chunk_keep and offset do not change. After successful allocation
  197. * of new buffer, previous buffers are deallocated without copying
  198. * anything into new buffers. chunk_used is reset to 1.
  199. *
  200. * This function returns 0 if it succeeds, or one of the following
  201. * negative error codes:
  202. *
  203. * NGHTTP2_ERR_NOMEM
  204. * Out of memory.
  205. * NGHTTP2_ERR_INVALID_ARGUMENT
  206. * chunk_length < offset
  207. */
  208. int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length);
  209. /*
  210. * Appends the |data| of length |len| to the |bufs|. The write starts
  211. * at bufs->cur->buf.last. A new buffers will be allocated to store
  212. * all data.
  213. *
  214. * This function returns 0 if it succeeds, or one of the following
  215. * negative error codes:
  216. *
  217. * NGHTTP2_ERR_NOMEM
  218. * Out of memory.
  219. * NGHTTP2_ERR_BUFFER_ERROR
  220. * Out of buffer space.
  221. */
  222. int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len);
  223. /*
  224. * Appends a single byte |b| to the |bufs|. The write starts at
  225. * bufs->cur->buf.last. A new buffers will be allocated to store all
  226. * data.
  227. *
  228. * This function returns 0 if it succeeds, or one of the following
  229. * negative error codes:
  230. *
  231. * NGHTTP2_ERR_NOMEM
  232. * Out of memory.
  233. * NGHTTP2_ERR_BUFFER_ERROR
  234. * Out of buffer space.
  235. */
  236. int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b);
  237. /*
  238. * Behaves like nghttp2_bufs_addb(), but this does not update
  239. * buf->last pointer.
  240. */
  241. int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b);
  242. #define nghttp2_bufs_fast_addb(BUFS, B) \
  243. do { \
  244. *(BUFS)->cur->buf.last++ = B; \
  245. } while (0)
  246. #define nghttp2_bufs_fast_addb_hold(BUFS, B) \
  247. do { \
  248. *(BUFS)->cur->buf.last = B; \
  249. } while (0)
  250. /*
  251. * Performs bitwise-OR of |b| at bufs->cur->buf.last. A new buffers
  252. * will be allocated if necessary.
  253. *
  254. * This function returns 0 if it succeeds, or one of the following
  255. * negative error codes:
  256. *
  257. * NGHTTP2_ERR_NOMEM
  258. * Out of memory.
  259. * NGHTTP2_ERR_BUFFER_ERROR
  260. * Out of buffer space.
  261. */
  262. int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b);
  263. /*
  264. * Behaves like nghttp2_bufs_orb(), but does not update buf->last
  265. * pointer.
  266. */
  267. int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
  268. #define nghttp2_bufs_fast_orb(BUFS, B) \
  269. do { \
  270. uint8_t **p = &(BUFS)->cur->buf.last; \
  271. **p = (uint8_t)(**p | (B)); \
  272. ++(*p); \
  273. } while (0)
  274. #define nghttp2_bufs_fast_orb_hold(BUFS, B) \
  275. do { \
  276. uint8_t *p = (BUFS)->cur->buf.last; \
  277. *p = (uint8_t)(*p | (B)); \
  278. } while (0)
  279. /*
  280. * Copies all data stored in |bufs| to the contiguous buffer. This
  281. * function allocates the contiguous memory to store all data in
  282. * |bufs| and assigns it to |*out|.
  283. *
  284. * The contents of |bufs| is left unchanged.
  285. *
  286. * This function returns the length of copied data and assigns the
  287. * pointer to copied data to |*out| if it succeeds, or one of the
  288. * following negative error codes:
  289. *
  290. * NGHTTP2_ERR_NOMEM
  291. * Out of memory
  292. */
  293. ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
  294. /*
  295. * Copies all data stored in |bufs| to |out|. This function assumes
  296. * that the buffer space pointed by |out| has at least
  297. * nghttp2_bufs(bufs) bytes.
  298. *
  299. * The contents of |bufs| is left unchanged.
  300. *
  301. * This function returns the length of copied data.
  302. */
  303. size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out);
  304. /*
  305. * Resets |bufs| and makes the buffers empty.
  306. */
  307. void nghttp2_bufs_reset(nghttp2_bufs *bufs);
  308. /*
  309. * Moves bufs->cur to bufs->cur->next. If resulting bufs->cur is
  310. * NULL, this function allocates new buffers and bufs->cur points to
  311. * it.
  312. *
  313. * This function returns 0 if it succeeds, or one of the following
  314. * negative error codes:
  315. *
  316. * NGHTTP2_ERR_NOMEM
  317. * Out of memory
  318. * NGHTTP2_ERR_BUFFER_ERROR
  319. * Out of buffer space.
  320. */
  321. int nghttp2_bufs_advance(nghttp2_bufs *bufs);
  322. /* Sets bufs->cur to bufs->head */
  323. #define nghttp2_bufs_rewind(BUFS) \
  324. do { \
  325. (BUFS)->cur = (BUFS)->head; \
  326. } while (0)
  327. /*
  328. * Move bufs->cur, from the current position, using next member, to
  329. * the last buf which has nghttp2_buf_len(buf) > 0 without seeing buf
  330. * which satisfies nghttp2_buf_len(buf) == 0. If
  331. * nghttp2_buf_len(&bufs->cur->buf) == 0 or bufs->cur->next is NULL,
  332. * bufs->cur is unchanged.
  333. */
  334. void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs);
  335. /*
  336. * Returns nonzero if bufs->cur->next is not emtpy.
  337. */
  338. int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
  339. #define nghttp2_bufs_cur_avail(BUFS) nghttp2_buf_avail(&(BUFS)->cur->buf)
  340. /*
  341. * Returns the buffer length of |bufs|.
  342. */
  343. size_t nghttp2_bufs_len(nghttp2_bufs *bufs);
  344. #endif /* NGHTTP2_BUF_H */