/src/libwebsockets/lib/secure-streams/protocols/ss-h2.c
Line | Count | Source |
1 | | /* |
2 | | * libwebsockets - small server side websockets and web server implementation |
3 | | * |
4 | | * Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com> |
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 | | |
25 | | #include <private-lib-core.h> |
26 | | |
27 | | extern int |
28 | | secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, |
29 | | void *in, size_t len); |
30 | | |
31 | | static int |
32 | | secstream_h2(struct lws *wsi, enum lws_callback_reasons reason, void *user, |
33 | | void *in, size_t len) |
34 | 0 | { |
35 | 0 | lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); |
36 | 0 | lws_ss_state_return_t r; |
37 | 0 | int n; |
38 | |
|
39 | 0 | switch (reason) { |
40 | | |
41 | 0 | case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: |
42 | |
|
43 | 0 | if (!h) |
44 | 0 | return -1; |
45 | | |
46 | | #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) |
47 | | if (h->being_serialized) { |
48 | | /* |
49 | | * We are the proxy-side SS for a remote client... we |
50 | | * need to inform the client about the initial tx credit |
51 | | * to write to it that the remote h2 server set up |
52 | | */ |
53 | | lwsl_info("%s: reporting initial tx cr from server %d\n", |
54 | | __func__, wsi->txc.tx_cr); |
55 | | ss_proxy_onward_txcr((void *)(h + 1), wsi->txc.tx_cr); |
56 | | } |
57 | | #endif |
58 | | |
59 | 0 | n = secstream_h1(wsi, reason, user, in, len); |
60 | |
|
61 | 0 | if (!n && (h->policy->flags & LWSSSPOLF_LONG_POLL)) { |
62 | 0 | lwsl_notice("%s: h2 client %s entering LONG_POLL\n", |
63 | 0 | __func__, lws_wsi_tag(wsi)); |
64 | 0 | lws_h2_client_stream_long_poll_rxonly(wsi); |
65 | 0 | } |
66 | 0 | return n; |
67 | | |
68 | 0 | case LWS_CALLBACK_CLOSED_CLIENT_HTTP: |
69 | | /* |
70 | | * Only allow the wsi that the handle believes is representing |
71 | | * him to report closure up to h1 |
72 | | */ |
73 | 0 | if (!h || h->wsi != wsi) |
74 | 0 | return 0; |
75 | | |
76 | 0 | break; |
77 | | |
78 | 0 | case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: |
79 | |
|
80 | 0 | if (!h) |
81 | 0 | return -1; |
82 | | |
83 | | // lwsl_err("%s: h2 COMPLETED_CLIENT_HTTP\n", __func__); |
84 | 0 | r = 0; |
85 | 0 | if (h->hanging_som) |
86 | 0 | r = h->info.rx(ss_to_userobj(h), NULL, 0, LWSSS_FLAG_EOM); |
87 | |
|
88 | 0 | h->txn_ok = 1; |
89 | 0 | lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ |
90 | 0 | if (h->hanging_som && r == LWSSSSRET_DESTROY_ME) |
91 | 0 | return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); |
92 | 0 | h->hanging_som = 0; |
93 | 0 | break; |
94 | | |
95 | 0 | case LWS_CALLBACK_WSI_TX_CREDIT_GET: |
96 | |
|
97 | 0 | if (!h) |
98 | 0 | return -1; |
99 | | |
100 | | /* |
101 | | * The peer has sent us additional tx credit... |
102 | | */ |
103 | 0 | lwsl_info("%s: LWS_CALLBACK_WSI_TX_CREDIT_GET: %d\n", |
104 | 0 | __func__, (int)len); |
105 | |
|
106 | | #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) |
107 | | if (h->being_serialized) |
108 | | /* we are the proxy-side SS for a remote client */ |
109 | | ss_proxy_onward_txcr((void *)(h + 1), (int)len); |
110 | | #endif |
111 | 0 | break; |
112 | | |
113 | 0 | default: |
114 | 0 | break; |
115 | 0 | } |
116 | | |
117 | 0 | return secstream_h1(wsi, reason, user, in, len); |
118 | 0 | } |
119 | | |
120 | | const struct lws_protocols protocol_secstream_h2 = { |
121 | | "lws-secstream-h2", |
122 | | secstream_h2, |
123 | | 0, 0, 0, NULL, 0 |
124 | | }; |
125 | | |
126 | | /* |
127 | | * Munge connect info according to protocol-specific considerations... this |
128 | | * usually means interpreting aux in a protocol-specific way and using the |
129 | | * pieces at connection setup time, eg, http url pieces. |
130 | | * |
131 | | * len bytes of buf can be used for things with scope until after the actual |
132 | | * connect. |
133 | | */ |
134 | | |
135 | | int |
136 | | secstream_connect_munge_h2(lws_ss_handle_t *h, char *buf, size_t len, |
137 | | struct lws_client_connect_info *i, |
138 | | union lws_ss_contemp *ct) |
139 | 0 | { |
140 | 0 | const char *pbasis = h->policy->u.http.url; |
141 | 0 | size_t used_in, used_out; |
142 | 0 | lws_strexp_t exp; |
143 | | |
144 | | /* i.path on entry is used to override the policy urlpath if not "" */ |
145 | |
|
146 | 0 | if (i->path[0]) |
147 | 0 | pbasis = i->path; |
148 | |
|
149 | 0 | if (h->policy->flags & LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM) |
150 | 0 | i->ssl_connection |= LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM; |
151 | |
|
152 | 0 | if (h->policy->flags & LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR) |
153 | 0 | i->ssl_connection |= LCCSCF_H2_QUIRK_OVERFLOWS_TXCR; |
154 | |
|
155 | 0 | if (h->policy->flags & LWSSSPOLF_HTTP_MULTIPART) |
156 | 0 | i->ssl_connection |= LCCSCF_HTTP_MULTIPART_MIME; |
157 | |
|
158 | 0 | if (h->policy->flags & LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED) |
159 | 0 | i->ssl_connection |= LCCSCF_HTTP_X_WWW_FORM_URLENCODED; |
160 | |
|
161 | 0 | if (h->policy->flags & LWSSSPOLF_HTTP_CACHE_COOKIES) |
162 | 0 | i->ssl_connection |= LCCSCF_CACHE_COOKIES; |
163 | |
|
164 | 0 | i->ssl_connection |= LCCSCF_PIPELINE; |
165 | |
|
166 | 0 | i->alpn = "h2"; |
167 | | |
168 | | /* initial peer tx credit */ |
169 | |
|
170 | 0 | if (h->info.manual_initial_tx_credit) { |
171 | 0 | i->ssl_connection |= LCCSCF_H2_MANUAL_RXFLOW; |
172 | 0 | i->manual_initial_tx_credit = h->info.manual_initial_tx_credit; |
173 | 0 | lwsl_info("%s: initial txcr %d\n", __func__, |
174 | 0 | i->manual_initial_tx_credit); |
175 | 0 | } |
176 | |
|
177 | 0 | if (!pbasis) |
178 | 0 | return 0; |
179 | | |
180 | | /* protocol aux is the path part */ |
181 | | |
182 | 0 | i->path = buf; |
183 | 0 | buf[0] = '/'; |
184 | |
|
185 | 0 | lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1); |
186 | |
|
187 | 0 | if (lws_strexp_expand(&exp, pbasis, strlen(pbasis), |
188 | 0 | &used_in, &used_out) != LSTRX_DONE) |
189 | 0 | return 1; |
190 | | |
191 | 0 | __lws_lc_tag_append(&h->lc, buf); |
192 | |
|
193 | 0 | return 0; |
194 | 0 | } |
195 | | |
196 | | static int |
197 | | secstream_tx_credit_add_h2(lws_ss_handle_t *h, int add) |
198 | 0 | { |
199 | 0 | lwsl_info("%s: %s: add %d\n", __func__, lws_ss_tag(h), add); |
200 | 0 | if (h->wsi) |
201 | 0 | return lws_wsi_tx_credit(h->wsi, LWSTXCR_PEER_TO_US, add); |
202 | | |
203 | 0 | return 0; |
204 | 0 | } |
205 | | |
206 | | static int |
207 | | secstream_tx_credit_est_h2(lws_ss_handle_t *h) |
208 | 0 | { |
209 | 0 | if (h->wsi) { |
210 | 0 | lwsl_info("%s: %s: est %d\n", __func__, lws_ss_tag(h), |
211 | 0 | lws_h2_get_peer_txcredit_estimate(h->wsi)); |
212 | |
|
213 | 0 | return lws_h2_get_peer_txcredit_estimate(h->wsi); |
214 | 0 | } |
215 | | |
216 | 0 | lwsl_info("%s: %s: Unknown (0)\n", __func__, lws_ss_tag(h)); |
217 | |
|
218 | 0 | return 0; |
219 | 0 | } |
220 | | |
221 | | const struct ss_pcols ss_pcol_h2 = { |
222 | | "h2", |
223 | | "h2", |
224 | | &protocol_secstream_h2, |
225 | | secstream_connect_munge_h2, |
226 | | secstream_tx_credit_add_h2, |
227 | | secstream_tx_credit_est_h2 |
228 | | }; |