ss-h2.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2019 - 2020 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. */
  24. #include <private-lib-core.h>
  25. extern int
  26. secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user,
  27. void *in, size_t len);
  28. static int
  29. secstream_h2(struct lws *wsi, enum lws_callback_reasons reason, void *user,
  30. void *in, size_t len)
  31. {
  32. lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi);
  33. lws_ss_state_return_t r;
  34. int n;
  35. switch (reason) {
  36. case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
  37. #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
  38. if (h->being_serialized) {
  39. /*
  40. * We are the proxy-side SS for a remote client... we
  41. * need to inform the client about the initial tx credit
  42. * to write to it that the remote h2 server set up
  43. */
  44. lwsl_info("%s: reporting initial tx cr from server %d\n",
  45. __func__, wsi->txc.tx_cr);
  46. ss_proxy_onward_txcr((void *)&h[1], wsi->txc.tx_cr);
  47. }
  48. #endif
  49. n = secstream_h1(wsi, reason, user, in, len);
  50. if (!n && (h->policy->flags & LWSSSPOLF_LONG_POLL)) {
  51. lwsl_notice("%s: h2 client %p entering LONG_POLL\n",
  52. __func__, wsi);
  53. lws_h2_client_stream_long_poll_rxonly(wsi);
  54. }
  55. return n;
  56. case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
  57. // lwsl_err("%s: h2 COMPLETED_CLIENT_HTTP\n", __func__);
  58. r = h->info.rx(ss_to_userobj(h), NULL, 0, LWSSS_FLAG_EOM);
  59. /* decouple the fates of the wsi and the ss */
  60. h->wsi = NULL;
  61. h->txn_ok = 1;
  62. lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
  63. if (r != LWSSSSRET_OK)
  64. return _lws_ss_handle_state_ret(r, wsi, &h);
  65. return 0;
  66. case LWS_CALLBACK_WSI_TX_CREDIT_GET:
  67. /*
  68. * The peer has sent us additional tx credit...
  69. */
  70. lwsl_info("%s: LWS_CALLBACK_WSI_TX_CREDIT_GET: %d\n",
  71. __func__, (int32_t)len);
  72. #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
  73. if (h->being_serialized)
  74. /* we are the proxy-side SS for a remote client */
  75. ss_proxy_onward_txcr((void *)&h[1], (int)len);
  76. #endif
  77. break;
  78. default:
  79. break;
  80. }
  81. return secstream_h1(wsi, reason, user, in, len);
  82. }
  83. const struct lws_protocols protocol_secstream_h2 = {
  84. "lws-secstream-h2",
  85. secstream_h2,
  86. 0,
  87. 0,
  88. };
  89. /*
  90. * Munge connect info according to protocol-specific considerations... this
  91. * usually means interpreting aux in a protocol-specific way and using the
  92. * pieces at connection setup time, eg, http url pieces.
  93. *
  94. * len bytes of buf can be used for things with scope until after the actual
  95. * connect.
  96. */
  97. int
  98. secstream_connect_munge_h2(lws_ss_handle_t *h, char *buf, size_t len,
  99. struct lws_client_connect_info *i,
  100. union lws_ss_contemp *ct)
  101. {
  102. const char *pbasis = h->policy->u.http.url;
  103. size_t used_in, used_out;
  104. lws_strexp_t exp;
  105. /* i.path on entry is used to override the policy urlpath if not "" */
  106. if (i->path[0])
  107. pbasis = i->path;
  108. if (h->policy->flags & LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM)
  109. i->ssl_connection |= LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM;
  110. if (h->policy->flags & LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR)
  111. i->ssl_connection |= LCCSCF_H2_QUIRK_OVERFLOWS_TXCR;
  112. if (h->policy->flags & LWSSSPOLF_HTTP_MULTIPART)
  113. i->ssl_connection |= LCCSCF_HTTP_MULTIPART_MIME;
  114. if (h->policy->flags & LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED)
  115. i->ssl_connection |= LCCSCF_HTTP_X_WWW_FORM_URLENCODED;
  116. i->ssl_connection |= LCCSCF_PIPELINE;
  117. i->alpn = "h2";
  118. /* initial peer tx credit */
  119. if (h->info.manual_initial_tx_credit) {
  120. i->ssl_connection |= LCCSCF_H2_MANUAL_RXFLOW;
  121. i->manual_initial_tx_credit = h->info.manual_initial_tx_credit;
  122. lwsl_info("%s: initial txcr %d\n", __func__,
  123. i->manual_initial_tx_credit);
  124. }
  125. if (!pbasis)
  126. return 0;
  127. /* protocol aux is the path part */
  128. i->path = buf;
  129. buf[0] = '/';
  130. lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1);
  131. if (lws_strexp_expand(&exp, pbasis, strlen(pbasis),
  132. &used_in, &used_out) != LSTRX_DONE)
  133. return 1;
  134. return 0;
  135. }
  136. static int
  137. secstream_tx_credit_add_h2(lws_ss_handle_t *h, int add)
  138. {
  139. lwsl_info("%s: h %p: add %d\n", __func__, h, add);
  140. if (h->wsi)
  141. return lws_h2_update_peer_txcredit(h->wsi, LWS_H2_STREAM_SID, add);
  142. return 0;
  143. }
  144. static int
  145. secstream_tx_credit_est_h2(lws_ss_handle_t *h)
  146. {
  147. if (h->wsi) {
  148. lwsl_info("%s: h %p: est %d\n", __func__, h,
  149. lws_h2_get_peer_txcredit_estimate(h->wsi));
  150. return lws_h2_get_peer_txcredit_estimate(h->wsi);
  151. }
  152. lwsl_info("%s: h %p: Unknown (0)\n", __func__, h);
  153. return 0;
  154. }
  155. const struct ss_pcols ss_pcol_h2 = {
  156. "h2",
  157. NULL,
  158. &protocol_secstream_h2,
  159. secstream_connect_munge_h2,
  160. secstream_tx_credit_add_h2,
  161. secstream_tx_credit_est_h2
  162. };