xref: /aosp_15_r20/external/libwebsockets/lib/secure-streams/secure-streams-process.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2019 - 2021 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  *
24*1c60b9acSAndroid Build Coastguard Worker  *
25*1c60b9acSAndroid Build Coastguard Worker  * When the user code is in a different process, a non-tls unix domain socket
26*1c60b9acSAndroid Build Coastguard Worker  * proxy is used to asynchronusly transfer buffers in each direction via the
27*1c60b9acSAndroid Build Coastguard Worker  * network stack, without explicit IPC
28*1c60b9acSAndroid Build Coastguard Worker  *
29*1c60b9acSAndroid Build Coastguard Worker  *     user_process{ [user code] | shim | socket-}------ lws_process{ lws }
30*1c60b9acSAndroid Build Coastguard Worker  *
31*1c60b9acSAndroid Build Coastguard Worker  * Lws exposes a listening unix domain socket in this case, the user processes
32*1c60b9acSAndroid Build Coastguard Worker  * connect to it and pass just info.streamtype in an initial tx packet.  All
33*1c60b9acSAndroid Build Coastguard Worker  * packets are prepended by a 1-byte type field when used in this mode.  See
34*1c60b9acSAndroid Build Coastguard Worker  * lws-secure-streams.h for documentation and definitions.
35*1c60b9acSAndroid Build Coastguard Worker  *
36*1c60b9acSAndroid Build Coastguard Worker  * Proxying in either direction can face the situation it cannot send the onward
37*1c60b9acSAndroid Build Coastguard Worker  * packet immediately and is subject to separating the write request from the
38*1c60b9acSAndroid Build Coastguard Worker  * write action.  To make the best use of memory, a single preallocated buffer
39*1c60b9acSAndroid Build Coastguard Worker  * stashes pending packets in all four directions (c->p, p->c, p->ss, ss->p).
40*1c60b9acSAndroid Build Coastguard Worker  * This allows it to adapt to different traffic patterns without wasted areas
41*1c60b9acSAndroid Build Coastguard Worker  * dedicated to traffic that isn't coming in a particular application.
42*1c60b9acSAndroid Build Coastguard Worker  *
43*1c60b9acSAndroid Build Coastguard Worker  * A shim is provided to monitor the process' unix domain socket and regenerate
44*1c60b9acSAndroid Build Coastguard Worker  * the secure sockets api there with callbacks happening in the process thread
45*1c60b9acSAndroid Build Coastguard Worker  * context.
46*1c60b9acSAndroid Build Coastguard Worker  *
47*1c60b9acSAndroid Build Coastguard Worker  * This file implements the listening unix domain socket proxy... this code is
48*1c60b9acSAndroid Build Coastguard Worker  * only going to run on a Linux-class device with its implications about memory
49*1c60b9acSAndroid Build Coastguard Worker  * availability.
50*1c60b9acSAndroid Build Coastguard Worker  */
51*1c60b9acSAndroid Build Coastguard Worker 
52*1c60b9acSAndroid Build Coastguard Worker #include <private-lib-core.h>
53*1c60b9acSAndroid Build Coastguard Worker 
54*1c60b9acSAndroid Build Coastguard Worker struct raw_pss {
55*1c60b9acSAndroid Build Coastguard Worker 	struct conn		*conn;
56*1c60b9acSAndroid Build Coastguard Worker };
57*1c60b9acSAndroid Build Coastguard Worker 
58*1c60b9acSAndroid Build Coastguard Worker /*
59*1c60b9acSAndroid Build Coastguard Worker  * Proxy - onward secure-stream handler
60*1c60b9acSAndroid Build Coastguard Worker  */
61*1c60b9acSAndroid Build Coastguard Worker 
62*1c60b9acSAndroid Build Coastguard Worker typedef struct ss_proxy_onward {
63*1c60b9acSAndroid Build Coastguard Worker 	lws_ss_handle_t 	*ss;
64*1c60b9acSAndroid Build Coastguard Worker 	struct conn		*conn;
65*1c60b9acSAndroid Build Coastguard Worker } ss_proxy_t;
66*1c60b9acSAndroid Build Coastguard Worker 
67*1c60b9acSAndroid Build Coastguard Worker void
lws_proxy_clean_conn_ss(struct lws * wsi)68*1c60b9acSAndroid Build Coastguard Worker lws_proxy_clean_conn_ss(struct lws *wsi)
69*1c60b9acSAndroid Build Coastguard Worker {
70*1c60b9acSAndroid Build Coastguard Worker #if 0
71*1c60b9acSAndroid Build Coastguard Worker 	lws_ss_handle_t *h = (lws_ss_handle_t *)wsi->a.opaque_user_data;
72*1c60b9acSAndroid Build Coastguard Worker 	struct conn *conn = h->conn_if_sspc_onw;
73*1c60b9acSAndroid Build Coastguard Worker 
74*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi)
75*1c60b9acSAndroid Build Coastguard Worker 		return;
76*1c60b9acSAndroid Build Coastguard Worker 
77*1c60b9acSAndroid Build Coastguard Worker 	if (conn && conn->ss)
78*1c60b9acSAndroid Build Coastguard Worker 		conn->ss->wsi = NULL;
79*1c60b9acSAndroid Build Coastguard Worker #endif
80*1c60b9acSAndroid Build Coastguard Worker }
81*1c60b9acSAndroid Build Coastguard Worker 
82*1c60b9acSAndroid Build Coastguard Worker 
83*1c60b9acSAndroid Build Coastguard Worker void
ss_proxy_onward_link_req_writeable(lws_ss_handle_t * h_onward)84*1c60b9acSAndroid Build Coastguard Worker ss_proxy_onward_link_req_writeable(lws_ss_handle_t *h_onward)
85*1c60b9acSAndroid Build Coastguard Worker {
86*1c60b9acSAndroid Build Coastguard Worker 	ss_proxy_t *m = (ss_proxy_t *)&h_onward[1];
87*1c60b9acSAndroid Build Coastguard Worker 
88*1c60b9acSAndroid Build Coastguard Worker 	if (m->conn->wsi) /* if possible, request client conn write */
89*1c60b9acSAndroid Build Coastguard Worker 		lws_callback_on_writable(m->conn->wsi);
90*1c60b9acSAndroid Build Coastguard Worker }
91*1c60b9acSAndroid Build Coastguard Worker 
92*1c60b9acSAndroid Build Coastguard Worker int
__lws_ss_proxy_bind_ss_to_conn_wsi(void * parconn,size_t dsh_size)93*1c60b9acSAndroid Build Coastguard Worker __lws_ss_proxy_bind_ss_to_conn_wsi(void *parconn, size_t dsh_size)
94*1c60b9acSAndroid Build Coastguard Worker {
95*1c60b9acSAndroid Build Coastguard Worker 	struct conn *conn = (struct conn *)parconn;
96*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt;
97*1c60b9acSAndroid Build Coastguard Worker 
98*1c60b9acSAndroid Build Coastguard Worker 	if (!conn || !conn->wsi || !conn->ss)
99*1c60b9acSAndroid Build Coastguard Worker 		return -1;
100*1c60b9acSAndroid Build Coastguard Worker 
101*1c60b9acSAndroid Build Coastguard Worker 	pt = &conn->wsi->a.context->pt[(int)conn->wsi->tsi];
102*1c60b9acSAndroid Build Coastguard Worker 
103*1c60b9acSAndroid Build Coastguard Worker 	if (lws_fi(&conn->ss->fic, "ssproxy_dsh_create_oom"))
104*1c60b9acSAndroid Build Coastguard Worker 		return -1;
105*1c60b9acSAndroid Build Coastguard Worker 	conn->dsh = lws_dsh_create(&pt->ss_dsh_owner, dsh_size, 2);
106*1c60b9acSAndroid Build Coastguard Worker 	if (!conn->dsh)
107*1c60b9acSAndroid Build Coastguard Worker 		return -1;
108*1c60b9acSAndroid Build Coastguard Worker 
109*1c60b9acSAndroid Build Coastguard Worker 	__lws_lc_tag_append(&conn->wsi->lc, lws_ss_tag(conn->ss));
110*1c60b9acSAndroid Build Coastguard Worker 
111*1c60b9acSAndroid Build Coastguard Worker 	return 0;
112*1c60b9acSAndroid Build Coastguard Worker }
113*1c60b9acSAndroid Build Coastguard Worker 
114*1c60b9acSAndroid Build Coastguard Worker /* Onward secure streams payload interface */
115*1c60b9acSAndroid Build Coastguard Worker 
116*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
ss_proxy_onward_rx(void * userobj,const uint8_t * buf,size_t len,int flags)117*1c60b9acSAndroid Build Coastguard Worker ss_proxy_onward_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
118*1c60b9acSAndroid Build Coastguard Worker {
119*1c60b9acSAndroid Build Coastguard Worker 	ss_proxy_t *m = (ss_proxy_t *)userobj;
120*1c60b9acSAndroid Build Coastguard Worker 	const char *rsp = NULL;
121*1c60b9acSAndroid Build Coastguard Worker 	int n;
122*1c60b9acSAndroid Build Coastguard Worker 
123*1c60b9acSAndroid Build Coastguard Worker 	// lwsl_notice("%s: len %d\n", __func__, (int)len);
124*1c60b9acSAndroid Build Coastguard Worker 
125*1c60b9acSAndroid Build Coastguard Worker 	/*
126*1c60b9acSAndroid Build Coastguard Worker 	 * The onward secure stream connection has received something.
127*1c60b9acSAndroid Build Coastguard Worker 	 */
128*1c60b9acSAndroid Build Coastguard Worker 
129*1c60b9acSAndroid Build Coastguard Worker 	if (m->ss->rideshare != m->ss->policy && m->ss->rideshare) {
130*1c60b9acSAndroid Build Coastguard Worker 		rsp = m->ss->rideshare->streamtype;
131*1c60b9acSAndroid Build Coastguard Worker 		flags |= LWSSS_FLAG_RIDESHARE;
132*1c60b9acSAndroid Build Coastguard Worker 	}
133*1c60b9acSAndroid Build Coastguard Worker 
134*1c60b9acSAndroid Build Coastguard Worker 	/*
135*1c60b9acSAndroid Build Coastguard Worker 	 * Apply SSS framing around this chunk of RX and stash it in the dsh
136*1c60b9acSAndroid Build Coastguard Worker 	 * in ss -> proxy [ -> client] direction.  This can fail...
137*1c60b9acSAndroid Build Coastguard Worker 	 */
138*1c60b9acSAndroid Build Coastguard Worker 
139*1c60b9acSAndroid Build Coastguard Worker 	if (lws_fi(&m->ss->fic, "ssproxy_dsh_rx_queue_oom"))
140*1c60b9acSAndroid Build Coastguard Worker 		n = 1;
141*1c60b9acSAndroid Build Coastguard Worker 	else
142*1c60b9acSAndroid Build Coastguard Worker 		n = lws_ss_serialize_rx_payload(m->conn->dsh, buf, len,
143*1c60b9acSAndroid Build Coastguard Worker 						flags, rsp);
144*1c60b9acSAndroid Build Coastguard Worker 	if (n)
145*1c60b9acSAndroid Build Coastguard Worker 		/*
146*1c60b9acSAndroid Build Coastguard Worker 		 * We couldn't buffer this rx, eg due to OOM, let's escalate it
147*1c60b9acSAndroid Build Coastguard Worker 		 * to be a "loss of connection", which it basically is...
148*1c60b9acSAndroid Build Coastguard Worker 		 */
149*1c60b9acSAndroid Build Coastguard Worker 		return LWSSSSRET_DISCONNECT_ME;
150*1c60b9acSAndroid Build Coastguard Worker 
151*1c60b9acSAndroid Build Coastguard Worker 	/*
152*1c60b9acSAndroid Build Coastguard Worker 	 * Manage rx flow on the SS (onward) side according to our situation
153*1c60b9acSAndroid Build Coastguard Worker 	 * in the dsh holding proxy->client serialized forwarding rx
154*1c60b9acSAndroid Build Coastguard Worker 	 */
155*1c60b9acSAndroid Build Coastguard Worker 
156*1c60b9acSAndroid Build Coastguard Worker 	if (!m->conn->onward_in_flow_control && m->ss->wsi &&
157*1c60b9acSAndroid Build Coastguard Worker 	    m->ss->policy->proxy_buflen_rxflow_on_above &&
158*1c60b9acSAndroid Build Coastguard Worker 	    lws_dsh_get_size(m->conn->dsh, KIND_SS_TO_P) >=
159*1c60b9acSAndroid Build Coastguard Worker 				m->ss->policy->proxy_buflen_rxflow_on_above) {
160*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: %s: rxflow disabling rx (%lu / %lu, hwm %lu)\n", __func__,
161*1c60b9acSAndroid Build Coastguard Worker 				lws_wsi_tag(m->ss->wsi),
162*1c60b9acSAndroid Build Coastguard Worker 				(unsigned long)lws_dsh_get_size(m->conn->dsh, KIND_SS_TO_P),
163*1c60b9acSAndroid Build Coastguard Worker 				(unsigned long)m->ss->policy->proxy_buflen,
164*1c60b9acSAndroid Build Coastguard Worker 				(unsigned long)m->ss->policy->proxy_buflen_rxflow_on_above);
165*1c60b9acSAndroid Build Coastguard Worker 		/*
166*1c60b9acSAndroid Build Coastguard Worker 		 * stop taking in rx once the onward wsi rx is above the
167*1c60b9acSAndroid Build Coastguard Worker 		 * high water mark
168*1c60b9acSAndroid Build Coastguard Worker 		 */
169*1c60b9acSAndroid Build Coastguard Worker 		lws_rx_flow_control(m->ss->wsi, 0);
170*1c60b9acSAndroid Build Coastguard Worker 		m->conn->onward_in_flow_control = 1;
171*1c60b9acSAndroid Build Coastguard Worker 	}
172*1c60b9acSAndroid Build Coastguard Worker 
173*1c60b9acSAndroid Build Coastguard Worker 	if (m->conn->wsi) /* if possible, request client conn write */
174*1c60b9acSAndroid Build Coastguard Worker 		lws_callback_on_writable(m->conn->wsi);
175*1c60b9acSAndroid Build Coastguard Worker 
176*1c60b9acSAndroid Build Coastguard Worker 	return LWSSSSRET_OK;
177*1c60b9acSAndroid Build Coastguard Worker }
178*1c60b9acSAndroid Build Coastguard Worker 
179*1c60b9acSAndroid Build Coastguard Worker /*
180*1c60b9acSAndroid Build Coastguard Worker  * we are transmitting buffered payload originally from the client on to the ss
181*1c60b9acSAndroid Build Coastguard Worker  */
182*1c60b9acSAndroid Build Coastguard Worker 
183*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
ss_proxy_onward_tx(void * userobj,lws_ss_tx_ordinal_t ord,uint8_t * buf,size_t * len,int * flags)184*1c60b9acSAndroid Build Coastguard Worker ss_proxy_onward_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf,
185*1c60b9acSAndroid Build Coastguard Worker 		   size_t *len, int *flags)
186*1c60b9acSAndroid Build Coastguard Worker {
187*1c60b9acSAndroid Build Coastguard Worker 	ss_proxy_t *m = (ss_proxy_t *)userobj;
188*1c60b9acSAndroid Build Coastguard Worker 	void *p;
189*1c60b9acSAndroid Build Coastguard Worker 	size_t si;
190*1c60b9acSAndroid Build Coastguard Worker 
191*1c60b9acSAndroid Build Coastguard Worker 	if (!m->conn->ss || m->conn->state != LPCSPROX_OPERATIONAL) {
192*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: ss not ready\n", __func__);
193*1c60b9acSAndroid Build Coastguard Worker 		*len = 0;
194*1c60b9acSAndroid Build Coastguard Worker 
195*1c60b9acSAndroid Build Coastguard Worker 		return LWSSSSRET_TX_DONT_SEND;
196*1c60b9acSAndroid Build Coastguard Worker 	}
197*1c60b9acSAndroid Build Coastguard Worker 
198*1c60b9acSAndroid Build Coastguard Worker 	/*
199*1c60b9acSAndroid Build Coastguard Worker 	 * The onward secure stream says that we could send something to it
200*1c60b9acSAndroid Build Coastguard Worker 	 * (by putting it in buf, and setting *len and *flags)... dredge the
201*1c60b9acSAndroid Build Coastguard Worker 	 * next thing out of the dsh
202*1c60b9acSAndroid Build Coastguard Worker 	 */
203*1c60b9acSAndroid Build Coastguard Worker 
204*1c60b9acSAndroid Build Coastguard Worker 	if (lws_ss_deserialize_tx_payload(m->conn->dsh, m->ss->wsi,
205*1c60b9acSAndroid Build Coastguard Worker 					  ord, buf, len, flags))
206*1c60b9acSAndroid Build Coastguard Worker 		return LWSSSSRET_TX_DONT_SEND;
207*1c60b9acSAndroid Build Coastguard Worker 
208*1c60b9acSAndroid Build Coastguard Worker 	/* ... there's more we want to send? */
209*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_dsh_get_head(m->conn->dsh, KIND_C_TO_P, (void **)&p, &si))
210*1c60b9acSAndroid Build Coastguard Worker 		_lws_ss_request_tx(m->conn->ss);
211*1c60b9acSAndroid Build Coastguard Worker 
212*1c60b9acSAndroid Build Coastguard Worker 	if (!*len && !*flags)
213*1c60b9acSAndroid Build Coastguard Worker 		/* we don't actually want to send anything */
214*1c60b9acSAndroid Build Coastguard Worker 		return LWSSSSRET_TX_DONT_SEND;
215*1c60b9acSAndroid Build Coastguard Worker 
216*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: onward tx %d fl 0x%x\n", __func__, (int)*len, *flags);
217*1c60b9acSAndroid Build Coastguard Worker 
218*1c60b9acSAndroid Build Coastguard Worker #if 0
219*1c60b9acSAndroid Build Coastguard Worker 	{
220*1c60b9acSAndroid Build Coastguard Worker 		int ff = open("/tmp/z", O_RDWR | O_CREAT | O_APPEND, 0666);
221*1c60b9acSAndroid Build Coastguard Worker 		if (ff == -1)
222*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: errno %d\n", __func__, errno);
223*1c60b9acSAndroid Build Coastguard Worker 		write(ff, buf, *len);
224*1c60b9acSAndroid Build Coastguard Worker 		close(ff);
225*1c60b9acSAndroid Build Coastguard Worker 	}
226*1c60b9acSAndroid Build Coastguard Worker #endif
227*1c60b9acSAndroid Build Coastguard Worker 
228*1c60b9acSAndroid Build Coastguard Worker 	return LWSSSSRET_OK;
229*1c60b9acSAndroid Build Coastguard Worker }
230*1c60b9acSAndroid Build Coastguard Worker 
231*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
ss_proxy_onward_state(void * userobj,void * sh,lws_ss_constate_t state,lws_ss_tx_ordinal_t ack)232*1c60b9acSAndroid Build Coastguard Worker ss_proxy_onward_state(void *userobj, void *sh,
233*1c60b9acSAndroid Build Coastguard Worker 		      lws_ss_constate_t state, lws_ss_tx_ordinal_t ack)
234*1c60b9acSAndroid Build Coastguard Worker {
235*1c60b9acSAndroid Build Coastguard Worker 	ss_proxy_t *m = (ss_proxy_t *)userobj;
236*1c60b9acSAndroid Build Coastguard Worker 	size_t dsh_size;
237*1c60b9acSAndroid Build Coastguard Worker 
238*1c60b9acSAndroid Build Coastguard Worker 	switch (state) {
239*1c60b9acSAndroid Build Coastguard Worker 	case LWSSSCS_CREATING:
240*1c60b9acSAndroid Build Coastguard Worker 
241*1c60b9acSAndroid Build Coastguard Worker 		/*
242*1c60b9acSAndroid Build Coastguard Worker 		 * conn is private to -process.c, call thru to a) adjust
243*1c60b9acSAndroid Build Coastguard Worker 		 * the accepted incoming proxy link wsi tag name to be
244*1c60b9acSAndroid Build Coastguard Worker 		 * appended with the onward ss tag information now we
245*1c60b9acSAndroid Build Coastguard Worker 		 * have it, and b) allocate the dsh buffer now we
246*1c60b9acSAndroid Build Coastguard Worker 		 * can find out the policy about it for the streamtype.
247*1c60b9acSAndroid Build Coastguard Worker 		 */
248*1c60b9acSAndroid Build Coastguard Worker 
249*1c60b9acSAndroid Build Coastguard Worker 		dsh_size = m->ss->policy->proxy_buflen ?
250*1c60b9acSAndroid Build Coastguard Worker 				m->ss->policy->proxy_buflen : 32768;
251*1c60b9acSAndroid Build Coastguard Worker 
252*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: %s: initializing dsh max len %lu\n",
253*1c60b9acSAndroid Build Coastguard Worker 				__func__, lws_ss_tag(m->ss),
254*1c60b9acSAndroid Build Coastguard Worker 				(unsigned long)dsh_size);
255*1c60b9acSAndroid Build Coastguard Worker 
256*1c60b9acSAndroid Build Coastguard Worker 		/* this includes ssproxy_dsh_create_oom fault generation */
257*1c60b9acSAndroid Build Coastguard Worker 
258*1c60b9acSAndroid Build Coastguard Worker 		if (__lws_ss_proxy_bind_ss_to_conn_wsi(m->conn, dsh_size)) {
259*1c60b9acSAndroid Build Coastguard Worker 
260*1c60b9acSAndroid Build Coastguard Worker 			/* failed to allocate the dsh */
261*1c60b9acSAndroid Build Coastguard Worker 
262*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: dsh init failed\n", __func__);
263*1c60b9acSAndroid Build Coastguard Worker 
264*1c60b9acSAndroid Build Coastguard Worker 			return LWSSSSRET_DESTROY_ME;
265*1c60b9acSAndroid Build Coastguard Worker 		}
266*1c60b9acSAndroid Build Coastguard Worker 		break;
267*1c60b9acSAndroid Build Coastguard Worker 
268*1c60b9acSAndroid Build Coastguard Worker 	case LWSSSCS_DESTROYING:
269*1c60b9acSAndroid Build Coastguard Worker 		if (!m->conn)
270*1c60b9acSAndroid Build Coastguard Worker 			break;
271*1c60b9acSAndroid Build Coastguard Worker 		if (!m->conn->wsi) {
272*1c60b9acSAndroid Build Coastguard Worker 			/*
273*1c60b9acSAndroid Build Coastguard Worker 			 * Our onward secure stream is closing and our client
274*1c60b9acSAndroid Build Coastguard Worker 			 * connection has already gone away... destroy the conn.
275*1c60b9acSAndroid Build Coastguard Worker 			 */
276*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: Destroying conn\n", __func__);
277*1c60b9acSAndroid Build Coastguard Worker 			lws_dsh_destroy(&m->conn->dsh);
278*1c60b9acSAndroid Build Coastguard Worker 			free(m->conn);
279*1c60b9acSAndroid Build Coastguard Worker 			m->conn = NULL;
280*1c60b9acSAndroid Build Coastguard Worker 			return 0;
281*1c60b9acSAndroid Build Coastguard Worker 		} else
282*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: ss DESTROYING, wsi up\n", __func__);
283*1c60b9acSAndroid Build Coastguard Worker 		break;
284*1c60b9acSAndroid Build Coastguard Worker 
285*1c60b9acSAndroid Build Coastguard Worker 	default:
286*1c60b9acSAndroid Build Coastguard Worker 		break;
287*1c60b9acSAndroid Build Coastguard Worker 	}
288*1c60b9acSAndroid Build Coastguard Worker 	if (!m->conn) {
289*1c60b9acSAndroid Build Coastguard Worker 		lwsl_warn("%s: dropping state due to conn not up\n", __func__);
290*1c60b9acSAndroid Build Coastguard Worker 
291*1c60b9acSAndroid Build Coastguard Worker 		return LWSSSSRET_OK;
292*1c60b9acSAndroid Build Coastguard Worker 	}
293*1c60b9acSAndroid Build Coastguard Worker 
294*1c60b9acSAndroid Build Coastguard Worker 	if (lws_ss_serialize_state(m->conn->wsi, m->conn->dsh, state, ack))
295*1c60b9acSAndroid Build Coastguard Worker 		/*
296*1c60b9acSAndroid Build Coastguard Worker 		 * Failed to alloc state packet that we want to send in dsh,
297*1c60b9acSAndroid Build Coastguard Worker 		 * we will lose coherence and have to disconnect the link
298*1c60b9acSAndroid Build Coastguard Worker 		 */
299*1c60b9acSAndroid Build Coastguard Worker 		return LWSSSSRET_DISCONNECT_ME;
300*1c60b9acSAndroid Build Coastguard Worker 
301*1c60b9acSAndroid Build Coastguard Worker 	if (m->conn->wsi) /* if possible, request client conn write */
302*1c60b9acSAndroid Build Coastguard Worker 		lws_callback_on_writable(m->conn->wsi);
303*1c60b9acSAndroid Build Coastguard Worker 
304*1c60b9acSAndroid Build Coastguard Worker 	return LWSSSSRET_OK;
305*1c60b9acSAndroid Build Coastguard Worker }
306*1c60b9acSAndroid Build Coastguard Worker 
307*1c60b9acSAndroid Build Coastguard Worker void
ss_proxy_onward_txcr(void * userobj,int bump)308*1c60b9acSAndroid Build Coastguard Worker ss_proxy_onward_txcr(void *userobj, int bump)
309*1c60b9acSAndroid Build Coastguard Worker {
310*1c60b9acSAndroid Build Coastguard Worker 	ss_proxy_t *m = (ss_proxy_t *)userobj;
311*1c60b9acSAndroid Build Coastguard Worker 
312*1c60b9acSAndroid Build Coastguard Worker 	if (!m->conn)
313*1c60b9acSAndroid Build Coastguard Worker 		return;
314*1c60b9acSAndroid Build Coastguard Worker 
315*1c60b9acSAndroid Build Coastguard Worker 	lws_ss_serialize_txcr(m->conn->dsh, bump);
316*1c60b9acSAndroid Build Coastguard Worker 
317*1c60b9acSAndroid Build Coastguard Worker 	if (m->conn->wsi) /* if possible, request client conn write */
318*1c60b9acSAndroid Build Coastguard Worker 		lws_callback_on_writable(m->conn->wsi);
319*1c60b9acSAndroid Build Coastguard Worker }
320*1c60b9acSAndroid Build Coastguard Worker 
321*1c60b9acSAndroid Build Coastguard Worker /*
322*1c60b9acSAndroid Build Coastguard Worker  * Client <-> Proxy connection, usually on Unix Domain Socket
323*1c60b9acSAndroid Build Coastguard Worker  */
324*1c60b9acSAndroid Build Coastguard Worker 
325*1c60b9acSAndroid Build Coastguard Worker static int
callback_ss_proxy(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)326*1c60b9acSAndroid Build Coastguard Worker callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason,
327*1c60b9acSAndroid Build Coastguard Worker 		  void *user, void *in, size_t len)
328*1c60b9acSAndroid Build Coastguard Worker {
329*1c60b9acSAndroid Build Coastguard Worker 	struct raw_pss *pss = (struct raw_pss *)user;
330*1c60b9acSAndroid Build Coastguard Worker 	const lws_ss_policy_t *rsp;
331*1c60b9acSAndroid Build Coastguard Worker 	struct conn *conn = NULL;
332*1c60b9acSAndroid Build Coastguard Worker 	lws_ss_metadata_t *md;
333*1c60b9acSAndroid Build Coastguard Worker 	lws_ss_info_t ssi;
334*1c60b9acSAndroid Build Coastguard Worker 	const uint8_t *cp;
335*1c60b9acSAndroid Build Coastguard Worker 	char s[512];
336*1c60b9acSAndroid Build Coastguard Worker 	uint8_t *p;
337*1c60b9acSAndroid Build Coastguard Worker 	size_t si;
338*1c60b9acSAndroid Build Coastguard Worker 	char pay;
339*1c60b9acSAndroid Build Coastguard Worker 	int n;
340*1c60b9acSAndroid Build Coastguard Worker 
341*1c60b9acSAndroid Build Coastguard Worker 	if (pss)
342*1c60b9acSAndroid Build Coastguard Worker 		conn = pss->conn;
343*1c60b9acSAndroid Build Coastguard Worker 
344*1c60b9acSAndroid Build Coastguard Worker 	switch (reason) {
345*1c60b9acSAndroid Build Coastguard Worker 	case LWS_CALLBACK_PROTOCOL_INIT:
346*1c60b9acSAndroid Build Coastguard Worker 		break;
347*1c60b9acSAndroid Build Coastguard Worker 
348*1c60b9acSAndroid Build Coastguard Worker 	case LWS_CALLBACK_PROTOCOL_DESTROY:
349*1c60b9acSAndroid Build Coastguard Worker 		break;
350*1c60b9acSAndroid Build Coastguard Worker 
351*1c60b9acSAndroid Build Coastguard Worker 	/* callbacks related to raw socket descriptor "accepted side" */
352*1c60b9acSAndroid Build Coastguard Worker 
353*1c60b9acSAndroid Build Coastguard Worker         case LWS_CALLBACK_RAW_ADOPT:
354*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("LWS_CALLBACK_RAW_ADOPT\n");
355*1c60b9acSAndroid Build Coastguard Worker 		if (!pss)
356*1c60b9acSAndroid Build Coastguard Worker 			return -1;
357*1c60b9acSAndroid Build Coastguard Worker 
358*1c60b9acSAndroid Build Coastguard Worker 		if (lws_fi(&wsi->fic, "ssproxy_client_adopt_oom"))
359*1c60b9acSAndroid Build Coastguard Worker 			pss->conn = NULL;
360*1c60b9acSAndroid Build Coastguard Worker 		else
361*1c60b9acSAndroid Build Coastguard Worker 			pss->conn = malloc(sizeof(struct conn));
362*1c60b9acSAndroid Build Coastguard Worker 		if (!pss->conn)
363*1c60b9acSAndroid Build Coastguard Worker 			return -1;
364*1c60b9acSAndroid Build Coastguard Worker 
365*1c60b9acSAndroid Build Coastguard Worker 		memset(pss->conn, 0, sizeof(*pss->conn));
366*1c60b9acSAndroid Build Coastguard Worker 
367*1c60b9acSAndroid Build Coastguard Worker 		/* dsh is allocated when the onward ss is done */
368*1c60b9acSAndroid Build Coastguard Worker 
369*1c60b9acSAndroid Build Coastguard Worker 		pss->conn->wsi = wsi;
370*1c60b9acSAndroid Build Coastguard Worker 		wsi->bound_ss_proxy_conn = 1; /* opaque is conn */
371*1c60b9acSAndroid Build Coastguard Worker 
372*1c60b9acSAndroid Build Coastguard Worker 		pss->conn->state = LPCSPROX_WAIT_INITIAL_TX;
373*1c60b9acSAndroid Build Coastguard Worker 
374*1c60b9acSAndroid Build Coastguard Worker 		/*
375*1c60b9acSAndroid Build Coastguard Worker 		 * Client is expected to follow the unix domain socket
376*1c60b9acSAndroid Build Coastguard Worker 		 * acceptance up rapidly with an initial tx containing the
377*1c60b9acSAndroid Build Coastguard Worker 		 * streamtype name.  We can't create the stream until then.
378*1c60b9acSAndroid Build Coastguard Worker 		 */
379*1c60b9acSAndroid Build Coastguard Worker 		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, 3);
380*1c60b9acSAndroid Build Coastguard Worker                 break;
381*1c60b9acSAndroid Build Coastguard Worker 
382*1c60b9acSAndroid Build Coastguard Worker 	case LWS_CALLBACK_RAW_CLOSE:
383*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("LWS_CALLBACK_RAW_CLOSE:\n");
384*1c60b9acSAndroid Build Coastguard Worker 
385*1c60b9acSAndroid Build Coastguard Worker 		if (!conn)
386*1c60b9acSAndroid Build Coastguard Worker 			break;
387*1c60b9acSAndroid Build Coastguard Worker 
388*1c60b9acSAndroid Build Coastguard Worker 		/*
389*1c60b9acSAndroid Build Coastguard Worker 		 * the client unix domain socket connection (wsi / conn->wsi)
390*1c60b9acSAndroid Build Coastguard Worker 		 * has closed... eg, client has exited or otherwise has
391*1c60b9acSAndroid Build Coastguard Worker 		 * definitively finished with the proxying and onward connection
392*1c60b9acSAndroid Build Coastguard Worker 		 *
393*1c60b9acSAndroid Build Coastguard Worker 		 * But right now, the SS and possibly the SS onward wsi are
394*1c60b9acSAndroid Build Coastguard Worker 		 * still live...
395*1c60b9acSAndroid Build Coastguard Worker 		 */
396*1c60b9acSAndroid Build Coastguard Worker 
397*1c60b9acSAndroid Build Coastguard Worker 		assert(conn->wsi == wsi);
398*1c60b9acSAndroid Build Coastguard Worker 		conn->wsi = NULL;
399*1c60b9acSAndroid Build Coastguard Worker 
400*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: cli->prox link %s closing\n", __func__,
401*1c60b9acSAndroid Build Coastguard Worker 				lws_wsi_tag(wsi));
402*1c60b9acSAndroid Build Coastguard Worker 
403*1c60b9acSAndroid Build Coastguard Worker 		/* sever relationship with conn */
404*1c60b9acSAndroid Build Coastguard Worker 		lws_set_opaque_user_data(wsi, NULL);
405*1c60b9acSAndroid Build Coastguard Worker 
406*1c60b9acSAndroid Build Coastguard Worker 		/*
407*1c60b9acSAndroid Build Coastguard Worker 		 * The current wsi is decoupled from the pss / conn and
408*1c60b9acSAndroid Build Coastguard Worker 		 * the conn no longer has a pointer on it.
409*1c60b9acSAndroid Build Coastguard Worker 		 *
410*1c60b9acSAndroid Build Coastguard Worker 		 * If there's an outgoing, proxied SS conn on our behalf, we
411*1c60b9acSAndroid Build Coastguard Worker 		 * have to destroy those
412*1c60b9acSAndroid Build Coastguard Worker 		 */
413*1c60b9acSAndroid Build Coastguard Worker 
414*1c60b9acSAndroid Build Coastguard Worker 		if (conn->ss) {
415*1c60b9acSAndroid Build Coastguard Worker 			struct lws *cw = conn->ss->wsi;
416*1c60b9acSAndroid Build Coastguard Worker 			/*
417*1c60b9acSAndroid Build Coastguard Worker 			 * conn->ss is the onward connection SS
418*1c60b9acSAndroid Build Coastguard Worker 			 */
419*1c60b9acSAndroid Build Coastguard Worker 
420*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: destroying %s, wsi %s\n",
421*1c60b9acSAndroid Build Coastguard Worker 					__func__, lws_ss_tag(conn->ss),
422*1c60b9acSAndroid Build Coastguard Worker 					lws_wsi_tag(conn->ss->wsi));
423*1c60b9acSAndroid Build Coastguard Worker 
424*1c60b9acSAndroid Build Coastguard Worker 			/* sever conn relationship with ss about to be deleted */
425*1c60b9acSAndroid Build Coastguard Worker 
426*1c60b9acSAndroid Build Coastguard Worker 			conn->ss->wsi = NULL;
427*1c60b9acSAndroid Build Coastguard Worker 
428*1c60b9acSAndroid Build Coastguard Worker 			if (cw && wsi != cw) {
429*1c60b9acSAndroid Build Coastguard Worker 
430*1c60b9acSAndroid Build Coastguard Worker 				/* disconnect onward SS from its wsi */
431*1c60b9acSAndroid Build Coastguard Worker 
432*1c60b9acSAndroid Build Coastguard Worker 				lws_set_opaque_user_data(cw, NULL);
433*1c60b9acSAndroid Build Coastguard Worker 
434*1c60b9acSAndroid Build Coastguard Worker 				/*
435*1c60b9acSAndroid Build Coastguard Worker 				 * The wsi doing the onward connection can no
436*1c60b9acSAndroid Build Coastguard Worker 				 * longer relate to the conn... otherwise when
437*1c60b9acSAndroid Build Coastguard Worker 				 * he gets callbacks he wants to bind to
438*1c60b9acSAndroid Build Coastguard Worker 				 * the ss we are about to delete
439*1c60b9acSAndroid Build Coastguard Worker 				 */
440*1c60b9acSAndroid Build Coastguard Worker 				lws_wsi_close(cw, LWS_TO_KILL_ASYNC);
441*1c60b9acSAndroid Build Coastguard Worker 			}
442*1c60b9acSAndroid Build Coastguard Worker 
443*1c60b9acSAndroid Build Coastguard Worker 			lws_ss_destroy(&conn->ss);
444*1c60b9acSAndroid Build Coastguard Worker 			/*
445*1c60b9acSAndroid Build Coastguard Worker 			 * Conn may have gone, at ss destroy handler in
446*1c60b9acSAndroid Build Coastguard Worker 			 * ssi.state for proxied ss
447*1c60b9acSAndroid Build Coastguard Worker 			 */
448*1c60b9acSAndroid Build Coastguard Worker 			break;
449*1c60b9acSAndroid Build Coastguard Worker 		}
450*1c60b9acSAndroid Build Coastguard Worker 
451*1c60b9acSAndroid Build Coastguard Worker 		if (conn->state == LPCSPROX_DESTROYED || !conn->ss) {
452*1c60b9acSAndroid Build Coastguard Worker 			/*
453*1c60b9acSAndroid Build Coastguard Worker 			 * There's no onward secure stream and our client
454*1c60b9acSAndroid Build Coastguard Worker 			 * connection is closing.  Destroy the conn.
455*1c60b9acSAndroid Build Coastguard Worker 			 */
456*1c60b9acSAndroid Build Coastguard Worker 			lws_dsh_destroy(&conn->dsh);
457*1c60b9acSAndroid Build Coastguard Worker 			free(conn);
458*1c60b9acSAndroid Build Coastguard Worker 			pss->conn = NULL;
459*1c60b9acSAndroid Build Coastguard Worker 		} else
460*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("%s: CLOSE; %s\n", __func__, lws_ss_tag(conn->ss));
461*1c60b9acSAndroid Build Coastguard Worker 
462*1c60b9acSAndroid Build Coastguard Worker 		break;
463*1c60b9acSAndroid Build Coastguard Worker 
464*1c60b9acSAndroid Build Coastguard Worker 	case LWS_CALLBACK_RAW_RX:
465*1c60b9acSAndroid Build Coastguard Worker 		/*
466*1c60b9acSAndroid Build Coastguard Worker 		 * ie, the proxy is receiving something from a client
467*1c60b9acSAndroid Build Coastguard Worker 		 */
468*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: RX: rx %d\n", __func__, (int)len);
469*1c60b9acSAndroid Build Coastguard Worker 
470*1c60b9acSAndroid Build Coastguard Worker 		if (!conn || !conn->wsi) {
471*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: rx with bad conn state\n", __func__);
472*1c60b9acSAndroid Build Coastguard Worker 
473*1c60b9acSAndroid Build Coastguard Worker 			return -1;
474*1c60b9acSAndroid Build Coastguard Worker 		}
475*1c60b9acSAndroid Build Coastguard Worker 
476*1c60b9acSAndroid Build Coastguard Worker 		// lwsl_hexdump_info(in, len);
477*1c60b9acSAndroid Build Coastguard Worker 
478*1c60b9acSAndroid Build Coastguard Worker 		if (conn->state == LPCSPROX_WAIT_INITIAL_TX) {
479*1c60b9acSAndroid Build Coastguard Worker 			memset(&ssi, 0, sizeof(ssi));
480*1c60b9acSAndroid Build Coastguard Worker 			ssi.user_alloc = sizeof(ss_proxy_t);
481*1c60b9acSAndroid Build Coastguard Worker 			ssi.handle_offset = offsetof(ss_proxy_t, ss);
482*1c60b9acSAndroid Build Coastguard Worker 			ssi.opaque_user_data_offset =
483*1c60b9acSAndroid Build Coastguard Worker 					offsetof(ss_proxy_t, conn);
484*1c60b9acSAndroid Build Coastguard Worker 			ssi.rx = ss_proxy_onward_rx;
485*1c60b9acSAndroid Build Coastguard Worker 			ssi.tx = ss_proxy_onward_tx;
486*1c60b9acSAndroid Build Coastguard Worker 		}
487*1c60b9acSAndroid Build Coastguard Worker 		ssi.state = ss_proxy_onward_state;
488*1c60b9acSAndroid Build Coastguard Worker 		ssi.flags = 0;
489*1c60b9acSAndroid Build Coastguard Worker 
490*1c60b9acSAndroid Build Coastguard Worker 		n = lws_ss_deserialize_parse(&conn->parser,
491*1c60b9acSAndroid Build Coastguard Worker 				lws_get_context(wsi), conn->dsh, in, len,
492*1c60b9acSAndroid Build Coastguard Worker 				&conn->state, conn, &conn->ss, &ssi, 0);
493*1c60b9acSAndroid Build Coastguard Worker 		switch (n) {
494*1c60b9acSAndroid Build Coastguard Worker 		case LWSSSSRET_OK:
495*1c60b9acSAndroid Build Coastguard Worker 			break;
496*1c60b9acSAndroid Build Coastguard Worker 		case LWSSSSRET_DISCONNECT_ME:
497*1c60b9acSAndroid Build Coastguard Worker 			return -1;
498*1c60b9acSAndroid Build Coastguard Worker 		case LWSSSSRET_DESTROY_ME:
499*1c60b9acSAndroid Build Coastguard Worker 			if (conn->ss)
500*1c60b9acSAndroid Build Coastguard Worker 				lws_ss_destroy(&conn->ss);
501*1c60b9acSAndroid Build Coastguard Worker 			return -1;
502*1c60b9acSAndroid Build Coastguard Worker 		}
503*1c60b9acSAndroid Build Coastguard Worker 
504*1c60b9acSAndroid Build Coastguard Worker 		if (conn->state == LPCSPROX_REPORTING_FAIL ||
505*1c60b9acSAndroid Build Coastguard Worker 		    conn->state == LPCSPROX_REPORTING_OK)
506*1c60b9acSAndroid Build Coastguard Worker 			lws_callback_on_writable(conn->wsi);
507*1c60b9acSAndroid Build Coastguard Worker 
508*1c60b9acSAndroid Build Coastguard Worker 		break;
509*1c60b9acSAndroid Build Coastguard Worker 
510*1c60b9acSAndroid Build Coastguard Worker 	case LWS_CALLBACK_RAW_WRITEABLE:
511*1c60b9acSAndroid Build Coastguard Worker 
512*1c60b9acSAndroid Build Coastguard Worker 		lwsl_debug("%s: %s: LWS_CALLBACK_RAW_WRITEABLE, state 0x%x\n",
513*1c60b9acSAndroid Build Coastguard Worker 				__func__, lws_wsi_tag(wsi), lwsi_state(wsi));
514*1c60b9acSAndroid Build Coastguard Worker 
515*1c60b9acSAndroid Build Coastguard Worker 		/*
516*1c60b9acSAndroid Build Coastguard Worker 		 * We can transmit something back to the client from the dsh
517*1c60b9acSAndroid Build Coastguard Worker 		 * of stuff we received on its behalf from the ss
518*1c60b9acSAndroid Build Coastguard Worker 		 */
519*1c60b9acSAndroid Build Coastguard Worker 
520*1c60b9acSAndroid Build Coastguard Worker 		if (!conn || !conn->wsi)
521*1c60b9acSAndroid Build Coastguard Worker 			break;
522*1c60b9acSAndroid Build Coastguard Worker 
523*1c60b9acSAndroid Build Coastguard Worker 		n = 0;
524*1c60b9acSAndroid Build Coastguard Worker 		pay = 0;
525*1c60b9acSAndroid Build Coastguard Worker 
526*1c60b9acSAndroid Build Coastguard Worker 		s[3] = 0;
527*1c60b9acSAndroid Build Coastguard Worker 		cp = (const uint8_t *)s;
528*1c60b9acSAndroid Build Coastguard Worker 		switch (conn->state) {
529*1c60b9acSAndroid Build Coastguard Worker 		case LPCSPROX_REPORTING_FAIL:
530*1c60b9acSAndroid Build Coastguard Worker 			s[3] = 1;
531*1c60b9acSAndroid Build Coastguard Worker 			/* fallthru */
532*1c60b9acSAndroid Build Coastguard Worker 		case LPCSPROX_REPORTING_OK:
533*1c60b9acSAndroid Build Coastguard Worker 			s[0] = LWSSS_SER_RXPRE_CREATE_RESULT;
534*1c60b9acSAndroid Build Coastguard Worker 			s[1] = 0;
535*1c60b9acSAndroid Build Coastguard Worker 			s[2] = 1;
536*1c60b9acSAndroid Build Coastguard Worker 
537*1c60b9acSAndroid Build Coastguard Worker 			n = 8;
538*1c60b9acSAndroid Build Coastguard Worker 
539*1c60b9acSAndroid Build Coastguard Worker 			lws_ser_wu32be((uint8_t *)&s[4], conn->ss &&
540*1c60b9acSAndroid Build Coastguard Worker 							 conn->ss->policy ?
541*1c60b9acSAndroid Build Coastguard Worker 					conn->ss->policy->client_buflen : 0);
542*1c60b9acSAndroid Build Coastguard Worker 
543*1c60b9acSAndroid Build Coastguard Worker 			/*
544*1c60b9acSAndroid Build Coastguard Worker 			 * If there's rideshare sequencing, it's added after the
545*1c60b9acSAndroid Build Coastguard Worker 			 * first 4 bytes or the create result, comma-separated
546*1c60b9acSAndroid Build Coastguard Worker 			 */
547*1c60b9acSAndroid Build Coastguard Worker 
548*1c60b9acSAndroid Build Coastguard Worker 			if (conn->ss) {
549*1c60b9acSAndroid Build Coastguard Worker 				rsp = conn->ss->policy;
550*1c60b9acSAndroid Build Coastguard Worker 
551*1c60b9acSAndroid Build Coastguard Worker 				while (rsp) {
552*1c60b9acSAndroid Build Coastguard Worker 					if (n != 4 && n < (int)sizeof(s) - 2)
553*1c60b9acSAndroid Build Coastguard Worker 						s[n++] = ',';
554*1c60b9acSAndroid Build Coastguard Worker 					n += lws_snprintf(&s[n], sizeof(s) - (unsigned int)n,
555*1c60b9acSAndroid Build Coastguard Worker 							"%s", rsp->streamtype);
556*1c60b9acSAndroid Build Coastguard Worker 					rsp = lws_ss_policy_lookup(wsi->a.context,
557*1c60b9acSAndroid Build Coastguard Worker 						rsp->rideshare_streamtype);
558*1c60b9acSAndroid Build Coastguard Worker 				}
559*1c60b9acSAndroid Build Coastguard Worker 			}
560*1c60b9acSAndroid Build Coastguard Worker 			s[2] = (char)(n - 3);
561*1c60b9acSAndroid Build Coastguard Worker 			conn->state = LPCSPROX_OPERATIONAL;
562*1c60b9acSAndroid Build Coastguard Worker 			lws_set_timeout(wsi, 0, 0);
563*1c60b9acSAndroid Build Coastguard Worker 			break;
564*1c60b9acSAndroid Build Coastguard Worker 
565*1c60b9acSAndroid Build Coastguard Worker 		case LPCSPROX_OPERATIONAL:
566*1c60b9acSAndroid Build Coastguard Worker 
567*1c60b9acSAndroid Build Coastguard Worker 			/*
568*1c60b9acSAndroid Build Coastguard Worker 			 * returning [onward -> ] proxy]-> client
569*1c60b9acSAndroid Build Coastguard Worker 			 * rx metadata has priority 1
570*1c60b9acSAndroid Build Coastguard Worker 			 */
571*1c60b9acSAndroid Build Coastguard Worker 
572*1c60b9acSAndroid Build Coastguard Worker 			md = conn->ss->metadata;
573*1c60b9acSAndroid Build Coastguard Worker 			while (md) {
574*1c60b9acSAndroid Build Coastguard Worker 				// lwsl_notice("%s: check %s: %d\n", __func__,
575*1c60b9acSAndroid Build Coastguard Worker 				// md->name, md->pending_onward);
576*1c60b9acSAndroid Build Coastguard Worker 				if (md->pending_onward) {
577*1c60b9acSAndroid Build Coastguard Worker 					size_t naml = strlen(md->name);
578*1c60b9acSAndroid Build Coastguard Worker 
579*1c60b9acSAndroid Build Coastguard Worker 					// lwsl_notice("%s: proxy issuing rxmd\n", __func__);
580*1c60b9acSAndroid Build Coastguard Worker 
581*1c60b9acSAndroid Build Coastguard Worker 					if (4 + naml + md->length > sizeof(s)) {
582*1c60b9acSAndroid Build Coastguard Worker 						lwsl_err("%s: rxmdata too big\n",
583*1c60b9acSAndroid Build Coastguard Worker 								__func__);
584*1c60b9acSAndroid Build Coastguard Worker 						goto hangup;
585*1c60b9acSAndroid Build Coastguard Worker 					}
586*1c60b9acSAndroid Build Coastguard Worker 					md->pending_onward = 0;
587*1c60b9acSAndroid Build Coastguard Worker 					p = (uint8_t *)s;
588*1c60b9acSAndroid Build Coastguard Worker 					p[0] = LWSSS_SER_RXPRE_METADATA;
589*1c60b9acSAndroid Build Coastguard Worker 					lws_ser_wu16be(&p[1], (uint16_t)(1 + naml +
590*1c60b9acSAndroid Build Coastguard Worker 							      md->length));
591*1c60b9acSAndroid Build Coastguard Worker 					p[3] = (uint8_t)naml;
592*1c60b9acSAndroid Build Coastguard Worker 					memcpy(&p[4], md->name, naml);
593*1c60b9acSAndroid Build Coastguard Worker 					p += 4 + naml;
594*1c60b9acSAndroid Build Coastguard Worker 					memcpy(p, md->value__may_own_heap,
595*1c60b9acSAndroid Build Coastguard Worker 					       md->length);
596*1c60b9acSAndroid Build Coastguard Worker 					p += md->length;
597*1c60b9acSAndroid Build Coastguard Worker 
598*1c60b9acSAndroid Build Coastguard Worker 					n = lws_ptr_diff(p, cp);
599*1c60b9acSAndroid Build Coastguard Worker 					goto again;
600*1c60b9acSAndroid Build Coastguard Worker 				}
601*1c60b9acSAndroid Build Coastguard Worker 
602*1c60b9acSAndroid Build Coastguard Worker 				md = md->next;
603*1c60b9acSAndroid Build Coastguard Worker 			}
604*1c60b9acSAndroid Build Coastguard Worker 
605*1c60b9acSAndroid Build Coastguard Worker 			/*
606*1c60b9acSAndroid Build Coastguard Worker 			 * If we have performance data, render it in JSON
607*1c60b9acSAndroid Build Coastguard Worker 			 * and send that in LWSSS_SER_RXPRE_PERF has
608*1c60b9acSAndroid Build Coastguard Worker 			 * priority 2
609*1c60b9acSAndroid Build Coastguard Worker 			 */
610*1c60b9acSAndroid Build Coastguard Worker 
611*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CONMON)
612*1c60b9acSAndroid Build Coastguard Worker 			if (conn->ss->conmon_json) {
613*1c60b9acSAndroid Build Coastguard Worker 				unsigned int xlen = conn->ss->conmon_len;
614*1c60b9acSAndroid Build Coastguard Worker 
615*1c60b9acSAndroid Build Coastguard Worker 				if (xlen > sizeof(s) - 3)
616*1c60b9acSAndroid Build Coastguard Worker 					xlen = sizeof(s) - 3;
617*1c60b9acSAndroid Build Coastguard Worker 				cp = (uint8_t *)s;
618*1c60b9acSAndroid Build Coastguard Worker 				p = (uint8_t *)s;
619*1c60b9acSAndroid Build Coastguard Worker 				p[0] = LWSSS_SER_RXPRE_PERF;
620*1c60b9acSAndroid Build Coastguard Worker 				lws_ser_wu16be(&p[1], (uint16_t)xlen);
621*1c60b9acSAndroid Build Coastguard Worker 				memcpy(&p[3], conn->ss->conmon_json, xlen);
622*1c60b9acSAndroid Build Coastguard Worker 
623*1c60b9acSAndroid Build Coastguard Worker 				lws_free_set_NULL(conn->ss->conmon_json);
624*1c60b9acSAndroid Build Coastguard Worker 				n = (int)(xlen + 3);
625*1c60b9acSAndroid Build Coastguard Worker 
626*1c60b9acSAndroid Build Coastguard Worker 				pay = 0;
627*1c60b9acSAndroid Build Coastguard Worker 				goto again;
628*1c60b9acSAndroid Build Coastguard Worker 			}
629*1c60b9acSAndroid Build Coastguard Worker #endif
630*1c60b9acSAndroid Build Coastguard Worker 			/*
631*1c60b9acSAndroid Build Coastguard Worker 			 * if no fresh rx metadata, just pass through incoming
632*1c60b9acSAndroid Build Coastguard Worker 			 * dsh
633*1c60b9acSAndroid Build Coastguard Worker 			 */
634*1c60b9acSAndroid Build Coastguard Worker 
635*1c60b9acSAndroid Build Coastguard Worker 			if (lws_dsh_get_head(conn->dsh, KIND_SS_TO_P,
636*1c60b9acSAndroid Build Coastguard Worker 					     (void **)&p, &si))
637*1c60b9acSAndroid Build Coastguard Worker 				break;
638*1c60b9acSAndroid Build Coastguard Worker 
639*1c60b9acSAndroid Build Coastguard Worker 			cp = p;
640*1c60b9acSAndroid Build Coastguard Worker 
641*1c60b9acSAndroid Build Coastguard Worker #if 0
642*1c60b9acSAndroid Build Coastguard Worker 			if (cp[0] == LWSSS_SER_RXPRE_RX_PAYLOAD &&
643*1c60b9acSAndroid Build Coastguard Worker 			    wsi->a.context->detailed_latency_cb) {
644*1c60b9acSAndroid Build Coastguard Worker 
645*1c60b9acSAndroid Build Coastguard Worker 				/*
646*1c60b9acSAndroid Build Coastguard Worker 				 * we're fulfilling rx that came in on ss
647*1c60b9acSAndroid Build Coastguard Worker 				 * by sending it back out to the client on
648*1c60b9acSAndroid Build Coastguard Worker 				 * the Unix Domain Socket
649*1c60b9acSAndroid Build Coastguard Worker 				 *
650*1c60b9acSAndroid Build Coastguard Worker 				 * +  7  u32  write will compute latency here...
651*1c60b9acSAndroid Build Coastguard Worker 				 * + 11  u32  ust we received from ss
652*1c60b9acSAndroid Build Coastguard Worker 				 *
653*1c60b9acSAndroid Build Coastguard Worker 				 * lws_write will report it and fill in
654*1c60b9acSAndroid Build Coastguard Worker 				 * LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE
655*1c60b9acSAndroid Build Coastguard Worker 				 */
656*1c60b9acSAndroid Build Coastguard Worker 
657*1c60b9acSAndroid Build Coastguard Worker 				us = lws_now_usecs();
658*1c60b9acSAndroid Build Coastguard Worker 				lws_ser_wu32be(&p[7], us -
659*1c60b9acSAndroid Build Coastguard Worker 						      lws_ser_ru64be(&p[11]));
660*1c60b9acSAndroid Build Coastguard Worker 				lws_ser_wu64be(&p[11], us);
661*1c60b9acSAndroid Build Coastguard Worker 
662*1c60b9acSAndroid Build Coastguard Worker 				wsi->detlat.acc_size =
663*1c60b9acSAndroid Build Coastguard Worker 					wsi->detlat.req_size = si - 19;
664*1c60b9acSAndroid Build Coastguard Worker 				/* time proxy held it */
665*1c60b9acSAndroid Build Coastguard Worker 				wsi->detlat.latencies[
666*1c60b9acSAndroid Build Coastguard Worker 				            LAT_DUR_PROXY_RX_TO_ONWARD_TX] =
667*1c60b9acSAndroid Build Coastguard Worker 							lws_ser_ru32be(&p[7]);
668*1c60b9acSAndroid Build Coastguard Worker 			}
669*1c60b9acSAndroid Build Coastguard Worker #endif
670*1c60b9acSAndroid Build Coastguard Worker 			pay = 1;
671*1c60b9acSAndroid Build Coastguard Worker 			n = (int)si;
672*1c60b9acSAndroid Build Coastguard Worker 			break;
673*1c60b9acSAndroid Build Coastguard Worker 		default:
674*1c60b9acSAndroid Build Coastguard Worker 			break;
675*1c60b9acSAndroid Build Coastguard Worker 		}
676*1c60b9acSAndroid Build Coastguard Worker again:
677*1c60b9acSAndroid Build Coastguard Worker 		if (!n)
678*1c60b9acSAndroid Build Coastguard Worker 			break;
679*1c60b9acSAndroid Build Coastguard Worker 
680*1c60b9acSAndroid Build Coastguard Worker 		if (lws_fi(&wsi->fic, "ssproxy_client_write_fail"))
681*1c60b9acSAndroid Build Coastguard Worker 			n = -1;
682*1c60b9acSAndroid Build Coastguard Worker 		else
683*1c60b9acSAndroid Build Coastguard Worker 			n = lws_write(wsi, (uint8_t *)cp, (unsigned int)n, LWS_WRITE_RAW);
684*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0) {
685*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: WRITEABLE: %d\n", __func__, n);
686*1c60b9acSAndroid Build Coastguard Worker 
687*1c60b9acSAndroid Build Coastguard Worker 			goto hangup;
688*1c60b9acSAndroid Build Coastguard Worker 		}
689*1c60b9acSAndroid Build Coastguard Worker 
690*1c60b9acSAndroid Build Coastguard Worker 		switch (conn->state) {
691*1c60b9acSAndroid Build Coastguard Worker 		case LPCSPROX_REPORTING_FAIL:
692*1c60b9acSAndroid Build Coastguard Worker 			goto hangup;
693*1c60b9acSAndroid Build Coastguard Worker 		case LPCSPROX_OPERATIONAL:
694*1c60b9acSAndroid Build Coastguard Worker 			if (!conn)
695*1c60b9acSAndroid Build Coastguard Worker 				break;
696*1c60b9acSAndroid Build Coastguard Worker 			if (pay) {
697*1c60b9acSAndroid Build Coastguard Worker 				lws_dsh_free((void **)&p);
698*1c60b9acSAndroid Build Coastguard Worker 
699*1c60b9acSAndroid Build Coastguard Worker 				/*
700*1c60b9acSAndroid Build Coastguard Worker 				 * Did we go below the rx flow threshold for
701*1c60b9acSAndroid Build Coastguard Worker 				 * this dsh?
702*1c60b9acSAndroid Build Coastguard Worker 				 */
703*1c60b9acSAndroid Build Coastguard Worker 
704*1c60b9acSAndroid Build Coastguard Worker 				if (conn->onward_in_flow_control &&
705*1c60b9acSAndroid Build Coastguard Worker 				    conn->ss->policy->proxy_buflen_rxflow_on_above &&
706*1c60b9acSAndroid Build Coastguard Worker 				    conn->ss->wsi &&
707*1c60b9acSAndroid Build Coastguard Worker 				    lws_dsh_get_size(conn->dsh, KIND_SS_TO_P) <
708*1c60b9acSAndroid Build Coastguard Worker 				      conn->ss->policy->proxy_buflen_rxflow_off_below) {
709*1c60b9acSAndroid Build Coastguard Worker 					lwsl_info("%s: %s: rxflow enabling rx (%lu / %lu, lwm %lu)\n", __func__,
710*1c60b9acSAndroid Build Coastguard Worker 							lws_wsi_tag(conn->ss->wsi),
711*1c60b9acSAndroid Build Coastguard Worker 							(unsigned long)lws_dsh_get_size(conn->dsh, KIND_SS_TO_P),
712*1c60b9acSAndroid Build Coastguard Worker 							(unsigned long)conn->ss->policy->proxy_buflen,
713*1c60b9acSAndroid Build Coastguard Worker 							(unsigned long)conn->ss->policy->proxy_buflen_rxflow_off_below);
714*1c60b9acSAndroid Build Coastguard Worker 					/*
715*1c60b9acSAndroid Build Coastguard Worker 					 * Resume receiving taking in rx once
716*1c60b9acSAndroid Build Coastguard Worker 					 * below the low threshold
717*1c60b9acSAndroid Build Coastguard Worker 					 */
718*1c60b9acSAndroid Build Coastguard Worker 					lws_rx_flow_control(conn->ss->wsi,
719*1c60b9acSAndroid Build Coastguard Worker 							    LWS_RXFLOW_ALLOW);
720*1c60b9acSAndroid Build Coastguard Worker 					conn->onward_in_flow_control = 0;
721*1c60b9acSAndroid Build Coastguard Worker 				}
722*1c60b9acSAndroid Build Coastguard Worker 			}
723*1c60b9acSAndroid Build Coastguard Worker 			if (!lws_dsh_get_head(conn->dsh, KIND_SS_TO_P,
724*1c60b9acSAndroid Build Coastguard Worker 					     (void **)&p, &si)) {
725*1c60b9acSAndroid Build Coastguard Worker 				if (!lws_send_pipe_choked(wsi)) {
726*1c60b9acSAndroid Build Coastguard Worker 					cp = p;
727*1c60b9acSAndroid Build Coastguard Worker 					pay = 1;
728*1c60b9acSAndroid Build Coastguard Worker 					n = (int)si;
729*1c60b9acSAndroid Build Coastguard Worker 					goto again;
730*1c60b9acSAndroid Build Coastguard Worker 				}
731*1c60b9acSAndroid Build Coastguard Worker 				lws_callback_on_writable(wsi);
732*1c60b9acSAndroid Build Coastguard Worker 			}
733*1c60b9acSAndroid Build Coastguard Worker 			break;
734*1c60b9acSAndroid Build Coastguard Worker 		default:
735*1c60b9acSAndroid Build Coastguard Worker 			break;
736*1c60b9acSAndroid Build Coastguard Worker 		}
737*1c60b9acSAndroid Build Coastguard Worker 		break;
738*1c60b9acSAndroid Build Coastguard Worker 
739*1c60b9acSAndroid Build Coastguard Worker 	default:
740*1c60b9acSAndroid Build Coastguard Worker 		break;
741*1c60b9acSAndroid Build Coastguard Worker 	}
742*1c60b9acSAndroid Build Coastguard Worker 
743*1c60b9acSAndroid Build Coastguard Worker 	return lws_callback_http_dummy(wsi, reason, user, in, len);
744*1c60b9acSAndroid Build Coastguard Worker 
745*1c60b9acSAndroid Build Coastguard Worker hangup:
746*1c60b9acSAndroid Build Coastguard Worker 	/* hang up on him */
747*1c60b9acSAndroid Build Coastguard Worker 
748*1c60b9acSAndroid Build Coastguard Worker 	return -1;
749*1c60b9acSAndroid Build Coastguard Worker }
750*1c60b9acSAndroid Build Coastguard Worker 
751*1c60b9acSAndroid Build Coastguard Worker static const struct lws_protocols protocols[] = {
752*1c60b9acSAndroid Build Coastguard Worker 	{
753*1c60b9acSAndroid Build Coastguard Worker 		"ssproxy-protocol",
754*1c60b9acSAndroid Build Coastguard Worker 		callback_ss_proxy,
755*1c60b9acSAndroid Build Coastguard Worker 		sizeof(struct raw_pss),
756*1c60b9acSAndroid Build Coastguard Worker 		2048, 2048, NULL, 0
757*1c60b9acSAndroid Build Coastguard Worker 	},
758*1c60b9acSAndroid Build Coastguard Worker 	{ NULL, NULL, 0, 0, 0, NULL, 0 }
759*1c60b9acSAndroid Build Coastguard Worker };
760*1c60b9acSAndroid Build Coastguard Worker 
761*1c60b9acSAndroid Build Coastguard Worker /*
762*1c60b9acSAndroid Build Coastguard Worker  * called from create_context()
763*1c60b9acSAndroid Build Coastguard Worker  */
764*1c60b9acSAndroid Build Coastguard Worker 
765*1c60b9acSAndroid Build Coastguard Worker int
lws_ss_proxy_create(struct lws_context * context,const char * bind,int port)766*1c60b9acSAndroid Build Coastguard Worker lws_ss_proxy_create(struct lws_context *context, const char *bind, int port)
767*1c60b9acSAndroid Build Coastguard Worker {
768*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_creation_info info;
769*1c60b9acSAndroid Build Coastguard Worker 
770*1c60b9acSAndroid Build Coastguard Worker 	memset(&info, 0, sizeof(info));
771*1c60b9acSAndroid Build Coastguard Worker 
772*1c60b9acSAndroid Build Coastguard Worker 	info.vhost_name			= "ssproxy";
773*1c60b9acSAndroid Build Coastguard Worker 	info.options = LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG |
774*1c60b9acSAndroid Build Coastguard Worker 			LWS_SERVER_OPTION_SS_PROXY;
775*1c60b9acSAndroid Build Coastguard Worker 	info.port = port;
776*1c60b9acSAndroid Build Coastguard Worker 	if (!port) {
777*1c60b9acSAndroid Build Coastguard Worker 		if (!bind)
778*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__)
779*1c60b9acSAndroid Build Coastguard Worker 			bind = "@proxy.ss.lws";
780*1c60b9acSAndroid Build Coastguard Worker #else
781*1c60b9acSAndroid Build Coastguard Worker 			bind = "/tmp/proxy.ss.lws";
782*1c60b9acSAndroid Build Coastguard Worker #endif
783*1c60b9acSAndroid Build Coastguard Worker 		info.options |= LWS_SERVER_OPTION_UNIX_SOCK;
784*1c60b9acSAndroid Build Coastguard Worker 	}
785*1c60b9acSAndroid Build Coastguard Worker 	info.iface			= bind;
786*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__)
787*1c60b9acSAndroid Build Coastguard Worker 	info.unix_socket_perms		= "root:root";
788*1c60b9acSAndroid Build Coastguard Worker #else
789*1c60b9acSAndroid Build Coastguard Worker #endif
790*1c60b9acSAndroid Build Coastguard Worker 	info.listen_accept_role		= "raw-skt";
791*1c60b9acSAndroid Build Coastguard Worker 	info.listen_accept_protocol	= "ssproxy-protocol";
792*1c60b9acSAndroid Build Coastguard Worker 	info.protocols			= protocols;
793*1c60b9acSAndroid Build Coastguard Worker 
794*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_create_vhost(context, &info)) {
795*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: Failed to create ss proxy vhost\n", __func__);
796*1c60b9acSAndroid Build Coastguard Worker 
797*1c60b9acSAndroid Build Coastguard Worker 		return 1;
798*1c60b9acSAndroid Build Coastguard Worker 	}
799*1c60b9acSAndroid Build Coastguard Worker 
800*1c60b9acSAndroid Build Coastguard Worker 	return 0;
801*1c60b9acSAndroid Build Coastguard Worker }
802