http2.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation:
  9. * version 2.1 of the License.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  19. * MA 02110-1301 USA
  20. */
  21. #include "private-libwebsockets.h"
  22. const struct http2_settings lws_http2_default_settings = { {
  23. 0,
  24. /* LWS_HTTP2_SETTINGS__HEADER_TABLE_SIZE */ 4096,
  25. /* LWS_HTTP2_SETTINGS__ENABLE_PUSH */ 1,
  26. /* LWS_HTTP2_SETTINGS__MAX_CONCURRENT_STREAMS */ 100,
  27. /* LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE */ 65535,
  28. /* LWS_HTTP2_SETTINGS__MAX_FRAME_SIZE */ 16384,
  29. /* LWS_HTTP2_SETTINGS__MAX_HEADER_LIST_SIZE */ ~0,
  30. }};
  31. void lws_http2_init(struct http2_settings *settings)
  32. {
  33. memcpy(settings, lws_http2_default_settings.setting, sizeof(*settings));
  34. }
  35. struct lws *
  36. lws_http2_wsi_from_id(struct lws *wsi, unsigned int sid)
  37. {
  38. do {
  39. if (wsi->u.http2.my_stream_id == sid)
  40. return wsi;
  41. wsi = wsi->u.http2.next_child_wsi;
  42. } while (wsi);
  43. return NULL;
  44. }
  45. struct lws *
  46. lws_create_server_child_wsi(struct lws_vhost *vhost, struct lws *parent_wsi,
  47. unsigned int sid)
  48. {
  49. struct lws *wsi = lws_create_new_server_wsi(vhost);
  50. if (!wsi)
  51. return NULL;
  52. /* no more children allowed by parent */
  53. if (parent_wsi->u.http2.child_count + 1 ==
  54. parent_wsi->u.http2.peer_settings.setting[
  55. LWS_HTTP2_SETTINGS__MAX_CONCURRENT_STREAMS])
  56. goto bail;
  57. lws_http2_init(&wsi->u.http2.peer_settings);
  58. lws_http2_init(&wsi->u.http2.my_settings);
  59. wsi->u.http2.stream_id = sid;
  60. wsi->u.http2.my_stream_id = sid;
  61. wsi->u.http2.parent_wsi = parent_wsi;
  62. wsi->u.http2.next_child_wsi = parent_wsi->u.http2.next_child_wsi;
  63. parent_wsi->u.http2.next_child_wsi = wsi;
  64. parent_wsi->u.http2.child_count++;
  65. wsi->u.http2.my_priority = 16;
  66. wsi->u.http2.tx_credit = 65535;
  67. wsi->state = LWSS_HTTP2_ESTABLISHED;
  68. wsi->mode = parent_wsi->mode;
  69. wsi->protocol = &vhost->protocols[0];
  70. if (lws_ensure_user_space(wsi))
  71. goto bail;
  72. lwsl_info("%s: %p new child %p, sid %d, user_space=%p\n", __func__,
  73. parent_wsi, wsi, sid, wsi->user_space);
  74. return wsi;
  75. bail:
  76. vhost->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY,
  77. NULL, NULL, 0);
  78. lws_free(wsi);
  79. return NULL;
  80. }
  81. int lws_remove_server_child_wsi(struct lws_context *context, struct lws *wsi)
  82. {
  83. struct lws **w = &wsi->u.http2.parent_wsi;
  84. do {
  85. if (*w == wsi) {
  86. *w = wsi->u.http2.next_child_wsi;
  87. (wsi->u.http2.parent_wsi)->u.http2.child_count--;
  88. return 0;
  89. }
  90. w = &((*w)->u.http2.next_child_wsi);
  91. } while (*w);
  92. lwsl_err("%s: can't find %p\n", __func__, wsi);
  93. return 1;
  94. }
  95. int
  96. lws_http2_interpret_settings_payload(struct http2_settings *settings,
  97. unsigned char *buf, int len)
  98. {
  99. unsigned int a, b;
  100. if (!len)
  101. return 0;
  102. if (len < LWS_HTTP2_SETTINGS_LENGTH)
  103. return 1;
  104. while (len >= LWS_HTTP2_SETTINGS_LENGTH) {
  105. a = (buf[0] << 8) | buf[1];
  106. if (a < LWS_HTTP2_SETTINGS__COUNT) {
  107. b = buf[2] << 24 | buf[3] << 16 | buf[4] << 8 | buf[5];
  108. settings->setting[a] = b;
  109. lwsl_info("http2 settings %d <- 0x%x\n", a, b);
  110. }
  111. len -= LWS_HTTP2_SETTINGS_LENGTH;
  112. buf += LWS_HTTP2_SETTINGS_LENGTH;
  113. }
  114. if (len)
  115. return 1;
  116. return 0;
  117. }
  118. struct lws *lws_http2_get_network_wsi(struct lws *wsi)
  119. {
  120. while (wsi->u.http2.parent_wsi)
  121. wsi = wsi->u.http2.parent_wsi;
  122. return wsi;
  123. }
  124. int lws_http2_frame_write(struct lws *wsi, int type, int flags,
  125. unsigned int sid, unsigned int len, unsigned char *buf)
  126. {
  127. struct lws *wsi_eff = lws_http2_get_network_wsi(wsi);
  128. unsigned char *p = &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH];
  129. int n;
  130. *p++ = len >> 16;
  131. *p++ = len >> 8;
  132. *p++ = len;
  133. *p++ = type;
  134. *p++ = flags;
  135. *p++ = sid >> 24;
  136. *p++ = sid >> 16;
  137. *p++ = sid >> 8;
  138. *p++ = sid;
  139. lwsl_info("%s: %p (eff %p). type %d, flags 0x%x, sid=%d, len=%d, tx_credit=%d\n",
  140. __func__, wsi, wsi_eff, type, flags, sid, len,
  141. wsi->u.http2.tx_credit);
  142. if (type == LWS_HTTP2_FRAME_TYPE_DATA) {
  143. if (wsi->u.http2.tx_credit < len)
  144. lwsl_err("%s: %p: sending payload len %d"
  145. " but tx_credit only %d!\n", __func__, wsi, len,
  146. wsi->u.http2.tx_credit);
  147. wsi->u.http2.tx_credit -= len;
  148. }
  149. n = lws_issue_raw(wsi_eff, &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH],
  150. len + LWS_HTTP2_FRAME_HEADER_LENGTH);
  151. if (n >= LWS_HTTP2_FRAME_HEADER_LENGTH)
  152. return n - LWS_HTTP2_FRAME_HEADER_LENGTH;
  153. return n;
  154. }
  155. static void lws_http2_settings_write(struct lws *wsi, int n, unsigned char *buf)
  156. {
  157. *buf++ = n >> 8;
  158. *buf++ = n;
  159. *buf++ = wsi->u.http2.my_settings.setting[n] >> 24;
  160. *buf++ = wsi->u.http2.my_settings.setting[n] >> 16;
  161. *buf++ = wsi->u.http2.my_settings.setting[n] >> 8;
  162. *buf = wsi->u.http2.my_settings.setting[n];
  163. }
  164. static const char * https_client_preface =
  165. "PRI * HTTP/2.0\x0d\x0a\x0d\x0aSM\x0d\x0a\x0d\x0a";
  166. int
  167. lws_http2_parser(struct lws *wsi, unsigned char c)
  168. {
  169. struct lws *swsi;
  170. int n;
  171. switch (wsi->state) {
  172. case LWSS_HTTP2_AWAIT_CLIENT_PREFACE:
  173. if (https_client_preface[wsi->u.http2.count++] != c)
  174. return 1;
  175. if (!https_client_preface[wsi->u.http2.count]) {
  176. lwsl_info("http2: %p: established\n", wsi);
  177. wsi->state = LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS;
  178. wsi->u.http2.count = 0;
  179. wsi->u.http2.tx_credit = 65535;
  180. /*
  181. * we must send a settings frame -- empty one is OK...
  182. * that must be the first thing sent by server
  183. * and the peer must send a SETTINGS with ACK flag...
  184. */
  185. lws_set_protocol_write_pending(wsi,
  186. LWS_PPS_HTTP2_MY_SETTINGS);
  187. }
  188. break;
  189. case LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS:
  190. case LWSS_HTTP2_ESTABLISHED:
  191. if (wsi->u.http2.frame_state == LWS_HTTP2_FRAME_HEADER_LENGTH) { // payload
  192. wsi->u.http2.count++;
  193. wsi->u.http2.stream_wsi->u.http2.count = wsi->u.http2.count;
  194. /* applies to wsi->u.http2.stream_wsi which may be wsi*/
  195. switch(wsi->u.http2.type) {
  196. case LWS_HTTP2_FRAME_TYPE_SETTINGS:
  197. wsi->u.http2.stream_wsi->u.http2.one_setting[wsi->u.http2.count % LWS_HTTP2_SETTINGS_LENGTH] = c;
  198. if (wsi->u.http2.count % LWS_HTTP2_SETTINGS_LENGTH == LWS_HTTP2_SETTINGS_LENGTH - 1)
  199. if (lws_http2_interpret_settings_payload(
  200. &wsi->u.http2.stream_wsi->u.http2.peer_settings,
  201. wsi->u.http2.one_setting,
  202. LWS_HTTP2_SETTINGS_LENGTH))
  203. return 1;
  204. break;
  205. case LWS_HTTP2_FRAME_TYPE_CONTINUATION:
  206. case LWS_HTTP2_FRAME_TYPE_HEADERS:
  207. lwsl_info(" %02X\n", c);
  208. if (!wsi->u.http2.stream_wsi->u.hdr.ah)
  209. if (lws_header_table_attach(wsi->u.http2.stream_wsi, 0)) {
  210. lwsl_err("%s: Failed to get ah\n", __func__);
  211. return 1;
  212. }
  213. if (lws_hpack_interpret(wsi->u.http2.stream_wsi, c)) {
  214. lwsl_notice("%s: lws_hpack_interpret failed\n", __func__);
  215. return 1;
  216. }
  217. break;
  218. case LWS_HTTP2_FRAME_TYPE_GOAWAY:
  219. if (wsi->u.http2.count >= 5 && wsi->u.http2.count <= 8) {
  220. wsi->u.http2.hpack_e_dep <<= 8;
  221. wsi->u.http2.hpack_e_dep |= c;
  222. if (wsi->u.http2.count == 8) {
  223. lwsl_info("goaway err 0x%x\n", wsi->u.http2.hpack_e_dep);
  224. }
  225. }
  226. wsi->u.http2.GOING_AWAY = 1;
  227. break;
  228. case LWS_HTTP2_FRAME_TYPE_DATA:
  229. break;
  230. case LWS_HTTP2_FRAME_TYPE_PRIORITY:
  231. break;
  232. case LWS_HTTP2_FRAME_TYPE_RST_STREAM:
  233. break;
  234. case LWS_HTTP2_FRAME_TYPE_PUSH_PROMISE:
  235. break;
  236. case LWS_HTTP2_FRAME_TYPE_PING:
  237. if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack
  238. } else { /* they're sending us a ping request */
  239. if (wsi->u.http2.count > 8)
  240. return 1;
  241. wsi->u.http2.ping_payload[wsi->u.http2.count - 1] = c;
  242. }
  243. break;
  244. case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE:
  245. wsi->u.http2.hpack_e_dep <<= 8;
  246. wsi->u.http2.hpack_e_dep |= c;
  247. break;
  248. }
  249. if (wsi->u.http2.count != wsi->u.http2.length)
  250. break;
  251. /* end of frame */
  252. wsi->u.http2.frame_state = 0;
  253. wsi->u.http2.count = 0;
  254. swsi = wsi->u.http2.stream_wsi;
  255. /* set our initial window size */
  256. if (!wsi->u.http2.initialized) {
  257. wsi->u.http2.tx_credit = wsi->u.http2.peer_settings.setting[LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE];
  258. lwsl_info("initial tx credit on master conn %p: %d\n", wsi, wsi->u.http2.tx_credit);
  259. wsi->u.http2.initialized = 1;
  260. }
  261. switch (wsi->u.http2.type) {
  262. case LWS_HTTP2_FRAME_TYPE_HEADERS:
  263. /* service the http request itself */
  264. lwsl_info("servicing initial http request, wsi=%p, stream wsi=%p\n", wsi, wsi->u.http2.stream_wsi);
  265. n = lws_http_action(swsi);
  266. (void)n;
  267. lwsl_info(" action result %d\n", n);
  268. break;
  269. case LWS_HTTP2_FRAME_TYPE_PING:
  270. if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack
  271. } else { /* they're sending us a ping request */
  272. lws_set_protocol_write_pending(wsi, LWS_PPS_HTTP2_PONG);
  273. }
  274. break;
  275. case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE:
  276. wsi->u.http2.hpack_e_dep &= ~(1 << 31);
  277. if ((long long)swsi->u.http2.tx_credit + (unsigned long long)wsi->u.http2.hpack_e_dep > (~(1 << 31)))
  278. return 1; /* actually need to close swsi not the whole show */
  279. swsi->u.http2.tx_credit += wsi->u.http2.hpack_e_dep;
  280. if (swsi->u.http2.waiting_tx_credit && swsi->u.http2.tx_credit > 0) {
  281. lwsl_info("%s: %p: waiting_tx_credit -> wait on writeable\n", __func__, wsi);
  282. swsi->u.http2.waiting_tx_credit = 0;
  283. lws_callback_on_writable(swsi);
  284. }
  285. break;
  286. }
  287. break;
  288. }
  289. switch (wsi->u.http2.frame_state++) {
  290. case 0:
  291. wsi->u.http2.length = c;
  292. break;
  293. case 1:
  294. case 2:
  295. wsi->u.http2.length <<= 8;
  296. wsi->u.http2.length |= c;
  297. break;
  298. case 3:
  299. wsi->u.http2.type = c;
  300. break;
  301. case 4:
  302. wsi->u.http2.flags = c;
  303. break;
  304. case 5:
  305. case 6:
  306. case 7:
  307. case 8:
  308. wsi->u.http2.stream_id <<= 8;
  309. wsi->u.http2.stream_id |= c;
  310. break;
  311. }
  312. if (wsi->u.http2.frame_state == LWS_HTTP2_FRAME_HEADER_LENGTH) { /* frame header complete */
  313. lwsl_info("frame: type 0x%x, flags 0x%x, sid 0x%x, len 0x%x\n",
  314. wsi->u.http2.type, wsi->u.http2.flags, wsi->u.http2.stream_id, wsi->u.http2.length);
  315. wsi->u.http2.count = 0;
  316. wsi->u.http2.stream_wsi = wsi;
  317. if (wsi->u.http2.stream_id)
  318. wsi->u.http2.stream_wsi = lws_http2_wsi_from_id(wsi, wsi->u.http2.stream_id);
  319. switch (wsi->u.http2.type) {
  320. case LWS_HTTP2_FRAME_TYPE_SETTINGS:
  321. /* nonzero sid on settings is illegal */
  322. if (wsi->u.http2.stream_id)
  323. return 1;
  324. if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack
  325. } else
  326. /* non-ACK coming in means we must ACK it */
  327. lws_set_protocol_write_pending(wsi, LWS_PPS_HTTP2_ACK_SETTINGS);
  328. break;
  329. case LWS_HTTP2_FRAME_TYPE_PING:
  330. if (wsi->u.http2.stream_id)
  331. return 1;
  332. if (wsi->u.http2.length != 8)
  333. return 1;
  334. break;
  335. case LWS_HTTP2_FRAME_TYPE_CONTINUATION:
  336. if (wsi->u.http2.END_HEADERS)
  337. return 1;
  338. goto update_end_headers;
  339. case LWS_HTTP2_FRAME_TYPE_HEADERS:
  340. lwsl_info("LWS_HTTP2_FRAME_TYPE_HEADERS: stream_id = %d\n", wsi->u.http2.stream_id);
  341. if (!wsi->u.http2.stream_id)
  342. return 1;
  343. if (!wsi->u.http2.stream_wsi) {
  344. wsi->u.http2.stream_wsi =
  345. lws_create_server_child_wsi(wsi->vhost, wsi, wsi->u.http2.stream_id);
  346. wsi->u.http2.stream_wsi->http2_substream = 1;
  347. }
  348. /* END_STREAM means after servicing this, close the stream */
  349. wsi->u.http2.END_STREAM = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_STREAM);
  350. lwsl_info("%s: headers END_STREAM = %d\n",__func__, wsi->u.http2.END_STREAM);
  351. update_end_headers:
  352. /* no END_HEADERS means CONTINUATION must come */
  353. wsi->u.http2.END_HEADERS = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_HEADERS);
  354. swsi = wsi->u.http2.stream_wsi;
  355. if (!swsi)
  356. return 1;
  357. /* prepare the hpack parser at the right start */
  358. swsi->u.http2.flags = wsi->u.http2.flags;
  359. swsi->u.http2.length = wsi->u.http2.length;
  360. swsi->u.http2.END_STREAM = wsi->u.http2.END_STREAM;
  361. if (swsi->u.http2.flags & LWS_HTTP2_FLAG_PADDED)
  362. swsi->u.http2.hpack = HPKS_OPT_PADDING;
  363. else
  364. if (swsi->u.http2.flags & LWS_HTTP2_FLAG_PRIORITY) {
  365. swsi->u.http2.hpack = HKPS_OPT_E_DEPENDENCY;
  366. swsi->u.http2.hpack_m = 4;
  367. } else
  368. swsi->u.http2.hpack = HPKS_TYPE;
  369. lwsl_info("initial hpack state %d\n", swsi->u.http2.hpack);
  370. break;
  371. case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE:
  372. if (wsi->u.http2.length != 4)
  373. return 1;
  374. break;
  375. }
  376. if (wsi->u.http2.length == 0)
  377. wsi->u.http2.frame_state = 0;
  378. }
  379. break;
  380. }
  381. return 0;
  382. }
  383. int lws_http2_do_pps_send(struct lws_context *context, struct lws *wsi)
  384. {
  385. unsigned char settings[LWS_PRE + 6 * LWS_HTTP2_SETTINGS__COUNT];
  386. struct lws *swsi;
  387. int n, m = 0;
  388. lwsl_debug("%s: %p: %d\n", __func__, wsi, wsi->pps);
  389. switch (wsi->pps) {
  390. case LWS_PPS_HTTP2_MY_SETTINGS:
  391. for (n = 1; n < LWS_HTTP2_SETTINGS__COUNT; n++)
  392. if (wsi->u.http2.my_settings.setting[n] != lws_http2_default_settings.setting[n]) {
  393. lws_http2_settings_write(wsi, n,
  394. &settings[LWS_PRE + m]);
  395. m += sizeof(wsi->u.http2.one_setting);
  396. }
  397. n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_SETTINGS,
  398. 0, LWS_HTTP2_STREAM_ID_MASTER, m,
  399. &settings[LWS_PRE]);
  400. if (n != m) {
  401. lwsl_info("send %d %d\n", n, m);
  402. return 1;
  403. }
  404. break;
  405. case LWS_PPS_HTTP2_ACK_SETTINGS:
  406. /* send ack ... always empty */
  407. n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_SETTINGS,
  408. 1, LWS_HTTP2_STREAM_ID_MASTER, 0,
  409. &settings[LWS_PRE]);
  410. if (n) {
  411. lwsl_err("ack tells %d\n", n);
  412. return 1;
  413. }
  414. /* this is the end of the preface dance then? */
  415. if (wsi->state == LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS) {
  416. wsi->state = LWSS_HTTP2_ESTABLISHED;
  417. wsi->u.http.fop_fd = NULL;
  418. if (lws_is_ssl(lws_http2_get_network_wsi(wsi))) {
  419. lwsl_info("skipping nonexistent ssl upgrade headers\n");
  420. break;
  421. }
  422. /*
  423. * we need to treat the headers from this upgrade
  424. * as the first job. These need to get
  425. * shifted to stream ID 1
  426. */
  427. lwsl_info("%s: setting up sid 1\n", __func__);
  428. swsi = wsi->u.http2.stream_wsi =
  429. lws_create_server_child_wsi(wsi->vhost, wsi, 1);
  430. /* pass on the initial headers to SID 1 */
  431. swsi->u.http.ah = wsi->u.http.ah;
  432. wsi->u.http.ah = NULL;
  433. lwsl_info("%s: inherited headers %p\n", __func__, swsi->u.http.ah);
  434. swsi->u.http2.tx_credit = wsi->u.http2.peer_settings.setting[LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE];
  435. lwsl_info("initial tx credit on conn %p: %d\n", swsi, swsi->u.http2.tx_credit);
  436. swsi->u.http2.initialized = 1;
  437. /* demanded by HTTP2 */
  438. swsi->u.http2.END_STREAM = 1;
  439. lwsl_info("servicing initial http request\n");
  440. return lws_http_action(swsi);
  441. }
  442. break;
  443. case LWS_PPS_HTTP2_PONG:
  444. memcpy(&settings[LWS_PRE], wsi->u.http2.ping_payload, 8);
  445. n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_PING,
  446. LWS_HTTP2_FLAG_SETTINGS_ACK,
  447. LWS_HTTP2_STREAM_ID_MASTER, 8,
  448. &settings[LWS_PRE]);
  449. if (n != 8) {
  450. lwsl_info("send %d %d\n", n, m);
  451. return 1;
  452. }
  453. break;
  454. default:
  455. break;
  456. }
  457. return 0;
  458. }
  459. struct lws * lws_http2_get_nth_child(struct lws *wsi, int n)
  460. {
  461. do {
  462. wsi = wsi->u.http2.next_child_wsi;
  463. if (!wsi)
  464. return NULL;
  465. } while (n--);
  466. return wsi;
  467. }