nghttp2_buf.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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 following
  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. This field may be 0 if
  124. nghttp2_bufs is initialized by nghttp2_bufs_wrap_init* family
  125. functions. */
  126. size_t chunk_length;
  127. /* The maximum number of nghttp2_buf_chain */
  128. size_t max_chunk;
  129. /* The number of nghttp2_buf_chain allocated */
  130. size_t chunk_used;
  131. /* The number of nghttp2_buf_chain to keep on reset */
  132. size_t chunk_keep;
  133. /* pos offset from begin in each buffers. On initialization and
  134. reset, buf->pos and buf->last are positioned at buf->begin +
  135. offset. */
  136. size_t offset;
  137. } nghttp2_bufs;
  138. /*
  139. * This is the same as calling nghttp2_bufs_init2 with the given
  140. * arguments and offset = 0.
  141. */
  142. int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk,
  143. nghttp2_mem *mem);
  144. /*
  145. * This is the same as calling nghttp2_bufs_init3 with the given
  146. * arguments and chunk_keep = max_chunk.
  147. */
  148. int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
  149. size_t max_chunk, size_t offset, nghttp2_mem *mem);
  150. /*
  151. * Initializes |bufs|. Each buffer size is given in the
  152. * |chunk_length|. The maximum number of buffers is given in the
  153. * |max_chunk|. On reset, first |chunk_keep| buffers are kept and
  154. * remaining buffers are deleted. Each buffer will have bufs->pos and
  155. * bufs->last shifted to left by |offset| bytes on creation and reset.
  156. *
  157. * This function allocates first buffer. bufs->head and bufs->cur
  158. * will point to the first buffer after this call.
  159. *
  160. * This function returns 0 if it succeeds, or one of the following
  161. * negative error codes:
  162. *
  163. * NGHTTP2_ERR_NOMEM
  164. * Out of memory.
  165. * NGHTTP2_ERR_INVALID_ARGUMENT
  166. * chunk_keep is 0; or max_chunk < chunk_keep; or offset is too
  167. * long.
  168. */
  169. int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
  170. size_t max_chunk, size_t chunk_keep, size_t offset,
  171. nghttp2_mem *mem);
  172. /*
  173. * Frees any related resources to the |bufs|.
  174. */
  175. void nghttp2_bufs_free(nghttp2_bufs *bufs);
  176. /*
  177. * Initializes |bufs| using supplied buffer |begin| of length |len|.
  178. * The first buffer bufs->head uses buffer |begin|. The buffer size
  179. * is fixed and no extra chunk buffer is allocated. In other
  180. * words, max_chunk = chunk_keep = 1. To free the resource allocated
  181. * for |bufs|, use nghttp2_bufs_wrap_free().
  182. *
  183. * Don't use the function which performs allocation, such as
  184. * nghttp2_bufs_realloc().
  185. *
  186. * This function returns 0 if it succeeds, or one of the following
  187. * negative error codes:
  188. *
  189. * NGHTTP2_ERR_NOMEM
  190. * Out of memory.
  191. */
  192. int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
  193. nghttp2_mem *mem);
  194. /*
  195. * Initializes |bufs| using supplied |veclen| size of buf vector
  196. * |vec|. The number of buffers is fixed and no extra chunk buffer is
  197. * allocated. In other words, max_chunk = chunk_keep = |in_len|. To
  198. * free the resource allocated for |bufs|, use
  199. * nghttp2_bufs_wrap_free().
  200. *
  201. * Don't use the function which performs allocation, such as
  202. * nghttp2_bufs_realloc().
  203. *
  204. * This function returns 0 if it succeeds, or one of the following
  205. * negative error codes:
  206. *
  207. * NGHTTP2_ERR_NOMEM
  208. * Out of memory.
  209. */
  210. int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec,
  211. size_t veclen, nghttp2_mem *mem);
  212. /*
  213. * Frees any related resource to the |bufs|. This function does not
  214. * free supplied buffer provided in nghttp2_bufs_wrap_init().
  215. */
  216. void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs);
  217. /*
  218. * Reallocates internal buffer using |chunk_length|. The max_chunk,
  219. * chunk_keep and offset do not change. After successful allocation
  220. * of new buffer, previous buffers are deallocated without copying
  221. * anything into new buffers. chunk_used is reset to 1.
  222. *
  223. * This function returns 0 if it succeeds, or one of the following
  224. * negative error codes:
  225. *
  226. * NGHTTP2_ERR_NOMEM
  227. * Out of memory.
  228. * NGHTTP2_ERR_INVALID_ARGUMENT
  229. * chunk_length < offset
  230. */
  231. int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length);
  232. /*
  233. * Appends the |data| of length |len| to the |bufs|. The write starts
  234. * at bufs->cur->buf.last. A new buffers will be allocated to store
  235. * all data.
  236. *
  237. * This function returns 0 if it succeeds, or one of the following
  238. * negative error codes:
  239. *
  240. * NGHTTP2_ERR_NOMEM
  241. * Out of memory.
  242. * NGHTTP2_ERR_BUFFER_ERROR
  243. * Out of buffer space.
  244. */
  245. int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len);
  246. /*
  247. * Appends a single byte |b| to the |bufs|. The write starts at
  248. * bufs->cur->buf.last. A new buffers will be allocated to store all
  249. * data.
  250. *
  251. * This function returns 0 if it succeeds, or one of the following
  252. * negative error codes:
  253. *
  254. * NGHTTP2_ERR_NOMEM
  255. * Out of memory.
  256. * NGHTTP2_ERR_BUFFER_ERROR
  257. * Out of buffer space.
  258. */
  259. int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b);
  260. /*
  261. * Behaves like nghttp2_bufs_addb(), but this does not update
  262. * buf->last pointer.
  263. */
  264. int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b);
  265. #define nghttp2_bufs_fast_addb(BUFS, B) \
  266. do { \
  267. *(BUFS)->cur->buf.last++ = B; \
  268. } while (0)
  269. #define nghttp2_bufs_fast_addb_hold(BUFS, B) \
  270. do { \
  271. *(BUFS)->cur->buf.last = B; \
  272. } while (0)
  273. /*
  274. * Performs bitwise-OR of |b| at bufs->cur->buf.last. A new buffers
  275. * will be allocated if necessary.
  276. *
  277. * This function returns 0 if it succeeds, or one of the following
  278. * negative error codes:
  279. *
  280. * NGHTTP2_ERR_NOMEM
  281. * Out of memory.
  282. * NGHTTP2_ERR_BUFFER_ERROR
  283. * Out of buffer space.
  284. */
  285. int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b);
  286. /*
  287. * Behaves like nghttp2_bufs_orb(), but does not update buf->last
  288. * pointer.
  289. */
  290. int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
  291. #define nghttp2_bufs_fast_orb(BUFS, B) \
  292. do { \
  293. uint8_t **p = &(BUFS)->cur->buf.last; \
  294. **p = (uint8_t)(**p | (B)); \
  295. ++(*p); \
  296. } while (0)
  297. #define nghttp2_bufs_fast_orb_hold(BUFS, B) \
  298. do { \
  299. uint8_t *p = (BUFS)->cur->buf.last; \
  300. *p = (uint8_t)(*p | (B)); \
  301. } while (0)
  302. /*
  303. * Copies all data stored in |bufs| to the contiguous buffer. This
  304. * function allocates the contiguous memory to store all data in
  305. * |bufs| and assigns it to |*out|.
  306. *
  307. * The contents of |bufs| is left unchanged.
  308. *
  309. * This function returns the length of copied data and assigns the
  310. * pointer to copied data to |*out| if it succeeds, or one of the
  311. * following negative error codes:
  312. *
  313. * NGHTTP2_ERR_NOMEM
  314. * Out of memory
  315. */
  316. nghttp2_ssize nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
  317. /*
  318. * Copies all data stored in |bufs| to |out|. This function assumes
  319. * that the buffer space pointed by |out| has at least
  320. * nghttp2_bufs(bufs) bytes.
  321. *
  322. * The contents of |bufs| is left unchanged.
  323. *
  324. * This function returns the length of copied data.
  325. */
  326. size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out);
  327. /*
  328. * Resets |bufs| and makes the buffers empty.
  329. */
  330. void nghttp2_bufs_reset(nghttp2_bufs *bufs);
  331. /*
  332. * Moves bufs->cur to bufs->cur->next. If resulting bufs->cur is
  333. * NULL, this function allocates new buffers and bufs->cur points to
  334. * it.
  335. *
  336. * This function returns 0 if it succeeds, or one of the following
  337. * negative error codes:
  338. *
  339. * NGHTTP2_ERR_NOMEM
  340. * Out of memory
  341. * NGHTTP2_ERR_BUFFER_ERROR
  342. * Out of buffer space.
  343. */
  344. int nghttp2_bufs_advance(nghttp2_bufs *bufs);
  345. /* Sets bufs->cur to bufs->head */
  346. #define nghttp2_bufs_rewind(BUFS) \
  347. do { \
  348. (BUFS)->cur = (BUFS)->head; \
  349. } while (0)
  350. /*
  351. * Move bufs->cur, from the current position, using next member, to
  352. * the last buf which has nghttp2_buf_len(buf) > 0 without seeing buf
  353. * which satisfies nghttp2_buf_len(buf) == 0. If
  354. * nghttp2_buf_len(&bufs->cur->buf) == 0 or bufs->cur->next is NULL,
  355. * bufs->cur is unchanged.
  356. */
  357. void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs);
  358. /*
  359. * Returns nonzero if bufs->cur->next is not empty.
  360. */
  361. int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
  362. #define nghttp2_bufs_cur_avail(BUFS) nghttp2_buf_avail(&(BUFS)->cur->buf)
  363. /*
  364. * Returns the total buffer length of |bufs|.
  365. */
  366. size_t nghttp2_bufs_len(nghttp2_bufs *bufs);
  367. #endif /* NGHTTP2_BUF_H */