nghttp2_buf.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. /*
  2. * Copyright (C) 2015-2018 Alibaba Group Holding Limited
  3. */
  4. #include "nghttp2_buf.h"
  5. #include <stdio.h>
  6. #include "nghttp2_helper.h"
  7. #include "nghttp2_debug.h"
  8. void nghttp2_buf_init(nghttp2_buf *buf) {
  9. buf->begin = NULL;
  10. buf->end = NULL;
  11. buf->pos = NULL;
  12. buf->last = NULL;
  13. buf->mark = NULL;
  14. }
  15. int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem) {
  16. nghttp2_buf_init(buf);
  17. return nghttp2_buf_reserve(buf, initial, mem);
  18. }
  19. void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem) {
  20. if (buf == NULL) {
  21. return;
  22. }
  23. nghttp2_mem_free(mem, buf->begin);
  24. buf->begin = NULL;
  25. }
  26. int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem) {
  27. uint8_t *ptr;
  28. size_t cap;
  29. cap = nghttp2_buf_cap(buf);
  30. if (cap >= new_cap) {
  31. return 0;
  32. }
  33. new_cap = nghttp2_max(new_cap, cap * 2);
  34. ptr = nghttp2_mem_realloc(mem, buf->begin, new_cap);
  35. if (ptr == NULL) {
  36. return NGHTTP2_ERR_NOMEM;
  37. }
  38. buf->pos = ptr + (buf->pos - buf->begin);
  39. buf->last = ptr + (buf->last - buf->begin);
  40. buf->mark = ptr + (buf->mark - buf->begin);
  41. buf->begin = ptr;
  42. buf->end = ptr + new_cap;
  43. return 0;
  44. }
  45. void nghttp2_buf_reset(nghttp2_buf *buf) {
  46. buf->pos = buf->last = buf->mark = buf->begin;
  47. }
  48. void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len) {
  49. buf->begin = buf->pos = buf->last = buf->mark = begin;
  50. buf->end = begin + len;
  51. }
  52. static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length,
  53. nghttp2_mem *mem) {
  54. int rv;
  55. *chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
  56. if (*chain == NULL) {
  57. return NGHTTP2_ERR_NOMEM;
  58. }
  59. (*chain)->next = NULL;
  60. rv = nghttp2_buf_init2(&(*chain)->buf, chunk_length, mem);
  61. if (rv != 0) {
  62. nghttp2_mem_free(mem, *chain);
  63. return NGHTTP2_ERR_NOMEM;
  64. }
  65. return 0;
  66. }
  67. static void buf_chain_del(nghttp2_buf_chain *chain, nghttp2_mem *mem) {
  68. nghttp2_buf_free(&chain->buf, mem);
  69. nghttp2_mem_free(mem, chain);
  70. }
  71. int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk,
  72. nghttp2_mem *mem) {
  73. return nghttp2_bufs_init2(bufs, chunk_length, max_chunk, 0, mem);
  74. }
  75. int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
  76. size_t max_chunk, size_t offset, nghttp2_mem *mem) {
  77. return nghttp2_bufs_init3(bufs, chunk_length, max_chunk, max_chunk, offset,
  78. mem);
  79. }
  80. int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
  81. size_t max_chunk, size_t chunk_keep, size_t offset,
  82. nghttp2_mem *mem) {
  83. int rv;
  84. nghttp2_buf_chain *chain;
  85. if (chunk_keep == 0 || max_chunk < chunk_keep || chunk_length < offset) {
  86. return NGHTTP2_ERR_INVALID_ARGUMENT;
  87. }
  88. rv = buf_chain_new(&chain, chunk_length, mem);
  89. if (rv != 0) {
  90. return rv;
  91. }
  92. bufs->mem = mem;
  93. bufs->offset = offset;
  94. bufs->head = chain;
  95. bufs->cur = bufs->head;
  96. nghttp2_buf_shift_right(&bufs->cur->buf, offset);
  97. bufs->chunk_length = chunk_length;
  98. bufs->chunk_used = 1;
  99. bufs->max_chunk = max_chunk;
  100. bufs->chunk_keep = chunk_keep;
  101. return 0;
  102. }
  103. int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length) {
  104. int rv;
  105. nghttp2_buf_chain *chain;
  106. if (chunk_length < bufs->offset) {
  107. return NGHTTP2_ERR_INVALID_ARGUMENT;
  108. }
  109. rv = buf_chain_new(&chain, chunk_length, bufs->mem);
  110. if (rv != 0) {
  111. return rv;
  112. }
  113. nghttp2_bufs_free(bufs);
  114. bufs->head = chain;
  115. bufs->cur = bufs->head;
  116. nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset);
  117. bufs->chunk_length = chunk_length;
  118. bufs->chunk_used = 1;
  119. return 0;
  120. }
  121. void nghttp2_bufs_free(nghttp2_bufs *bufs) {
  122. nghttp2_buf_chain *chain, *next_chain;
  123. if (bufs == NULL) {
  124. return;
  125. }
  126. for (chain = bufs->head; chain;) {
  127. next_chain = chain->next;
  128. buf_chain_del(chain, bufs->mem);
  129. chain = next_chain;
  130. }
  131. bufs->head = NULL;
  132. }
  133. int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
  134. nghttp2_mem *mem) {
  135. nghttp2_buf_chain *chain;
  136. chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
  137. if (chain == NULL) {
  138. return NGHTTP2_ERR_NOMEM;
  139. }
  140. chain->next = NULL;
  141. nghttp2_buf_wrap_init(&chain->buf, begin, len);
  142. bufs->mem = mem;
  143. bufs->offset = 0;
  144. bufs->head = chain;
  145. bufs->cur = bufs->head;
  146. bufs->chunk_length = len;
  147. bufs->chunk_used = 1;
  148. bufs->max_chunk = 1;
  149. bufs->chunk_keep = 1;
  150. return 0;
  151. }
  152. int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec,
  153. size_t veclen, nghttp2_mem *mem) {
  154. size_t i = 0;
  155. nghttp2_buf_chain *cur_chain;
  156. nghttp2_buf_chain *head_chain;
  157. nghttp2_buf_chain **dst_chain = &head_chain;
  158. if (veclen == 0) {
  159. return nghttp2_bufs_wrap_init(bufs, NULL, 0, mem);
  160. }
  161. head_chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain) * veclen);
  162. if (head_chain == NULL) {
  163. return NGHTTP2_ERR_NOMEM;
  164. }
  165. for (i = 0; i < veclen; ++i) {
  166. cur_chain = &head_chain[i];
  167. cur_chain->next = NULL;
  168. nghttp2_buf_wrap_init(&cur_chain->buf, vec[i].base, vec[i].len);
  169. *dst_chain = cur_chain;
  170. dst_chain = &cur_chain->next;
  171. }
  172. bufs->mem = mem;
  173. bufs->offset = 0;
  174. bufs->head = head_chain;
  175. bufs->cur = bufs->head;
  176. /* We don't use chunk_length since no allocation is expected. */
  177. bufs->chunk_length = 0;
  178. bufs->chunk_used = veclen;
  179. bufs->max_chunk = veclen;
  180. bufs->chunk_keep = veclen;
  181. return 0;
  182. }
  183. void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) {
  184. if (bufs == NULL) {
  185. return;
  186. }
  187. if (bufs->head) {
  188. nghttp2_mem_free(bufs->mem, bufs->head);
  189. }
  190. }
  191. void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) {
  192. nghttp2_buf_chain *ci;
  193. for (ci = bufs->cur; ci; ci = ci->next) {
  194. if (nghttp2_buf_len(&ci->buf) == 0) {
  195. return;
  196. } else {
  197. bufs->cur = ci;
  198. }
  199. }
  200. }
  201. size_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
  202. nghttp2_buf_chain *ci;
  203. size_t len;
  204. len = 0;
  205. for (ci = bufs->head; ci; ci = ci->next) {
  206. len += nghttp2_buf_len(&ci->buf);
  207. }
  208. return len;
  209. }
  210. static int bufs_alloc_chain(nghttp2_bufs *bufs) {
  211. int rv;
  212. nghttp2_buf_chain *chain;
  213. if (bufs->cur->next) {
  214. bufs->cur = bufs->cur->next;
  215. return 0;
  216. }
  217. if (bufs->max_chunk == bufs->chunk_used) {
  218. return NGHTTP2_ERR_BUFFER_ERROR;
  219. }
  220. rv = buf_chain_new(&chain, bufs->chunk_length, bufs->mem);
  221. if (rv != 0) {
  222. return rv;
  223. }
  224. DEBUGF("new buffer %zu bytes allocated for bufs %p, used %zu\n",
  225. bufs->chunk_length, bufs, bufs->chunk_used);
  226. ++bufs->chunk_used;
  227. bufs->cur->next = chain;
  228. bufs->cur = chain;
  229. nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset);
  230. return 0;
  231. }
  232. int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
  233. int rv;
  234. size_t nwrite;
  235. nghttp2_buf *buf;
  236. const uint8_t *p;
  237. p = data;
  238. while (len) {
  239. buf = &bufs->cur->buf;
  240. nwrite = nghttp2_min(nghttp2_buf_avail(buf), len);
  241. if (nwrite == 0) {
  242. rv = bufs_alloc_chain(bufs);
  243. if (rv != 0) {
  244. return rv;
  245. }
  246. continue;
  247. }
  248. buf->last = nghttp2_cpymem(buf->last, p, nwrite);
  249. p += nwrite;
  250. len -= nwrite;
  251. }
  252. return 0;
  253. }
  254. static int bufs_ensure_addb(nghttp2_bufs *bufs) {
  255. int rv;
  256. nghttp2_buf *buf;
  257. buf = &bufs->cur->buf;
  258. if (nghttp2_buf_avail(buf) > 0) {
  259. return 0;
  260. }
  261. rv = bufs_alloc_chain(bufs);
  262. if (rv != 0) {
  263. return rv;
  264. }
  265. return 0;
  266. }
  267. int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b) {
  268. int rv;
  269. rv = bufs_ensure_addb(bufs);
  270. if (rv != 0) {
  271. return rv;
  272. }
  273. *bufs->cur->buf.last++ = b;
  274. return 0;
  275. }
  276. int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b) {
  277. int rv;
  278. rv = bufs_ensure_addb(bufs);
  279. if (rv != 0) {
  280. return rv;
  281. }
  282. *bufs->cur->buf.last = b;
  283. return 0;
  284. }
  285. int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b) {
  286. int rv;
  287. rv = bufs_ensure_addb(bufs);
  288. if (rv != 0) {
  289. return rv;
  290. }
  291. *bufs->cur->buf.last++ |= b;
  292. return 0;
  293. }
  294. int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b) {
  295. int rv;
  296. rv = bufs_ensure_addb(bufs);
  297. if (rv != 0) {
  298. return rv;
  299. }
  300. *bufs->cur->buf.last |= b;
  301. return 0;
  302. }
  303. ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
  304. size_t len;
  305. nghttp2_buf_chain *chain;
  306. nghttp2_buf *buf;
  307. uint8_t *res;
  308. nghttp2_buf resbuf;
  309. len = 0;
  310. for (chain = bufs->head; chain; chain = chain->next) {
  311. len += nghttp2_buf_len(&chain->buf);
  312. }
  313. if (len == 0) {
  314. res = NULL;
  315. return 0;
  316. }
  317. res = nghttp2_mem_malloc(bufs->mem, len);
  318. if (res == NULL) {
  319. return NGHTTP2_ERR_NOMEM;
  320. }
  321. nghttp2_buf_wrap_init(&resbuf, res, len);
  322. for (chain = bufs->head; chain; chain = chain->next) {
  323. buf = &chain->buf;
  324. resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
  325. }
  326. *out = res;
  327. return (ssize_t)len;
  328. }
  329. size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) {
  330. size_t len;
  331. nghttp2_buf_chain *chain;
  332. nghttp2_buf *buf;
  333. nghttp2_buf resbuf;
  334. len = nghttp2_bufs_len(bufs);
  335. nghttp2_buf_wrap_init(&resbuf, out, len);
  336. for (chain = bufs->head; chain; chain = chain->next) {
  337. buf = &chain->buf;
  338. resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
  339. }
  340. return len;
  341. }
  342. void nghttp2_bufs_reset(nghttp2_bufs *bufs) {
  343. nghttp2_buf_chain *chain, *ci;
  344. size_t k;
  345. k = bufs->chunk_keep;
  346. for (ci = bufs->head; ci; ci = ci->next) {
  347. nghttp2_buf_reset(&ci->buf);
  348. nghttp2_buf_shift_right(&ci->buf, bufs->offset);
  349. if (--k == 0) {
  350. break;
  351. }
  352. }
  353. if (ci) {
  354. chain = ci->next;
  355. ci->next = NULL;
  356. for (ci = chain; ci;) {
  357. chain = ci->next;
  358. buf_chain_del(ci, bufs->mem);
  359. ci = chain;
  360. }
  361. bufs->chunk_used = bufs->chunk_keep;
  362. }
  363. bufs->cur = bufs->head;
  364. }
  365. int nghttp2_bufs_advance(nghttp2_bufs *bufs) { return bufs_alloc_chain(bufs); }
  366. int nghttp2_bufs_next_present(nghttp2_bufs *bufs) {
  367. nghttp2_buf_chain *chain;
  368. chain = bufs->cur->next;
  369. return chain && nghttp2_buf_len(&chain->buf);
  370. }