nghttp3_stream.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247
  1. /*
  2. * nghttp3
  3. *
  4. * Copyright (c) 2019 nghttp3 contributors
  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. #include "nghttp3_stream.h"
  26. #include <string.h>
  27. #include <assert.h>
  28. #include <stdio.h>
  29. #include "nghttp3_conv.h"
  30. #include "nghttp3_macro.h"
  31. #include "nghttp3_frame.h"
  32. #include "nghttp3_conn.h"
  33. #include "nghttp3_str.h"
  34. #include "nghttp3_http.h"
  35. #include "nghttp3_vec.h"
  36. #include "nghttp3_unreachable.h"
  37. /* NGHTTP3_STREAM_MAX_COPY_THRES is the maximum size of buffer which
  38. makes a copy to outq. */
  39. #define NGHTTP3_STREAM_MAX_COPY_THRES 128
  40. /* NGHTTP3_MIN_RBLEN is the minimum length of nghttp3_ringbuf */
  41. #define NGHTTP3_MIN_RBLEN 4
  42. nghttp3_objalloc_def(stream, nghttp3_stream, oplent)
  43. int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id,
  44. const nghttp3_stream_callbacks *callbacks,
  45. nghttp3_objalloc *out_chunk_objalloc,
  46. nghttp3_objalloc *stream_objalloc,
  47. const nghttp3_mem *mem) {
  48. nghttp3_stream *stream = nghttp3_objalloc_stream_get(stream_objalloc);
  49. if (stream == NULL) {
  50. return NGHTTP3_ERR_NOMEM;
  51. }
  52. memset(stream, 0, sizeof(*stream));
  53. stream->out_chunk_objalloc = out_chunk_objalloc;
  54. stream->stream_objalloc = stream_objalloc;
  55. nghttp3_tnode_init(&stream->node, stream_id);
  56. nghttp3_ringbuf_init(&stream->frq, 0, sizeof(nghttp3_frame_entry), mem);
  57. nghttp3_ringbuf_init(&stream->chunks, 0, sizeof(nghttp3_buf), mem);
  58. nghttp3_ringbuf_init(&stream->outq, 0, sizeof(nghttp3_typed_buf), mem);
  59. nghttp3_ringbuf_init(&stream->inq, 0, sizeof(nghttp3_buf), mem);
  60. nghttp3_qpack_stream_context_init(&stream->qpack_sctx, stream_id, mem);
  61. stream->qpack_blocked_pe.index = NGHTTP3_PQ_BAD_INDEX;
  62. stream->mem = mem;
  63. stream->rx.http.status_code = -1;
  64. stream->rx.http.content_length = -1;
  65. stream->rx.http.pri.urgency = NGHTTP3_DEFAULT_URGENCY;
  66. stream->error_code = NGHTTP3_H3_NO_ERROR;
  67. if (callbacks) {
  68. stream->callbacks = *callbacks;
  69. }
  70. *pstream = stream;
  71. return 0;
  72. }
  73. static void delete_outq(nghttp3_ringbuf *outq, const nghttp3_mem *mem) {
  74. nghttp3_typed_buf *tbuf;
  75. size_t i, len = nghttp3_ringbuf_len(outq);
  76. for (i = 0; i < len; ++i) {
  77. tbuf = nghttp3_ringbuf_get(outq, i);
  78. if (tbuf->type == NGHTTP3_BUF_TYPE_PRIVATE) {
  79. nghttp3_buf_free(&tbuf->buf, mem);
  80. }
  81. }
  82. nghttp3_ringbuf_free(outq);
  83. }
  84. static void delete_chunks(nghttp3_ringbuf *chunks, const nghttp3_mem *mem) {
  85. nghttp3_buf *buf;
  86. size_t i, len = nghttp3_ringbuf_len(chunks);
  87. for (i = 0; i < len; ++i) {
  88. buf = nghttp3_ringbuf_get(chunks, i);
  89. nghttp3_buf_free(buf, mem);
  90. }
  91. nghttp3_ringbuf_free(chunks);
  92. }
  93. static void delete_out_chunks(nghttp3_ringbuf *chunks,
  94. nghttp3_objalloc *out_chunk_objalloc,
  95. const nghttp3_mem *mem) {
  96. nghttp3_buf *buf;
  97. size_t i, len = nghttp3_ringbuf_len(chunks);
  98. for (i = 0; i < len; ++i) {
  99. buf = nghttp3_ringbuf_get(chunks, i);
  100. if (nghttp3_buf_cap(buf) == NGHTTP3_STREAM_MIN_CHUNK_SIZE) {
  101. nghttp3_objalloc_chunk_release(out_chunk_objalloc,
  102. (nghttp3_chunk *)(void *)buf->begin);
  103. continue;
  104. }
  105. nghttp3_buf_free(buf, mem);
  106. }
  107. nghttp3_ringbuf_free(chunks);
  108. }
  109. static void delete_frq(nghttp3_ringbuf *frq, const nghttp3_mem *mem) {
  110. nghttp3_frame_entry *frent;
  111. size_t i, len = nghttp3_ringbuf_len(frq);
  112. for (i = 0; i < len; ++i) {
  113. frent = nghttp3_ringbuf_get(frq, i);
  114. switch (frent->fr.hd.type) {
  115. case NGHTTP3_FRAME_HEADERS:
  116. nghttp3_frame_headers_free(&frent->fr.headers, mem);
  117. break;
  118. case NGHTTP3_FRAME_PRIORITY_UPDATE:
  119. nghttp3_frame_priority_update_free(&frent->fr.priority_update, mem);
  120. break;
  121. default:
  122. break;
  123. }
  124. }
  125. nghttp3_ringbuf_free(frq);
  126. }
  127. void nghttp3_stream_del(nghttp3_stream *stream) {
  128. if (stream == NULL) {
  129. return;
  130. }
  131. nghttp3_qpack_stream_context_free(&stream->qpack_sctx);
  132. delete_chunks(&stream->inq, stream->mem);
  133. delete_outq(&stream->outq, stream->mem);
  134. delete_out_chunks(&stream->chunks, stream->out_chunk_objalloc, stream->mem);
  135. delete_frq(&stream->frq, stream->mem);
  136. nghttp3_tnode_free(&stream->node);
  137. nghttp3_objalloc_stream_release(stream->stream_objalloc, stream);
  138. }
  139. void nghttp3_varint_read_state_reset(nghttp3_varint_read_state *rvint) {
  140. memset(rvint, 0, sizeof(*rvint));
  141. }
  142. void nghttp3_stream_read_state_reset(nghttp3_stream_read_state *rstate) {
  143. memset(rstate, 0, sizeof(*rstate));
  144. }
  145. nghttp3_ssize nghttp3_read_varint(nghttp3_varint_read_state *rvint,
  146. const uint8_t *begin, const uint8_t *end,
  147. int fin) {
  148. const uint8_t *orig_begin = begin;
  149. size_t len;
  150. assert(begin != end);
  151. if (rvint->left == 0) {
  152. assert(rvint->acc == 0);
  153. len = nghttp3_get_varintlen(begin);
  154. if (len <= (size_t)(end - begin)) {
  155. nghttp3_get_varint(&rvint->acc, begin);
  156. return (nghttp3_ssize)len;
  157. }
  158. if (fin) {
  159. return NGHTTP3_ERR_INVALID_ARGUMENT;
  160. }
  161. rvint->acc = nghttp3_get_varint_fb(begin++);
  162. rvint->left = len - 1;
  163. }
  164. len = nghttp3_min_size(rvint->left, (size_t)(end - begin));
  165. end = begin + len;
  166. for (; begin != end;) {
  167. rvint->acc = (rvint->acc << 8) + *begin++;
  168. }
  169. rvint->left -= len;
  170. if (fin && rvint->left) {
  171. return NGHTTP3_ERR_INVALID_ARGUMENT;
  172. }
  173. return (nghttp3_ssize)(begin - orig_begin);
  174. }
  175. int nghttp3_stream_frq_add(nghttp3_stream *stream,
  176. const nghttp3_frame_entry *frent) {
  177. nghttp3_ringbuf *frq = &stream->frq;
  178. nghttp3_frame_entry *dest;
  179. int rv;
  180. if (nghttp3_ringbuf_full(frq)) {
  181. size_t nlen =
  182. nghttp3_max_size(NGHTTP3_MIN_RBLEN, nghttp3_ringbuf_len(frq) * 2);
  183. rv = nghttp3_ringbuf_reserve(frq, nlen);
  184. if (rv != 0) {
  185. return rv;
  186. }
  187. }
  188. dest = nghttp3_ringbuf_push_back(frq);
  189. *dest = *frent;
  190. return 0;
  191. }
  192. int nghttp3_stream_fill_outq(nghttp3_stream *stream) {
  193. nghttp3_ringbuf *frq = &stream->frq;
  194. nghttp3_frame_entry *frent;
  195. int data_eof;
  196. int rv;
  197. for (; nghttp3_ringbuf_len(frq) &&
  198. stream->unsent_bytes < NGHTTP3_MIN_UNSENT_BYTES;) {
  199. frent = nghttp3_ringbuf_get(frq, 0);
  200. switch (frent->fr.hd.type) {
  201. case NGHTTP3_FRAME_SETTINGS:
  202. rv = nghttp3_stream_write_settings(stream, frent);
  203. if (rv != 0) {
  204. return rv;
  205. }
  206. break;
  207. case NGHTTP3_FRAME_HEADERS:
  208. rv = nghttp3_stream_write_headers(stream, frent);
  209. if (rv != 0) {
  210. return rv;
  211. }
  212. nghttp3_frame_headers_free(&frent->fr.headers, stream->mem);
  213. break;
  214. case NGHTTP3_FRAME_DATA:
  215. rv = nghttp3_stream_write_data(stream, &data_eof, frent);
  216. if (rv != 0) {
  217. return rv;
  218. }
  219. if (stream->flags & NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED) {
  220. return 0;
  221. }
  222. if (!data_eof) {
  223. return 0;
  224. }
  225. break;
  226. case NGHTTP3_FRAME_GOAWAY:
  227. rv = nghttp3_stream_write_goaway(stream, frent);
  228. if (rv != 0) {
  229. return rv;
  230. }
  231. break;
  232. case NGHTTP3_FRAME_PRIORITY_UPDATE:
  233. rv = nghttp3_stream_write_priority_update(stream, frent);
  234. if (rv != 0) {
  235. return rv;
  236. }
  237. nghttp3_frame_priority_update_free(&frent->fr.priority_update,
  238. stream->mem);
  239. break;
  240. default:
  241. /* TODO Not implemented */
  242. break;
  243. }
  244. nghttp3_ringbuf_pop_front(frq);
  245. }
  246. return 0;
  247. }
  248. static void typed_buf_shared_init(nghttp3_typed_buf *tbuf,
  249. const nghttp3_buf *chunk) {
  250. nghttp3_typed_buf_init(tbuf, chunk, NGHTTP3_BUF_TYPE_SHARED);
  251. tbuf->buf.pos = tbuf->buf.last;
  252. }
  253. int nghttp3_stream_write_stream_type(nghttp3_stream *stream) {
  254. size_t len = nghttp3_put_varintlen((int64_t)stream->type);
  255. nghttp3_buf *chunk;
  256. nghttp3_typed_buf tbuf;
  257. int rv;
  258. rv = nghttp3_stream_ensure_chunk(stream, len);
  259. if (rv != 0) {
  260. return rv;
  261. }
  262. chunk = nghttp3_stream_get_chunk(stream);
  263. typed_buf_shared_init(&tbuf, chunk);
  264. chunk->last = nghttp3_put_varint(chunk->last, (int64_t)stream->type);
  265. tbuf.buf.last = chunk->last;
  266. return nghttp3_stream_outq_add(stream, &tbuf);
  267. }
  268. int nghttp3_stream_write_settings(nghttp3_stream *stream,
  269. nghttp3_frame_entry *frent) {
  270. size_t len;
  271. int rv;
  272. nghttp3_buf *chunk;
  273. nghttp3_typed_buf tbuf;
  274. struct {
  275. nghttp3_frame_settings settings;
  276. nghttp3_settings_entry iv[15];
  277. } fr;
  278. nghttp3_settings_entry *iv;
  279. nghttp3_settings *local_settings = frent->aux.settings.local_settings;
  280. fr.settings.hd.type = NGHTTP3_FRAME_SETTINGS;
  281. fr.settings.niv = 3;
  282. iv = &fr.settings.iv[0];
  283. iv[0].id = NGHTTP3_SETTINGS_ID_MAX_FIELD_SECTION_SIZE;
  284. iv[0].value = local_settings->max_field_section_size;
  285. iv[1].id = NGHTTP3_SETTINGS_ID_QPACK_MAX_TABLE_CAPACITY;
  286. iv[1].value = local_settings->qpack_max_dtable_capacity;
  287. iv[2].id = NGHTTP3_SETTINGS_ID_QPACK_BLOCKED_STREAMS;
  288. iv[2].value = local_settings->qpack_blocked_streams;
  289. if (local_settings->h3_datagram) {
  290. iv[fr.settings.niv].id = NGHTTP3_SETTINGS_ID_H3_DATAGRAM;
  291. iv[fr.settings.niv].value = 1;
  292. ++fr.settings.niv;
  293. }
  294. if (local_settings->enable_connect_protocol) {
  295. iv[fr.settings.niv].id = NGHTTP3_SETTINGS_ID_ENABLE_CONNECT_PROTOCOL;
  296. iv[fr.settings.niv].value = 1;
  297. ++fr.settings.niv;
  298. }
  299. len = nghttp3_frame_write_settings_len(&fr.settings.hd.length, &fr.settings);
  300. rv = nghttp3_stream_ensure_chunk(stream, len);
  301. if (rv != 0) {
  302. return rv;
  303. }
  304. chunk = nghttp3_stream_get_chunk(stream);
  305. typed_buf_shared_init(&tbuf, chunk);
  306. chunk->last = nghttp3_frame_write_settings(chunk->last, &fr.settings);
  307. tbuf.buf.last = chunk->last;
  308. return nghttp3_stream_outq_add(stream, &tbuf);
  309. }
  310. int nghttp3_stream_write_goaway(nghttp3_stream *stream,
  311. nghttp3_frame_entry *frent) {
  312. nghttp3_frame_goaway *fr = &frent->fr.goaway;
  313. size_t len;
  314. int rv;
  315. nghttp3_buf *chunk;
  316. nghttp3_typed_buf tbuf;
  317. len = nghttp3_frame_write_goaway_len(&fr->hd.length, fr);
  318. rv = nghttp3_stream_ensure_chunk(stream, len);
  319. if (rv != 0) {
  320. return rv;
  321. }
  322. chunk = nghttp3_stream_get_chunk(stream);
  323. typed_buf_shared_init(&tbuf, chunk);
  324. chunk->last = nghttp3_frame_write_goaway(chunk->last, fr);
  325. tbuf.buf.last = chunk->last;
  326. return nghttp3_stream_outq_add(stream, &tbuf);
  327. }
  328. int nghttp3_stream_write_priority_update(nghttp3_stream *stream,
  329. nghttp3_frame_entry *frent) {
  330. nghttp3_frame_priority_update *fr = &frent->fr.priority_update;
  331. size_t len;
  332. int rv;
  333. nghttp3_buf *chunk;
  334. nghttp3_typed_buf tbuf;
  335. len = nghttp3_frame_write_priority_update_len(&fr->hd.length, fr);
  336. rv = nghttp3_stream_ensure_chunk(stream, len);
  337. if (rv != 0) {
  338. return rv;
  339. }
  340. chunk = nghttp3_stream_get_chunk(stream);
  341. typed_buf_shared_init(&tbuf, chunk);
  342. chunk->last = nghttp3_frame_write_priority_update(chunk->last, fr);
  343. tbuf.buf.last = chunk->last;
  344. return nghttp3_stream_outq_add(stream, &tbuf);
  345. }
  346. int nghttp3_stream_write_headers(nghttp3_stream *stream,
  347. nghttp3_frame_entry *frent) {
  348. nghttp3_frame_headers *fr = &frent->fr.headers;
  349. nghttp3_conn *conn = stream->conn;
  350. assert(conn);
  351. return nghttp3_stream_write_header_block(
  352. stream, &conn->qenc, conn->tx.qenc, &conn->tx.qpack.rbuf,
  353. &conn->tx.qpack.ebuf, NGHTTP3_FRAME_HEADERS, fr->nva, fr->nvlen);
  354. }
  355. int nghttp3_stream_write_header_block(nghttp3_stream *stream,
  356. nghttp3_qpack_encoder *qenc,
  357. nghttp3_stream *qenc_stream,
  358. nghttp3_buf *rbuf, nghttp3_buf *ebuf,
  359. int64_t frame_type, const nghttp3_nv *nva,
  360. size_t nvlen) {
  361. nghttp3_buf pbuf;
  362. int rv;
  363. size_t len;
  364. nghttp3_buf *chunk;
  365. nghttp3_typed_buf tbuf;
  366. nghttp3_frame_hd hd;
  367. uint8_t raw_pbuf[16];
  368. size_t pbuflen, rbuflen, ebuflen;
  369. nghttp3_buf_wrap_init(&pbuf, raw_pbuf, sizeof(raw_pbuf));
  370. rv = nghttp3_qpack_encoder_encode(qenc, &pbuf, rbuf, ebuf, stream->node.id,
  371. nva, nvlen);
  372. if (rv != 0) {
  373. goto fail;
  374. }
  375. pbuflen = nghttp3_buf_len(&pbuf);
  376. rbuflen = nghttp3_buf_len(rbuf);
  377. ebuflen = nghttp3_buf_len(ebuf);
  378. hd.type = frame_type;
  379. hd.length = (int64_t)(pbuflen + rbuflen);
  380. len = nghttp3_frame_write_hd_len(&hd) + pbuflen;
  381. if (rbuflen <= NGHTTP3_STREAM_MAX_COPY_THRES) {
  382. len += rbuflen;
  383. }
  384. rv = nghttp3_stream_ensure_chunk(stream, len);
  385. if (rv != 0) {
  386. goto fail;
  387. }
  388. chunk = nghttp3_stream_get_chunk(stream);
  389. typed_buf_shared_init(&tbuf, chunk);
  390. chunk->last = nghttp3_frame_write_hd(chunk->last, &hd);
  391. chunk->last = nghttp3_cpymem(chunk->last, pbuf.pos, pbuflen);
  392. nghttp3_buf_init(&pbuf);
  393. if (rbuflen > NGHTTP3_STREAM_MAX_COPY_THRES) {
  394. tbuf.buf.last = chunk->last;
  395. rv = nghttp3_stream_outq_add(stream, &tbuf);
  396. if (rv != 0) {
  397. goto fail;
  398. }
  399. nghttp3_typed_buf_init(&tbuf, rbuf, NGHTTP3_BUF_TYPE_PRIVATE);
  400. rv = nghttp3_stream_outq_add(stream, &tbuf);
  401. if (rv != 0) {
  402. goto fail;
  403. }
  404. nghttp3_buf_init(rbuf);
  405. } else if (rbuflen) {
  406. chunk->last = nghttp3_cpymem(chunk->last, rbuf->pos, rbuflen);
  407. tbuf.buf.last = chunk->last;
  408. rv = nghttp3_stream_outq_add(stream, &tbuf);
  409. if (rv != 0) {
  410. goto fail;
  411. }
  412. nghttp3_buf_reset(rbuf);
  413. }
  414. if (ebuflen > NGHTTP3_STREAM_MAX_COPY_THRES) {
  415. assert(qenc_stream);
  416. nghttp3_typed_buf_init(&tbuf, ebuf, NGHTTP3_BUF_TYPE_PRIVATE);
  417. rv = nghttp3_stream_outq_add(qenc_stream, &tbuf);
  418. if (rv != 0) {
  419. return rv;
  420. }
  421. nghttp3_buf_init(ebuf);
  422. } else if (ebuflen) {
  423. assert(qenc_stream);
  424. rv = nghttp3_stream_ensure_chunk(qenc_stream, ebuflen);
  425. if (rv != 0) {
  426. goto fail;
  427. }
  428. chunk = nghttp3_stream_get_chunk(qenc_stream);
  429. typed_buf_shared_init(&tbuf, chunk);
  430. chunk->last = nghttp3_cpymem(chunk->last, ebuf->pos, ebuflen);
  431. tbuf.buf.last = chunk->last;
  432. rv = nghttp3_stream_outq_add(qenc_stream, &tbuf);
  433. if (rv != 0) {
  434. goto fail;
  435. }
  436. nghttp3_buf_reset(ebuf);
  437. }
  438. assert(0 == nghttp3_buf_len(&pbuf));
  439. assert(0 == nghttp3_buf_len(rbuf));
  440. assert(0 == nghttp3_buf_len(ebuf));
  441. return 0;
  442. fail:
  443. return rv;
  444. }
  445. int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof,
  446. nghttp3_frame_entry *frent) {
  447. int rv;
  448. size_t len;
  449. nghttp3_typed_buf tbuf;
  450. nghttp3_buf buf;
  451. nghttp3_buf *chunk;
  452. nghttp3_read_data_callback read_data = frent->aux.data.dr.read_data;
  453. nghttp3_conn *conn = stream->conn;
  454. int64_t datalen;
  455. uint32_t flags = 0;
  456. nghttp3_frame_hd hd;
  457. nghttp3_vec vec[8];
  458. nghttp3_vec *v;
  459. nghttp3_ssize sveccnt;
  460. size_t i;
  461. assert(!(stream->flags & NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED));
  462. assert(read_data);
  463. assert(conn);
  464. *peof = 0;
  465. sveccnt = read_data(conn, stream->node.id, vec, nghttp3_arraylen(vec), &flags,
  466. conn->user_data, stream->user_data);
  467. if (sveccnt < 0) {
  468. if (sveccnt == NGHTTP3_ERR_WOULDBLOCK) {
  469. stream->flags |= NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED;
  470. return 0;
  471. }
  472. return NGHTTP3_ERR_CALLBACK_FAILURE;
  473. }
  474. datalen = nghttp3_vec_len_varint(vec, (size_t)sveccnt);
  475. if (datalen == -1) {
  476. return NGHTTP3_ERR_STREAM_DATA_OVERFLOW;
  477. }
  478. assert(datalen || flags & NGHTTP3_DATA_FLAG_EOF);
  479. if (flags & NGHTTP3_DATA_FLAG_EOF) {
  480. *peof = 1;
  481. if (!(flags & NGHTTP3_DATA_FLAG_NO_END_STREAM)) {
  482. stream->flags |= NGHTTP3_STREAM_FLAG_WRITE_END_STREAM;
  483. if (datalen == 0) {
  484. if (nghttp3_stream_outq_write_done(stream)) {
  485. /* If this is the last data and its is 0 length, we don't
  486. need send DATA frame. We rely on the non-emptiness of
  487. outq to schedule stream, so add empty tbuf to outq to
  488. just send fin. */
  489. nghttp3_buf_init(&buf);
  490. nghttp3_typed_buf_init(&tbuf, &buf, NGHTTP3_BUF_TYPE_PRIVATE);
  491. return nghttp3_stream_outq_add(stream, &tbuf);
  492. }
  493. return 0;
  494. }
  495. }
  496. if (datalen == 0) {
  497. /* We are going to send more frames, but no DATA frame this
  498. time. */
  499. return 0;
  500. }
  501. }
  502. hd.type = NGHTTP3_FRAME_DATA;
  503. hd.length = datalen;
  504. len = nghttp3_frame_write_hd_len(&hd);
  505. rv = nghttp3_stream_ensure_chunk(stream, len);
  506. if (rv != 0) {
  507. return rv;
  508. }
  509. chunk = nghttp3_stream_get_chunk(stream);
  510. typed_buf_shared_init(&tbuf, chunk);
  511. chunk->last = nghttp3_frame_write_hd(chunk->last, &hd);
  512. tbuf.buf.last = chunk->last;
  513. rv = nghttp3_stream_outq_add(stream, &tbuf);
  514. if (rv != 0) {
  515. return rv;
  516. }
  517. if (datalen) {
  518. for (i = 0; i < (size_t)sveccnt; ++i) {
  519. v = &vec[i];
  520. if (v->len == 0) {
  521. continue;
  522. }
  523. nghttp3_buf_wrap_init(&buf, v->base, v->len);
  524. buf.last = buf.end;
  525. nghttp3_typed_buf_init(&tbuf, &buf, NGHTTP3_BUF_TYPE_ALIEN);
  526. rv = nghttp3_stream_outq_add(stream, &tbuf);
  527. if (rv != 0) {
  528. return rv;
  529. }
  530. }
  531. }
  532. return 0;
  533. }
  534. int nghttp3_stream_write_qpack_decoder_stream(nghttp3_stream *stream) {
  535. nghttp3_qpack_decoder *qdec;
  536. nghttp3_buf *chunk;
  537. int rv;
  538. nghttp3_typed_buf tbuf;
  539. size_t len;
  540. assert(stream->conn);
  541. assert(stream->conn->tx.qdec == stream);
  542. qdec = &stream->conn->qdec;
  543. assert(qdec);
  544. len = nghttp3_qpack_decoder_get_decoder_streamlen(qdec);
  545. if (len == 0) {
  546. return 0;
  547. }
  548. rv = nghttp3_stream_ensure_chunk(stream, len);
  549. if (rv != 0) {
  550. return rv;
  551. }
  552. chunk = nghttp3_stream_get_chunk(stream);
  553. typed_buf_shared_init(&tbuf, chunk);
  554. nghttp3_qpack_decoder_write_decoder(qdec, chunk);
  555. tbuf.buf.last = chunk->last;
  556. return nghttp3_stream_outq_add(stream, &tbuf);
  557. }
  558. int nghttp3_stream_outq_add(nghttp3_stream *stream,
  559. const nghttp3_typed_buf *tbuf) {
  560. nghttp3_ringbuf *outq = &stream->outq;
  561. int rv;
  562. nghttp3_typed_buf *dest;
  563. size_t len = nghttp3_ringbuf_len(outq);
  564. size_t buflen = nghttp3_buf_len(&tbuf->buf);
  565. if (buflen > NGHTTP3_MAX_VARINT - stream->tx.offset) {
  566. return NGHTTP3_ERR_STREAM_DATA_OVERFLOW;
  567. }
  568. stream->tx.offset += buflen;
  569. stream->unsent_bytes += buflen;
  570. if (len) {
  571. dest = nghttp3_ringbuf_get(outq, len - 1);
  572. if (dest->type == tbuf->type && dest->type == NGHTTP3_BUF_TYPE_SHARED &&
  573. dest->buf.begin == tbuf->buf.begin && dest->buf.last == tbuf->buf.pos) {
  574. /* If we have already written last entry, adjust outq_idx and
  575. offset so that this entry is eligible to send. */
  576. if (len == stream->outq_idx) {
  577. --stream->outq_idx;
  578. stream->outq_offset = nghttp3_buf_len(&dest->buf);
  579. }
  580. dest->buf.last = tbuf->buf.last;
  581. /* TODO Is this required? */
  582. dest->buf.end = tbuf->buf.end;
  583. return 0;
  584. }
  585. }
  586. if (nghttp3_ringbuf_full(outq)) {
  587. size_t nlen = nghttp3_max_size(NGHTTP3_MIN_RBLEN, len * 2);
  588. rv = nghttp3_ringbuf_reserve(outq, nlen);
  589. if (rv != 0) {
  590. return rv;
  591. }
  592. }
  593. dest = nghttp3_ringbuf_push_back(outq);
  594. *dest = *tbuf;
  595. return 0;
  596. }
  597. int nghttp3_stream_ensure_chunk(nghttp3_stream *stream, size_t need) {
  598. nghttp3_ringbuf *chunks = &stream->chunks;
  599. nghttp3_buf *chunk;
  600. size_t len = nghttp3_ringbuf_len(chunks);
  601. uint8_t *p;
  602. int rv;
  603. size_t n = NGHTTP3_STREAM_MIN_CHUNK_SIZE;
  604. if (len) {
  605. chunk = nghttp3_ringbuf_get(chunks, len - 1);
  606. if (nghttp3_buf_left(chunk) >= need) {
  607. return 0;
  608. }
  609. }
  610. for (; n < need; n *= 2)
  611. ;
  612. if (n == NGHTTP3_STREAM_MIN_CHUNK_SIZE) {
  613. p =
  614. (uint8_t *)nghttp3_objalloc_chunk_len_get(stream->out_chunk_objalloc, n);
  615. } else {
  616. p = nghttp3_mem_malloc(stream->mem, n);
  617. }
  618. if (p == NULL) {
  619. return NGHTTP3_ERR_NOMEM;
  620. }
  621. if (nghttp3_ringbuf_full(chunks)) {
  622. size_t nlen = nghttp3_max_size(NGHTTP3_MIN_RBLEN, len * 2);
  623. rv = nghttp3_ringbuf_reserve(chunks, nlen);
  624. if (rv != 0) {
  625. return rv;
  626. }
  627. }
  628. chunk = nghttp3_ringbuf_push_back(chunks);
  629. nghttp3_buf_wrap_init(chunk, p, n);
  630. return 0;
  631. }
  632. nghttp3_buf *nghttp3_stream_get_chunk(nghttp3_stream *stream) {
  633. nghttp3_ringbuf *chunks = &stream->chunks;
  634. size_t len = nghttp3_ringbuf_len(chunks);
  635. assert(len);
  636. return nghttp3_ringbuf_get(chunks, len - 1);
  637. }
  638. int nghttp3_stream_is_blocked(nghttp3_stream *stream) {
  639. return (stream->flags & NGHTTP3_STREAM_FLAG_FC_BLOCKED) ||
  640. (stream->flags & NGHTTP3_STREAM_FLAG_SHUT_WR) ||
  641. (stream->flags & NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED);
  642. }
  643. int nghttp3_stream_require_schedule(nghttp3_stream *stream) {
  644. return (!nghttp3_stream_outq_write_done(stream) &&
  645. !(stream->flags & NGHTTP3_STREAM_FLAG_FC_BLOCKED) &&
  646. !(stream->flags & NGHTTP3_STREAM_FLAG_SHUT_WR)) ||
  647. (nghttp3_ringbuf_len(&stream->frq) &&
  648. !(stream->flags & NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED));
  649. }
  650. size_t nghttp3_stream_writev(nghttp3_stream *stream, int *pfin,
  651. nghttp3_vec *vec, size_t veccnt) {
  652. nghttp3_ringbuf *outq = &stream->outq;
  653. size_t len = nghttp3_ringbuf_len(outq);
  654. size_t i = stream->outq_idx;
  655. uint64_t offset = stream->outq_offset;
  656. size_t buflen;
  657. nghttp3_vec *vbegin = vec, *vend = vec + veccnt;
  658. nghttp3_typed_buf *tbuf;
  659. assert(veccnt > 0);
  660. if (i < len) {
  661. tbuf = nghttp3_ringbuf_get(outq, i);
  662. buflen = nghttp3_buf_len(&tbuf->buf);
  663. if (offset < buflen) {
  664. vec->base = tbuf->buf.pos + offset;
  665. vec->len = (size_t)(buflen - offset);
  666. ++vec;
  667. } else {
  668. /* This is the only case that satisfies offset >= buflen */
  669. assert(0 == offset);
  670. assert(0 == buflen);
  671. }
  672. ++i;
  673. for (; i < len && vec != vend; ++i, ++vec) {
  674. tbuf = nghttp3_ringbuf_get(outq, i);
  675. vec->base = tbuf->buf.pos;
  676. vec->len = nghttp3_buf_len(&tbuf->buf);
  677. }
  678. }
  679. /* TODO Rework this if we have finished implementing HTTP
  680. messaging */
  681. *pfin = nghttp3_ringbuf_len(&stream->frq) == 0 && i == len &&
  682. (stream->flags & NGHTTP3_STREAM_FLAG_WRITE_END_STREAM);
  683. return (size_t)(vec - vbegin);
  684. }
  685. void nghttp3_stream_add_outq_offset(nghttp3_stream *stream, size_t n) {
  686. nghttp3_ringbuf *outq = &stream->outq;
  687. size_t i;
  688. size_t len = nghttp3_ringbuf_len(outq);
  689. uint64_t offset = stream->outq_offset + n;
  690. size_t buflen;
  691. nghttp3_typed_buf *tbuf;
  692. for (i = stream->outq_idx; i < len; ++i) {
  693. tbuf = nghttp3_ringbuf_get(outq, i);
  694. buflen = nghttp3_buf_len(&tbuf->buf);
  695. if (offset >= buflen) {
  696. offset -= buflen;
  697. continue;
  698. }
  699. break;
  700. }
  701. assert(i < len || offset == 0);
  702. stream->unsent_bytes -= n;
  703. stream->outq_idx = i;
  704. stream->outq_offset = offset;
  705. }
  706. int nghttp3_stream_outq_write_done(nghttp3_stream *stream) {
  707. nghttp3_ringbuf *outq = &stream->outq;
  708. size_t len = nghttp3_ringbuf_len(outq);
  709. return len == 0 || stream->outq_idx >= len;
  710. }
  711. static void stream_pop_outq_entry(nghttp3_stream *stream,
  712. nghttp3_typed_buf *tbuf) {
  713. nghttp3_ringbuf *chunks = &stream->chunks;
  714. nghttp3_buf *chunk;
  715. switch (tbuf->type) {
  716. case NGHTTP3_BUF_TYPE_PRIVATE:
  717. nghttp3_buf_free(&tbuf->buf, stream->mem);
  718. break;
  719. case NGHTTP3_BUF_TYPE_ALIEN:
  720. break;
  721. case NGHTTP3_BUF_TYPE_SHARED:
  722. assert(nghttp3_ringbuf_len(chunks));
  723. chunk = nghttp3_ringbuf_get(chunks, 0);
  724. assert(chunk->begin == tbuf->buf.begin);
  725. assert(chunk->end == tbuf->buf.end);
  726. if (chunk->last == tbuf->buf.last) {
  727. if (nghttp3_buf_cap(chunk) == NGHTTP3_STREAM_MIN_CHUNK_SIZE) {
  728. nghttp3_objalloc_chunk_release(stream->out_chunk_objalloc,
  729. (nghttp3_chunk *)(void *)chunk->begin);
  730. } else {
  731. nghttp3_buf_free(chunk, stream->mem);
  732. }
  733. nghttp3_ringbuf_pop_front(chunks);
  734. }
  735. break;
  736. default:
  737. nghttp3_unreachable();
  738. };
  739. nghttp3_ringbuf_pop_front(&stream->outq);
  740. }
  741. int nghttp3_stream_update_ack_offset(nghttp3_stream *stream, uint64_t offset) {
  742. nghttp3_ringbuf *outq = &stream->outq;
  743. size_t buflen;
  744. size_t npopped = 0;
  745. uint64_t nack;
  746. nghttp3_typed_buf *tbuf;
  747. int rv;
  748. for (; nghttp3_ringbuf_len(outq);) {
  749. tbuf = nghttp3_ringbuf_get(outq, 0);
  750. buflen = nghttp3_buf_len(&tbuf->buf);
  751. /* For NGHTTP3_BUF_TYPE_ALIEN, we never add 0 length buffer. */
  752. if (tbuf->type == NGHTTP3_BUF_TYPE_ALIEN && stream->ack_offset < offset &&
  753. stream->callbacks.acked_data) {
  754. nack = nghttp3_min_uint64(offset, stream->ack_base + buflen) -
  755. stream->ack_offset;
  756. rv = stream->callbacks.acked_data(stream, stream->node.id, nack,
  757. stream->user_data);
  758. if (rv != 0) {
  759. return NGHTTP3_ERR_CALLBACK_FAILURE;
  760. }
  761. }
  762. if (offset >= stream->ack_base + buflen) {
  763. stream_pop_outq_entry(stream, tbuf);
  764. stream->ack_base += buflen;
  765. stream->ack_offset = stream->ack_base;
  766. ++npopped;
  767. if (stream->outq_idx + 1 == npopped) {
  768. stream->outq_offset = 0;
  769. break;
  770. }
  771. continue;
  772. }
  773. break;
  774. }
  775. assert(stream->outq_idx + 1 >= npopped);
  776. if (stream->outq_idx >= npopped) {
  777. stream->outq_idx -= npopped;
  778. } else {
  779. stream->outq_idx = 0;
  780. }
  781. stream->ack_offset = offset;
  782. return 0;
  783. }
  784. int nghttp3_stream_buffer_data(nghttp3_stream *stream, const uint8_t *data,
  785. size_t datalen) {
  786. nghttp3_ringbuf *inq = &stream->inq;
  787. size_t len = nghttp3_ringbuf_len(inq);
  788. nghttp3_buf *buf;
  789. size_t nwrite;
  790. uint8_t *rawbuf;
  791. size_t bufleft;
  792. int rv;
  793. if (len) {
  794. buf = nghttp3_ringbuf_get(inq, len - 1);
  795. bufleft = nghttp3_buf_left(buf);
  796. nwrite = nghttp3_min_size(datalen, bufleft);
  797. buf->last = nghttp3_cpymem(buf->last, data, nwrite);
  798. data += nwrite;
  799. datalen -= nwrite;
  800. }
  801. for (; datalen;) {
  802. if (nghttp3_ringbuf_full(inq)) {
  803. size_t nlen =
  804. nghttp3_max_size(NGHTTP3_MIN_RBLEN, nghttp3_ringbuf_len(inq) * 2);
  805. rv = nghttp3_ringbuf_reserve(inq, nlen);
  806. if (rv != 0) {
  807. return rv;
  808. }
  809. }
  810. rawbuf = nghttp3_mem_malloc(stream->mem, 16384);
  811. if (rawbuf == NULL) {
  812. return NGHTTP3_ERR_NOMEM;
  813. }
  814. buf = nghttp3_ringbuf_push_back(inq);
  815. nghttp3_buf_wrap_init(buf, rawbuf, 16384);
  816. bufleft = nghttp3_buf_left(buf);
  817. nwrite = nghttp3_min_size(datalen, bufleft);
  818. buf->last = nghttp3_cpymem(buf->last, data, nwrite);
  819. data += nwrite;
  820. datalen -= nwrite;
  821. }
  822. return 0;
  823. }
  824. size_t nghttp3_stream_get_buffered_datalen(nghttp3_stream *stream) {
  825. nghttp3_ringbuf *inq = &stream->inq;
  826. size_t len = nghttp3_ringbuf_len(inq);
  827. size_t i, n = 0;
  828. nghttp3_buf *buf;
  829. for (i = 0; i < len; ++i) {
  830. buf = nghttp3_ringbuf_get(inq, i);
  831. n += nghttp3_buf_len(buf);
  832. }
  833. return n;
  834. }
  835. int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
  836. nghttp3_stream_http_event event) {
  837. int rv;
  838. switch (stream->rx.hstate) {
  839. case NGHTTP3_HTTP_STATE_NONE:
  840. return NGHTTP3_ERR_H3_INTERNAL_ERROR;
  841. case NGHTTP3_HTTP_STATE_REQ_INITIAL:
  842. switch (event) {
  843. case NGHTTP3_HTTP_EVENT_HEADERS_BEGIN:
  844. stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN;
  845. return 0;
  846. default:
  847. return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
  848. }
  849. case NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN:
  850. if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
  851. return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
  852. }
  853. stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_HEADERS_END;
  854. return 0;
  855. case NGHTTP3_HTTP_STATE_REQ_HEADERS_END:
  856. switch (event) {
  857. case NGHTTP3_HTTP_EVENT_HEADERS_BEGIN:
  858. /* TODO Better to check status code */
  859. if (stream->rx.http.flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) {
  860. return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
  861. }
  862. stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN;
  863. return 0;
  864. case NGHTTP3_HTTP_EVENT_DATA_BEGIN:
  865. stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_DATA_BEGIN;
  866. return 0;
  867. case NGHTTP3_HTTP_EVENT_MSG_END:
  868. rv = nghttp3_http_on_remote_end_stream(stream);
  869. if (rv != 0) {
  870. return rv;
  871. }
  872. stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
  873. return 0;
  874. default:
  875. return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
  876. }
  877. case NGHTTP3_HTTP_STATE_REQ_DATA_BEGIN:
  878. if (event != NGHTTP3_HTTP_EVENT_DATA_END) {
  879. return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
  880. }
  881. stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_DATA_END;
  882. return 0;
  883. case NGHTTP3_HTTP_STATE_REQ_DATA_END:
  884. switch (event) {
  885. case NGHTTP3_HTTP_EVENT_DATA_BEGIN:
  886. stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_DATA_BEGIN;
  887. return 0;
  888. case NGHTTP3_HTTP_EVENT_HEADERS_BEGIN:
  889. /* TODO Better to check status code */
  890. if (stream->rx.http.flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) {
  891. return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
  892. }
  893. stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN;
  894. return 0;
  895. case NGHTTP3_HTTP_EVENT_MSG_END:
  896. rv = nghttp3_http_on_remote_end_stream(stream);
  897. if (rv != 0) {
  898. return rv;
  899. }
  900. stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
  901. return 0;
  902. default:
  903. return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
  904. }
  905. case NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN:
  906. if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
  907. return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
  908. }
  909. stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_TRAILERS_END;
  910. return 0;
  911. case NGHTTP3_HTTP_STATE_REQ_TRAILERS_END:
  912. if (event != NGHTTP3_HTTP_EVENT_MSG_END) {
  913. /* TODO Should ignore unexpected frame in this state as per
  914. spec. */
  915. return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
  916. }
  917. rv = nghttp3_http_on_remote_end_stream(stream);
  918. if (rv != 0) {
  919. return rv;
  920. }
  921. stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
  922. return 0;
  923. case NGHTTP3_HTTP_STATE_REQ_END:
  924. return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
  925. case NGHTTP3_HTTP_STATE_RESP_INITIAL:
  926. if (event != NGHTTP3_HTTP_EVENT_HEADERS_BEGIN) {
  927. return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
  928. }
  929. stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN;
  930. return 0;
  931. case NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN:
  932. if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
  933. return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
  934. }
  935. stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_HEADERS_END;
  936. return 0;
  937. case NGHTTP3_HTTP_STATE_RESP_HEADERS_END:
  938. switch (event) {
  939. case NGHTTP3_HTTP_EVENT_HEADERS_BEGIN:
  940. if (stream->rx.http.status_code == -1) {
  941. stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN;
  942. return 0;
  943. }
  944. if ((stream->rx.http.flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) &&
  945. stream->rx.http.status_code / 100 == 2) {
  946. return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
  947. }
  948. stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN;
  949. return 0;
  950. case NGHTTP3_HTTP_EVENT_DATA_BEGIN:
  951. if (stream->rx.http.flags & NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE) {
  952. return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
  953. }
  954. stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_DATA_BEGIN;
  955. return 0;
  956. case NGHTTP3_HTTP_EVENT_MSG_END:
  957. rv = nghttp3_http_on_remote_end_stream(stream);
  958. if (rv != 0) {
  959. return rv;
  960. }
  961. stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
  962. return 0;
  963. default:
  964. return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
  965. }
  966. case NGHTTP3_HTTP_STATE_RESP_DATA_BEGIN:
  967. if (event != NGHTTP3_HTTP_EVENT_DATA_END) {
  968. return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
  969. }
  970. stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_DATA_END;
  971. return 0;
  972. case NGHTTP3_HTTP_STATE_RESP_DATA_END:
  973. switch (event) {
  974. case NGHTTP3_HTTP_EVENT_DATA_BEGIN:
  975. stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_DATA_BEGIN;
  976. return 0;
  977. case NGHTTP3_HTTP_EVENT_HEADERS_BEGIN:
  978. if ((stream->rx.http.flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) &&
  979. stream->rx.http.status_code / 100 == 2) {
  980. return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
  981. }
  982. stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN;
  983. return 0;
  984. case NGHTTP3_HTTP_EVENT_MSG_END:
  985. rv = nghttp3_http_on_remote_end_stream(stream);
  986. if (rv != 0) {
  987. return rv;
  988. }
  989. stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
  990. return 0;
  991. default:
  992. return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
  993. }
  994. case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
  995. if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
  996. return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
  997. }
  998. stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_TRAILERS_END;
  999. return 0;
  1000. case NGHTTP3_HTTP_STATE_RESP_TRAILERS_END:
  1001. if (event != NGHTTP3_HTTP_EVENT_MSG_END) {
  1002. return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
  1003. }
  1004. rv = nghttp3_http_on_remote_end_stream(stream);
  1005. if (rv != 0) {
  1006. return rv;
  1007. }
  1008. stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
  1009. return 0;
  1010. case NGHTTP3_HTTP_STATE_RESP_END:
  1011. return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
  1012. default:
  1013. nghttp3_unreachable();
  1014. }
  1015. }
  1016. int nghttp3_stream_empty_headers_allowed(nghttp3_stream *stream) {
  1017. switch (stream->rx.hstate) {
  1018. case NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN:
  1019. case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
  1020. return 0;
  1021. default:
  1022. return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
  1023. }
  1024. }
  1025. int nghttp3_stream_uni(int64_t stream_id) { return (stream_id & 0x2) != 0; }
  1026. int nghttp3_client_stream_bidi(int64_t stream_id) {
  1027. return (stream_id & 0x3) == 0;
  1028. }
  1029. int nghttp3_client_stream_uni(int64_t stream_id) {
  1030. return (stream_id & 0x3) == 0x2;
  1031. }
  1032. int nghttp3_server_stream_uni(int64_t stream_id) {
  1033. return (stream_id & 0x3) == 0x3;
  1034. }