• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
secstream_h2(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)32 secstream_h2(struct lws *wsi, enum lws_callback_reasons reason, void *user,
33 	     void *in, size_t len)
34 {
35 	lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi);
36 	int n;
37 
38 	switch (reason) {
39 
40 	case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
41 
42 #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
43 		if (h->being_serialized) {
44 			/*
45 			 * We are the proxy-side SS for a remote client... we
46 			 * need to inform the client about the initial tx credit
47 			 * to write to it that the remote h2 server set up
48 			 */
49 			lwsl_info("%s: reporting initial tx cr from server %d\n",
50 				  __func__, wsi->txc.tx_cr);
51 			ss_proxy_onward_txcr((void *)&h[1], wsi->txc.tx_cr);
52 		}
53 #endif
54 
55 		n = secstream_h1(wsi, reason, user, in, len);
56 
57 		if (!n && (h->policy->flags & LWSSSPOLF_LONG_POLL)) {
58 			lwsl_notice("%s: h2 client %p entering LONG_POLL\n",
59 					__func__, wsi);
60 			lws_h2_client_stream_long_poll_rxonly(wsi);
61 		}
62 		return n;
63 
64 	case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
65 		// lwsl_err("%s: h2 COMPLETED_CLIENT_HTTP\n", __func__);
66 		h->info.rx(ss_to_userobj(h), NULL, 0, LWSSS_FLAG_EOM);
67 		h->wsi = NULL;
68 		h->txn_ok = 1;
69 		//bad = status != 200;
70 		lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
71 		break;
72 
73 	case LWS_CALLBACK_WSI_TX_CREDIT_GET:
74 		/*
75 		 * The peer has sent us additional tx credit...
76 		 */
77 		lwsl_info("%s: LWS_CALLBACK_WSI_TX_CREDIT_GET: %d\n",
78 			    __func__, (int32_t)len);
79 
80 #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
81 		if (h->being_serialized)
82 			/* we are the proxy-side SS for a remote client */
83 			ss_proxy_onward_txcr((void *)&h[1], (int)len);
84 #endif
85 		break;
86 
87 	default:
88 		break;
89 	}
90 
91 	return secstream_h1(wsi, reason, user, in, len);
92 }
93 
94 const struct lws_protocols protocol_secstream_h2 = {
95 	"lws-secstream-h2",
96 	secstream_h2,
97 	0,
98 	0,
99 };
100 
101 /*
102  * Munge connect info according to protocol-specific considerations... this
103  * usually means interpreting aux in a protocol-specific way and using the
104  * pieces at connection setup time, eg, http url pieces.
105  *
106  * len bytes of buf can be used for things with scope until after the actual
107  * connect.
108  */
109 
110 int
secstream_connect_munge_h2(lws_ss_handle_t * h,char * buf,size_t len,struct lws_client_connect_info * i,union lws_ss_contemp * ct)111 secstream_connect_munge_h2(lws_ss_handle_t *h, char *buf, size_t len,
112 			   struct lws_client_connect_info *i,
113 			   union lws_ss_contemp *ct)
114 {
115 	if (h->policy->flags & LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM)
116 		i->ssl_connection |= LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM;
117 
118 	if (h->policy->flags & LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR)
119 		i->ssl_connection |= LCCSCF_H2_QUIRK_OVERFLOWS_TXCR;
120 
121 	if (h->policy->flags & LWSSSPOLF_HTTP_MULTIPART)
122 		i->ssl_connection |= LCCSCF_HTTP_MULTIPART_MIME;
123 
124 	if (h->policy->flags & LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED)
125 		i->ssl_connection |= LCCSCF_HTTP_X_WWW_FORM_URLENCODED;
126 
127 	i->ssl_connection |= LCCSCF_PIPELINE;
128 
129 	i->alpn = "h2";
130 
131 	/* initial peer tx credit */
132 
133 	if (h->info.manual_initial_tx_credit) {
134 		i->ssl_connection |= LCCSCF_H2_MANUAL_RXFLOW;
135 		i->manual_initial_tx_credit = h->info.manual_initial_tx_credit;
136 		lwsl_info("%s: initial txcr %d\n", __func__,
137 				i->manual_initial_tx_credit);
138 	}
139 
140 	if (!h->policy->u.http.url)
141 		return 0;
142 
143 	/* protocol aux is the path part */
144 
145 	i->path = buf;
146 	lws_snprintf(buf, len, "/%s", h->policy->u.http.url);
147 
148 	return 0;
149 }
150 
151 static int
secstream_tx_credit_add_h2(lws_ss_handle_t * h,int add)152 secstream_tx_credit_add_h2(lws_ss_handle_t *h, int add)
153 {
154 	lwsl_info("%s: h %p: add %d\n", __func__, h, add);
155 	if (h->wsi)
156 		return lws_h2_update_peer_txcredit(h->wsi, LWS_H2_STREAM_SID, add);
157 
158 	return 0;
159 }
160 
161 static int
secstream_tx_credit_est_h2(lws_ss_handle_t * h)162 secstream_tx_credit_est_h2(lws_ss_handle_t *h)
163 {
164 	if (h->wsi) {
165 		lwsl_info("%s: h %p: est %d\n", __func__, h,
166 				lws_h2_get_peer_txcredit_estimate(h->wsi));
167 
168 		return lws_h2_get_peer_txcredit_estimate(h->wsi);
169 	}
170 
171 	lwsl_info("%s: h %p: Unknown (0)\n", __func__, h);
172 
173 	return 0;
174 }
175 
176 const struct ss_pcols ss_pcol_h2 = {
177 	"h2",
178 	NULL,
179 	"lws-secstream-h2",
180 	secstream_connect_munge_h2,
181 	secstream_tx_credit_add_h2,
182 	secstream_tx_credit_est_h2
183 };
184