1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * lws-minimal-secure-streams-client
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Written in 2010-2020 by Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * This file is made available under the Creative Commons CC0 1.0
7*1c60b9acSAndroid Build Coastguard Worker * Universal Public Domain Dedication.
8*1c60b9acSAndroid Build Coastguard Worker *
9*1c60b9acSAndroid Build Coastguard Worker *
10*1c60b9acSAndroid Build Coastguard Worker * This client does not perform any INET networking... instead it opens a unix
11*1c60b9acSAndroid Build Coastguard Worker * domain socket on a proxy that is listening for it, and that creates the
12*1c60b9acSAndroid Build Coastguard Worker * actual secure stream connection.
13*1c60b9acSAndroid Build Coastguard Worker *
14*1c60b9acSAndroid Build Coastguard Worker * We are able to use the usual secure streams api in the client process, with
15*1c60b9acSAndroid Build Coastguard Worker * payloads and connection state information proxied over the unix domain
16*1c60b9acSAndroid Build Coastguard Worker * socket and fulfilled in the proxy process.
17*1c60b9acSAndroid Build Coastguard Worker *
18*1c60b9acSAndroid Build Coastguard Worker * The public client helper pieces are built as part of lws
19*1c60b9acSAndroid Build Coastguard Worker */
20*1c60b9acSAndroid Build Coastguard Worker #include <private-lib-core.h>
21*1c60b9acSAndroid Build Coastguard Worker
22*1c60b9acSAndroid Build Coastguard Worker extern const uint32_t ss_state_txn_validity[17];
23*1c60b9acSAndroid Build Coastguard Worker
24*1c60b9acSAndroid Build Coastguard Worker int
lws_ss_check_next_state_sspc(lws_sspc_handle_t * ss,uint8_t * prevstate,lws_ss_constate_t cs)25*1c60b9acSAndroid Build Coastguard Worker lws_ss_check_next_state_sspc(lws_sspc_handle_t *ss, uint8_t *prevstate,
26*1c60b9acSAndroid Build Coastguard Worker lws_ss_constate_t cs)
27*1c60b9acSAndroid Build Coastguard Worker {
28*1c60b9acSAndroid Build Coastguard Worker if (cs >= LWSSSCS_USER_BASE || cs == LWSSSCS_EVENT_WAIT_CANCELLED)
29*1c60b9acSAndroid Build Coastguard Worker /*
30*1c60b9acSAndroid Build Coastguard Worker * we can't judge user or transient states, leave the old state
31*1c60b9acSAndroid Build Coastguard Worker * and just wave them through
32*1c60b9acSAndroid Build Coastguard Worker */
33*1c60b9acSAndroid Build Coastguard Worker return 0;
34*1c60b9acSAndroid Build Coastguard Worker
35*1c60b9acSAndroid Build Coastguard Worker if (cs >= LWS_ARRAY_SIZE(ss_state_txn_validity)) {
36*1c60b9acSAndroid Build Coastguard Worker /* we don't recognize this state as usable */
37*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_err(ss, "bad new state %u", cs);
38*1c60b9acSAndroid Build Coastguard Worker assert(0);
39*1c60b9acSAndroid Build Coastguard Worker return 1;
40*1c60b9acSAndroid Build Coastguard Worker }
41*1c60b9acSAndroid Build Coastguard Worker
42*1c60b9acSAndroid Build Coastguard Worker if (*prevstate >= LWS_ARRAY_SIZE(ss_state_txn_validity)) {
43*1c60b9acSAndroid Build Coastguard Worker /* existing state is broken */
44*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_err(ss, "bad existing state %u",
45*1c60b9acSAndroid Build Coastguard Worker (unsigned int)*prevstate);
46*1c60b9acSAndroid Build Coastguard Worker assert(0);
47*1c60b9acSAndroid Build Coastguard Worker return 1;
48*1c60b9acSAndroid Build Coastguard Worker }
49*1c60b9acSAndroid Build Coastguard Worker
50*1c60b9acSAndroid Build Coastguard Worker if (ss_state_txn_validity[*prevstate] & (1u << cs)) {
51*1c60b9acSAndroid Build Coastguard Worker
52*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_notice(ss, "%s -> %s",
53*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_name((int)*prevstate),
54*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_name((int)cs));
55*1c60b9acSAndroid Build Coastguard Worker
56*1c60b9acSAndroid Build Coastguard Worker /* this is explicitly allowed, update old state to new */
57*1c60b9acSAndroid Build Coastguard Worker *prevstate = (uint8_t)cs;
58*1c60b9acSAndroid Build Coastguard Worker
59*1c60b9acSAndroid Build Coastguard Worker return 0;
60*1c60b9acSAndroid Build Coastguard Worker }
61*1c60b9acSAndroid Build Coastguard Worker
62*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_err(ss, "transition from %s -> %s is illegal",
63*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_name((int)*prevstate),
64*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_name((int)cs));
65*1c60b9acSAndroid Build Coastguard Worker
66*1c60b9acSAndroid Build Coastguard Worker assert(0);
67*1c60b9acSAndroid Build Coastguard Worker
68*1c60b9acSAndroid Build Coastguard Worker return 1;
69*1c60b9acSAndroid Build Coastguard Worker }
70*1c60b9acSAndroid Build Coastguard Worker
71*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_return_t
lws_sspc_event_helper(lws_sspc_handle_t * h,lws_ss_constate_t cs,lws_ss_tx_ordinal_t flags)72*1c60b9acSAndroid Build Coastguard Worker lws_sspc_event_helper(lws_sspc_handle_t *h, lws_ss_constate_t cs,
73*1c60b9acSAndroid Build Coastguard Worker lws_ss_tx_ordinal_t flags)
74*1c60b9acSAndroid Build Coastguard Worker {
75*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_return_t ret;
76*1c60b9acSAndroid Build Coastguard Worker
77*1c60b9acSAndroid Build Coastguard Worker if (!h)
78*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
79*1c60b9acSAndroid Build Coastguard Worker
80*1c60b9acSAndroid Build Coastguard Worker if (lws_ss_check_next_state_sspc(h, &h->prev_ss_state, cs))
81*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
82*1c60b9acSAndroid Build Coastguard Worker
83*1c60b9acSAndroid Build Coastguard Worker if (!h->ssi.state)
84*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
85*1c60b9acSAndroid Build Coastguard Worker
86*1c60b9acSAndroid Build Coastguard Worker h->h_in_svc = h;
87*1c60b9acSAndroid Build Coastguard Worker ret = h->ssi.state((void *)((uint8_t *)&h[1]), NULL, cs, flags);
88*1c60b9acSAndroid Build Coastguard Worker h->h_in_svc = NULL;
89*1c60b9acSAndroid Build Coastguard Worker
90*1c60b9acSAndroid Build Coastguard Worker return ret;
91*1c60b9acSAndroid Build Coastguard Worker }
92*1c60b9acSAndroid Build Coastguard Worker
93*1c60b9acSAndroid Build Coastguard Worker static void
lws_sspc_sul_retry_cb(lws_sorted_usec_list_t * sul)94*1c60b9acSAndroid Build Coastguard Worker lws_sspc_sul_retry_cb(lws_sorted_usec_list_t *sul)
95*1c60b9acSAndroid Build Coastguard Worker {
96*1c60b9acSAndroid Build Coastguard Worker lws_sspc_handle_t *h = lws_container_of(sul, lws_sspc_handle_t, sul_retry);
97*1c60b9acSAndroid Build Coastguard Worker static struct lws_client_connect_info i;
98*1c60b9acSAndroid Build Coastguard Worker
99*1c60b9acSAndroid Build Coastguard Worker /*
100*1c60b9acSAndroid Build Coastguard Worker * We may have started up before the system proxy, so be prepared with
101*1c60b9acSAndroid Build Coastguard Worker * a sul to retry at 1Hz
102*1c60b9acSAndroid Build Coastguard Worker */
103*1c60b9acSAndroid Build Coastguard Worker
104*1c60b9acSAndroid Build Coastguard Worker memset(&i, 0, sizeof i);
105*1c60b9acSAndroid Build Coastguard Worker i.context = h->context;
106*1c60b9acSAndroid Build Coastguard Worker if (h->context->ss_proxy_port) { /* tcp */
107*1c60b9acSAndroid Build Coastguard Worker i.address = h->context->ss_proxy_address;
108*1c60b9acSAndroid Build Coastguard Worker i.port = h->context->ss_proxy_port;
109*1c60b9acSAndroid Build Coastguard Worker i.iface = h->context->ss_proxy_bind;
110*1c60b9acSAndroid Build Coastguard Worker } else {
111*1c60b9acSAndroid Build Coastguard Worker if (h->context->ss_proxy_bind)
112*1c60b9acSAndroid Build Coastguard Worker i.address = h->context->ss_proxy_bind;
113*1c60b9acSAndroid Build Coastguard Worker else
114*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__)
115*1c60b9acSAndroid Build Coastguard Worker i.address = "+@proxy.ss.lws";
116*1c60b9acSAndroid Build Coastguard Worker #else
117*1c60b9acSAndroid Build Coastguard Worker i.address = "+/tmp/proxy.ss.lws";
118*1c60b9acSAndroid Build Coastguard Worker #endif
119*1c60b9acSAndroid Build Coastguard Worker }
120*1c60b9acSAndroid Build Coastguard Worker i.host = i.address;
121*1c60b9acSAndroid Build Coastguard Worker i.origin = i.address;
122*1c60b9acSAndroid Build Coastguard Worker i.method = "RAW";
123*1c60b9acSAndroid Build Coastguard Worker i.protocol = lws_sspc_protocols[0].name;
124*1c60b9acSAndroid Build Coastguard Worker i.local_protocol_name = lws_sspc_protocols[0].name;
125*1c60b9acSAndroid Build Coastguard Worker i.path = "";
126*1c60b9acSAndroid Build Coastguard Worker i.pwsi = &h->cwsi;
127*1c60b9acSAndroid Build Coastguard Worker i.opaque_user_data = (void *)h;
128*1c60b9acSAndroid Build Coastguard Worker i.ssl_connection = LCCSCF_SECSTREAM_PROXY_LINK;
129*1c60b9acSAndroid Build Coastguard Worker
130*1c60b9acSAndroid Build Coastguard Worker lws_metrics_caliper_bind(h->cal_txn, h->context->mt_ss_cliprox_conn);
131*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_METRICS)
132*1c60b9acSAndroid Build Coastguard Worker lws_metrics_tag_add(&h->cal_txn.mtags_owner, "ss", h->ssi.streamtype);
133*1c60b9acSAndroid Build Coastguard Worker #endif
134*1c60b9acSAndroid Build Coastguard Worker
135*1c60b9acSAndroid Build Coastguard Worker /* this wsi is the link to the proxy */
136*1c60b9acSAndroid Build Coastguard Worker
137*1c60b9acSAndroid Build Coastguard Worker if (!lws_client_connect_via_info(&i)) {
138*1c60b9acSAndroid Build Coastguard Worker
139*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_METRICS)
140*1c60b9acSAndroid Build Coastguard Worker /*
141*1c60b9acSAndroid Build Coastguard Worker * If any hanging caliper measurement, dump it, and free any tags
142*1c60b9acSAndroid Build Coastguard Worker */
143*1c60b9acSAndroid Build Coastguard Worker lws_metrics_caliper_report_hist(h->cal_txn, (struct lws *)NULL);
144*1c60b9acSAndroid Build Coastguard Worker #endif
145*1c60b9acSAndroid Build Coastguard Worker
146*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(h->context, 0, &h->sul_retry,
147*1c60b9acSAndroid Build Coastguard Worker lws_sspc_sul_retry_cb, LWS_US_PER_SEC);
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker return;
150*1c60b9acSAndroid Build Coastguard Worker }
151*1c60b9acSAndroid Build Coastguard Worker
152*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_notice(h, "%s", h->cwsi->lc.gutag);
153*1c60b9acSAndroid Build Coastguard Worker }
154*1c60b9acSAndroid Build Coastguard Worker
155*1c60b9acSAndroid Build Coastguard Worker static int
lws_sspc_serialize_metadata(lws_sspc_handle_t * h,lws_sspc_metadata_t * md,uint8_t * p,uint8_t * end)156*1c60b9acSAndroid Build Coastguard Worker lws_sspc_serialize_metadata(lws_sspc_handle_t *h, lws_sspc_metadata_t *md,
157*1c60b9acSAndroid Build Coastguard Worker uint8_t *p, uint8_t *end)
158*1c60b9acSAndroid Build Coastguard Worker {
159*1c60b9acSAndroid Build Coastguard Worker int n, txc;
160*1c60b9acSAndroid Build Coastguard Worker
161*1c60b9acSAndroid Build Coastguard Worker if (md->name[0] == '\0') {
162*1c60b9acSAndroid Build Coastguard Worker
163*1c60b9acSAndroid Build Coastguard Worker lwsl_info("sending tx credit update %d\n",
164*1c60b9acSAndroid Build Coastguard Worker md->tx_cr_adjust);
165*1c60b9acSAndroid Build Coastguard Worker
166*1c60b9acSAndroid Build Coastguard Worker p[0] = LWSSS_SER_TXPRE_TXCR_UPDATE;
167*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu16be(&p[1], 4);
168*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu32be(&p[3], (uint32_t)md->tx_cr_adjust);
169*1c60b9acSAndroid Build Coastguard Worker
170*1c60b9acSAndroid Build Coastguard Worker n = 7;
171*1c60b9acSAndroid Build Coastguard Worker
172*1c60b9acSAndroid Build Coastguard Worker } else {
173*1c60b9acSAndroid Build Coastguard Worker
174*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "sending metadata");
175*1c60b9acSAndroid Build Coastguard Worker
176*1c60b9acSAndroid Build Coastguard Worker p[0] = LWSSS_SER_TXPRE_METADATA;
177*1c60b9acSAndroid Build Coastguard Worker txc = (int)strlen(md->name);
178*1c60b9acSAndroid Build Coastguard Worker n = txc + 1 + (int)md->len;
179*1c60b9acSAndroid Build Coastguard Worker if (n > 0xffff)
180*1c60b9acSAndroid Build Coastguard Worker /* we can't serialize this metadata in 16b length */
181*1c60b9acSAndroid Build Coastguard Worker return -1;
182*1c60b9acSAndroid Build Coastguard Worker if (n > lws_ptr_diff(end, &p[4]))
183*1c60b9acSAndroid Build Coastguard Worker /* we don't have space for this metadata */
184*1c60b9acSAndroid Build Coastguard Worker return -1;
185*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu16be(&p[1], (uint16_t)n);
186*1c60b9acSAndroid Build Coastguard Worker p[3] = (uint8_t)txc;
187*1c60b9acSAndroid Build Coastguard Worker memcpy(&p[4], md->name, (unsigned int)txc);
188*1c60b9acSAndroid Build Coastguard Worker memcpy(&p[4 + txc], &md[1], md->len);
189*1c60b9acSAndroid Build Coastguard Worker n = 4 + txc + (int)md->len;
190*1c60b9acSAndroid Build Coastguard Worker }
191*1c60b9acSAndroid Build Coastguard Worker
192*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&md->list);
193*1c60b9acSAndroid Build Coastguard Worker lws_free(md);
194*1c60b9acSAndroid Build Coastguard Worker
195*1c60b9acSAndroid Build Coastguard Worker return n;
196*1c60b9acSAndroid Build Coastguard Worker }
197*1c60b9acSAndroid Build Coastguard Worker
198*1c60b9acSAndroid Build Coastguard Worker static int
callback_sspc_client(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)199*1c60b9acSAndroid Build Coastguard Worker callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason,
200*1c60b9acSAndroid Build Coastguard Worker void *user, void *in, size_t len)
201*1c60b9acSAndroid Build Coastguard Worker {
202*1c60b9acSAndroid Build Coastguard Worker lws_sspc_handle_t *h = (lws_sspc_handle_t *)lws_get_opaque_user_data(wsi);
203*1c60b9acSAndroid Build Coastguard Worker size_t pktsize = wsi->a.context->max_http_header_data;
204*1c60b9acSAndroid Build Coastguard Worker void *m = (void *)((uint8_t *)&h[1]);
205*1c60b9acSAndroid Build Coastguard Worker uint8_t *pkt = NULL, *p = NULL, *end = NULL;
206*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_return_t r;
207*1c60b9acSAndroid Build Coastguard Worker uint64_t interval;
208*1c60b9acSAndroid Build Coastguard Worker const uint8_t *cp;
209*1c60b9acSAndroid Build Coastguard Worker uint8_t s[64];
210*1c60b9acSAndroid Build Coastguard Worker lws_usec_t us;
211*1c60b9acSAndroid Build Coastguard Worker int flags, n;
212*1c60b9acSAndroid Build Coastguard Worker
213*1c60b9acSAndroid Build Coastguard Worker switch (reason) {
214*1c60b9acSAndroid Build Coastguard Worker
215*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CONNECTING:
216*1c60b9acSAndroid Build Coastguard Worker /*
217*1c60b9acSAndroid Build Coastguard Worker * In our particular case, we want CCEs even inside the
218*1c60b9acSAndroid Build Coastguard Worker * initial connect loop time
219*1c60b9acSAndroid Build Coastguard Worker */
220*1c60b9acSAndroid Build Coastguard Worker wsi->client_suppress_CONNECTION_ERROR = 0;
221*1c60b9acSAndroid Build Coastguard Worker break;
222*1c60b9acSAndroid Build Coastguard Worker
223*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
224*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: CCE: %s\n", __func__,
225*1c60b9acSAndroid Build Coastguard Worker in ? (const char *)in : "null");
226*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_METRICS)
227*1c60b9acSAndroid Build Coastguard Worker /*
228*1c60b9acSAndroid Build Coastguard Worker * If any hanging caliper measurement, dump it, and free any tags
229*1c60b9acSAndroid Build Coastguard Worker */
230*1c60b9acSAndroid Build Coastguard Worker lws_metrics_caliper_report_hist(h->cal_txn, (struct lws *)NULL);
231*1c60b9acSAndroid Build Coastguard Worker #endif
232*1c60b9acSAndroid Build Coastguard Worker lws_set_opaque_user_data(wsi, NULL);
233*1c60b9acSAndroid Build Coastguard Worker h->cwsi = NULL;
234*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(h->context, 0, &h->sul_retry,
235*1c60b9acSAndroid Build Coastguard Worker lws_sspc_sul_retry_cb, LWS_US_PER_SEC);
236*1c60b9acSAndroid Build Coastguard Worker if (h->ssi.state) {
237*1c60b9acSAndroid Build Coastguard Worker interval = (uint64_t)(lws_now_usecs() - h->us_start_upstream) /
238*1c60b9acSAndroid Build Coastguard Worker LWS_US_PER_MS;
239*1c60b9acSAndroid Build Coastguard Worker if (interval > 0xffffffffull)
240*1c60b9acSAndroid Build Coastguard Worker interval = 0xffffffffull;
241*1c60b9acSAndroid Build Coastguard Worker r = h->ssi.state(lws_sspc_to_user_object(h), NULL,
242*1c60b9acSAndroid Build Coastguard Worker LWSSSCS_UPSTREAM_LINK_RETRY,
243*1c60b9acSAndroid Build Coastguard Worker (uint32_t)interval);
244*1c60b9acSAndroid Build Coastguard Worker if (r == LWSSSSRET_DESTROY_ME)
245*1c60b9acSAndroid Build Coastguard Worker lws_sspc_destroy(&h);
246*1c60b9acSAndroid Build Coastguard Worker }
247*1c60b9acSAndroid Build Coastguard Worker break;
248*1c60b9acSAndroid Build Coastguard Worker
249*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_CONNECTED:
250*1c60b9acSAndroid Build Coastguard Worker if (!h || lws_fi(&h->fic, "sspc_fail_on_linkup"))
251*1c60b9acSAndroid Build Coastguard Worker return -1;
252*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "CONNECTED (%s)", h->ssi.streamtype);
253*1c60b9acSAndroid Build Coastguard Worker
254*1c60b9acSAndroid Build Coastguard Worker h->state = LPCSCLI_SENDING_INITIAL_TX;
255*1c60b9acSAndroid Build Coastguard Worker /*
256*1c60b9acSAndroid Build Coastguard Worker * We create the dsh at the response to the initial tx, which
257*1c60b9acSAndroid Build Coastguard Worker * will let us know the policy's max size for it... let's
258*1c60b9acSAndroid Build Coastguard Worker * protect the connection with a promise to complete the
259*1c60b9acSAndroid Build Coastguard Worker * SS serialization streamtype negotation within a short period,
260*1c60b9acSAndroid Build Coastguard Worker * we will cancel this timeout when we have the proxy's ack
261*1c60b9acSAndroid Build Coastguard Worker * of the streamtype serialization, eg, it exists in the proxy
262*1c60b9acSAndroid Build Coastguard Worker * policy etc
263*1c60b9acSAndroid Build Coastguard Worker */
264*1c60b9acSAndroid Build Coastguard Worker lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, 3);
265*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
266*1c60b9acSAndroid Build Coastguard Worker h->us_start_upstream = 0;
267*1c60b9acSAndroid Build Coastguard Worker break;
268*1c60b9acSAndroid Build Coastguard Worker
269*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_CLOSE:
270*1c60b9acSAndroid Build Coastguard Worker /*
271*1c60b9acSAndroid Build Coastguard Worker * our ss proxy Unix Domain socket has closed...
272*1c60b9acSAndroid Build Coastguard Worker */
273*1c60b9acSAndroid Build Coastguard Worker if (!h) {
274*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: no sspc on client proxy link close", __func__);
275*1c60b9acSAndroid Build Coastguard Worker break;
276*1c60b9acSAndroid Build Coastguard Worker }
277*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "LWS_CALLBACK_RAW_CLOSE: proxy conn down, wsi %s",
278*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi));
279*1c60b9acSAndroid Build Coastguard Worker
280*1c60b9acSAndroid Build Coastguard Worker lws_dsh_destroy(&h->dsh);
281*1c60b9acSAndroid Build Coastguard Worker if (h->ss_dangling_connected && h->ssi.state) {
282*1c60b9acSAndroid Build Coastguard Worker
283*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_notice(h, "setting _DISCONNECTED");
284*1c60b9acSAndroid Build Coastguard Worker h->ss_dangling_connected = 0;
285*1c60b9acSAndroid Build Coastguard Worker h->prev_ss_state = LWSSSCS_DISCONNECTED;
286*1c60b9acSAndroid Build Coastguard Worker r = h->ssi.state(ss_to_userobj(h), NULL,
287*1c60b9acSAndroid Build Coastguard Worker LWSSSCS_DISCONNECTED, 0);
288*1c60b9acSAndroid Build Coastguard Worker if (r == LWSSSSRET_DESTROY_ME) {
289*1c60b9acSAndroid Build Coastguard Worker h->cwsi = NULL;
290*1c60b9acSAndroid Build Coastguard Worker lws_set_opaque_user_data(wsi, NULL);
291*1c60b9acSAndroid Build Coastguard Worker lws_sspc_destroy(&h);
292*1c60b9acSAndroid Build Coastguard Worker break;
293*1c60b9acSAndroid Build Coastguard Worker }
294*1c60b9acSAndroid Build Coastguard Worker }
295*1c60b9acSAndroid Build Coastguard Worker
296*1c60b9acSAndroid Build Coastguard Worker h->cwsi = NULL;
297*1c60b9acSAndroid Build Coastguard Worker /*
298*1c60b9acSAndroid Build Coastguard Worker * schedule a reconnect in 1s
299*1c60b9acSAndroid Build Coastguard Worker */
300*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(h->context, 0, &h->sul_retry,
301*1c60b9acSAndroid Build Coastguard Worker lws_sspc_sul_retry_cb, LWS_US_PER_SEC);
302*1c60b9acSAndroid Build Coastguard Worker
303*1c60b9acSAndroid Build Coastguard Worker break;
304*1c60b9acSAndroid Build Coastguard Worker
305*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_RX:
306*1c60b9acSAndroid Build Coastguard Worker /*
307*1c60b9acSAndroid Build Coastguard Worker * ie, the proxy has sent us something
308*1c60b9acSAndroid Build Coastguard Worker */
309*1c60b9acSAndroid Build Coastguard Worker
310*1c60b9acSAndroid Build Coastguard Worker if (!h || !h->cwsi) {
311*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: rx when client ss destroyed\n", __func__);
312*1c60b9acSAndroid Build Coastguard Worker
313*1c60b9acSAndroid Build Coastguard Worker return -1;
314*1c60b9acSAndroid Build Coastguard Worker }
315*1c60b9acSAndroid Build Coastguard Worker
316*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "%s: RAW_RX: rx %d\n", __func__, (int)len);
317*1c60b9acSAndroid Build Coastguard Worker
318*1c60b9acSAndroid Build Coastguard Worker if (!len) {
319*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_notice(h, "RAW_RX: zero len");
320*1c60b9acSAndroid Build Coastguard Worker
321*1c60b9acSAndroid Build Coastguard Worker return -1;
322*1c60b9acSAndroid Build Coastguard Worker }
323*1c60b9acSAndroid Build Coastguard Worker
324*1c60b9acSAndroid Build Coastguard Worker if (lws_fi(&h->fic, "sspc_fake_rxparse_disconnect_me"))
325*1c60b9acSAndroid Build Coastguard Worker n = LWSSSSRET_DISCONNECT_ME;
326*1c60b9acSAndroid Build Coastguard Worker else
327*1c60b9acSAndroid Build Coastguard Worker if (lws_fi(&h->fic, "sspc_fake_rxparse_destroy_me"))
328*1c60b9acSAndroid Build Coastguard Worker n = LWSSSSRET_DESTROY_ME;
329*1c60b9acSAndroid Build Coastguard Worker else
330*1c60b9acSAndroid Build Coastguard Worker n = lws_ss_deserialize_parse(&h->parser,
331*1c60b9acSAndroid Build Coastguard Worker lws_get_context(wsi),
332*1c60b9acSAndroid Build Coastguard Worker h->dsh, in, len,
333*1c60b9acSAndroid Build Coastguard Worker &h->state, h,
334*1c60b9acSAndroid Build Coastguard Worker (lws_ss_handle_t **)m,
335*1c60b9acSAndroid Build Coastguard Worker &h->ssi, 1);
336*1c60b9acSAndroid Build Coastguard Worker switch (n) {
337*1c60b9acSAndroid Build Coastguard Worker case LWSSSSRET_OK:
338*1c60b9acSAndroid Build Coastguard Worker break;
339*1c60b9acSAndroid Build Coastguard Worker case LWSSSSRET_DISCONNECT_ME:
340*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: proxlicent RX ended with DISCONNECT_ME\n",
341*1c60b9acSAndroid Build Coastguard Worker __func__);
342*1c60b9acSAndroid Build Coastguard Worker return -1;
343*1c60b9acSAndroid Build Coastguard Worker case LWSSSSRET_DESTROY_ME:
344*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: proxlicent RX ended with DESTROY_ME\n",
345*1c60b9acSAndroid Build Coastguard Worker __func__);
346*1c60b9acSAndroid Build Coastguard Worker lws_set_opaque_user_data(wsi, NULL);
347*1c60b9acSAndroid Build Coastguard Worker lws_sspc_destroy(&h);
348*1c60b9acSAndroid Build Coastguard Worker return -1;
349*1c60b9acSAndroid Build Coastguard Worker }
350*1c60b9acSAndroid Build Coastguard Worker
351*1c60b9acSAndroid Build Coastguard Worker if (h->state == LPCSCLI_LOCAL_CONNECTED ||
352*1c60b9acSAndroid Build Coastguard Worker h->state == LPCSCLI_ONWARD_CONNECT)
353*1c60b9acSAndroid Build Coastguard Worker lws_set_timeout(wsi, 0, 0);
354*1c60b9acSAndroid Build Coastguard Worker
355*1c60b9acSAndroid Build Coastguard Worker break;
356*1c60b9acSAndroid Build Coastguard Worker
357*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_WRITEABLE:
358*1c60b9acSAndroid Build Coastguard Worker
359*1c60b9acSAndroid Build Coastguard Worker /*
360*1c60b9acSAndroid Build Coastguard Worker * We can transmit something to the proxy...
361*1c60b9acSAndroid Build Coastguard Worker */
362*1c60b9acSAndroid Build Coastguard Worker
363*1c60b9acSAndroid Build Coastguard Worker if (!h)
364*1c60b9acSAndroid Build Coastguard Worker break;
365*1c60b9acSAndroid Build Coastguard Worker
366*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_debug(h, "WRITEABLE %s, state %d",
367*1c60b9acSAndroid Build Coastguard Worker wsi->lc.gutag, h->state);
368*1c60b9acSAndroid Build Coastguard Worker
369*1c60b9acSAndroid Build Coastguard Worker /*
370*1c60b9acSAndroid Build Coastguard Worker * Management of ss timeout can happen any time and doesn't
371*1c60b9acSAndroid Build Coastguard Worker * depend on wsi existence or state
372*1c60b9acSAndroid Build Coastguard Worker */
373*1c60b9acSAndroid Build Coastguard Worker
374*1c60b9acSAndroid Build Coastguard Worker n = 0;
375*1c60b9acSAndroid Build Coastguard Worker cp = s;
376*1c60b9acSAndroid Build Coastguard Worker
377*1c60b9acSAndroid Build Coastguard Worker if (h->pending_timeout_update) {
378*1c60b9acSAndroid Build Coastguard Worker s[0] = LWSSS_SER_TXPRE_TIMEOUT_UPDATE;
379*1c60b9acSAndroid Build Coastguard Worker s[1] = 0;
380*1c60b9acSAndroid Build Coastguard Worker s[2] = 4;
381*1c60b9acSAndroid Build Coastguard Worker /*
382*1c60b9acSAndroid Build Coastguard Worker * 0: use policy timeout value
383*1c60b9acSAndroid Build Coastguard Worker * 0xffffffff: cancel the timeout
384*1c60b9acSAndroid Build Coastguard Worker */
385*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu32be(&s[3], h->timeout_ms);
386*1c60b9acSAndroid Build Coastguard Worker /* in case anything else to write */
387*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(h->cwsi);
388*1c60b9acSAndroid Build Coastguard Worker h->pending_timeout_update = 0;
389*1c60b9acSAndroid Build Coastguard Worker n = 7;
390*1c60b9acSAndroid Build Coastguard Worker goto do_write;
391*1c60b9acSAndroid Build Coastguard Worker }
392*1c60b9acSAndroid Build Coastguard Worker
393*1c60b9acSAndroid Build Coastguard Worker s[1] = 0;
394*1c60b9acSAndroid Build Coastguard Worker /*
395*1c60b9acSAndroid Build Coastguard Worker * This is the state of the link that connects us to the onward
396*1c60b9acSAndroid Build Coastguard Worker * proxy
397*1c60b9acSAndroid Build Coastguard Worker */
398*1c60b9acSAndroid Build Coastguard Worker switch (h->state) {
399*1c60b9acSAndroid Build Coastguard Worker case LPCSCLI_SENDING_INITIAL_TX:
400*1c60b9acSAndroid Build Coastguard Worker /*
401*1c60b9acSAndroid Build Coastguard Worker * We are negotating the opening of a particular
402*1c60b9acSAndroid Build Coastguard Worker * streamtype
403*1c60b9acSAndroid Build Coastguard Worker */
404*1c60b9acSAndroid Build Coastguard Worker n = (int)strlen(h->ssi.streamtype) + 1 + 4 + 4;
405*1c60b9acSAndroid Build Coastguard Worker
406*1c60b9acSAndroid Build Coastguard Worker s[0] = LWSSS_SER_TXPRE_STREAMTYPE;
407*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu16be(&s[1], (uint16_t)n);
408*1c60b9acSAndroid Build Coastguard Worker /* SSSv1: add protocol version byte (initially 1) */
409*1c60b9acSAndroid Build Coastguard Worker s[3] = (uint8_t)LWS_SSS_CLIENT_PROTOCOL_VERSION;
410*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu32be(&s[4], (uint32_t)getpid());
411*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu32be(&s[8], (uint32_t)h->txc.peer_tx_cr_est);
412*1c60b9acSAndroid Build Coastguard Worker //h->txcr_out = txc;
413*1c60b9acSAndroid Build Coastguard Worker lws_strncpy((char *)&s[12], h->ssi.streamtype, sizeof(s) - 12);
414*1c60b9acSAndroid Build Coastguard Worker n += 3;
415*1c60b9acSAndroid Build Coastguard Worker h->state = LPCSCLI_WAITING_CREATE_RESULT;
416*1c60b9acSAndroid Build Coastguard Worker
417*1c60b9acSAndroid Build Coastguard Worker break;
418*1c60b9acSAndroid Build Coastguard Worker
419*1c60b9acSAndroid Build Coastguard Worker case LPCSCLI_LOCAL_CONNECTED:
420*1c60b9acSAndroid Build Coastguard Worker
421*1c60b9acSAndroid Build Coastguard Worker // lwsl_notice("%s: LPCSCLI_LOCAL_CONNECTED\n", __func__);
422*1c60b9acSAndroid Build Coastguard Worker
423*1c60b9acSAndroid Build Coastguard Worker /*
424*1c60b9acSAndroid Build Coastguard Worker * Do we need to prioritize sending any metadata
425*1c60b9acSAndroid Build Coastguard Worker * changes?
426*1c60b9acSAndroid Build Coastguard Worker */
427*1c60b9acSAndroid Build Coastguard Worker
428*1c60b9acSAndroid Build Coastguard Worker if (h->metadata_owner.count) {
429*1c60b9acSAndroid Build Coastguard Worker lws_sspc_metadata_t *md = lws_container_of(
430*1c60b9acSAndroid Build Coastguard Worker lws_dll2_get_tail(&h->metadata_owner),
431*1c60b9acSAndroid Build Coastguard Worker lws_sspc_metadata_t, list);
432*1c60b9acSAndroid Build Coastguard Worker
433*1c60b9acSAndroid Build Coastguard Worker pkt = lws_malloc(pktsize + LWS_PRE, __func__);
434*1c60b9acSAndroid Build Coastguard Worker if (!pkt)
435*1c60b9acSAndroid Build Coastguard Worker goto hangup;
436*1c60b9acSAndroid Build Coastguard Worker cp = p = pkt + LWS_PRE;
437*1c60b9acSAndroid Build Coastguard Worker end = p + pktsize;
438*1c60b9acSAndroid Build Coastguard Worker
439*1c60b9acSAndroid Build Coastguard Worker n = lws_sspc_serialize_metadata(h, md, p, end);
440*1c60b9acSAndroid Build Coastguard Worker if (n < 0)
441*1c60b9acSAndroid Build Coastguard Worker goto metadata_hangup;
442*1c60b9acSAndroid Build Coastguard Worker
443*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_debug(h, "(local_conn) metadata");
444*1c60b9acSAndroid Build Coastguard Worker
445*1c60b9acSAndroid Build Coastguard Worker goto req_write_and_issue;
446*1c60b9acSAndroid Build Coastguard Worker }
447*1c60b9acSAndroid Build Coastguard Worker
448*1c60b9acSAndroid Build Coastguard Worker if (h->pending_writeable_len) {
449*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_debug(h, "(local_conn) PAYLOAD_LENGTH_HINT %u",
450*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h->writeable_len);
451*1c60b9acSAndroid Build Coastguard Worker s[0] = LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT;
452*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu16be(&s[1], 4);
453*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu32be(&s[3], (uint32_t)h->writeable_len);
454*1c60b9acSAndroid Build Coastguard Worker h->pending_writeable_len = 0;
455*1c60b9acSAndroid Build Coastguard Worker n = 7;
456*1c60b9acSAndroid Build Coastguard Worker goto req_write_and_issue;
457*1c60b9acSAndroid Build Coastguard Worker }
458*1c60b9acSAndroid Build Coastguard Worker
459*1c60b9acSAndroid Build Coastguard Worker if (h->conn_req_state >= LWSSSPC_ONW_ONGOING) {
460*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "conn_req_state %d",
461*1c60b9acSAndroid Build Coastguard Worker h->conn_req_state);
462*1c60b9acSAndroid Build Coastguard Worker break;
463*1c60b9acSAndroid Build Coastguard Worker }
464*1c60b9acSAndroid Build Coastguard Worker
465*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "(local_conn) onward connect");
466*1c60b9acSAndroid Build Coastguard Worker
467*1c60b9acSAndroid Build Coastguard Worker h->conn_req_state = LWSSSPC_ONW_ONGOING;
468*1c60b9acSAndroid Build Coastguard Worker
469*1c60b9acSAndroid Build Coastguard Worker s[0] = LWSSS_SER_TXPRE_ONWARD_CONNECT;
470*1c60b9acSAndroid Build Coastguard Worker s[1] = 0;
471*1c60b9acSAndroid Build Coastguard Worker s[2] = 0;
472*1c60b9acSAndroid Build Coastguard Worker n = 3;
473*1c60b9acSAndroid Build Coastguard Worker break;
474*1c60b9acSAndroid Build Coastguard Worker
475*1c60b9acSAndroid Build Coastguard Worker case LPCSCLI_OPERATIONAL:
476*1c60b9acSAndroid Build Coastguard Worker
477*1c60b9acSAndroid Build Coastguard Worker /*
478*1c60b9acSAndroid Build Coastguard Worker *
479*1c60b9acSAndroid Build Coastguard Worker * - Do we need to prioritize sending any metadata
480*1c60b9acSAndroid Build Coastguard Worker * changes? (includes txcr updates)
481*1c60b9acSAndroid Build Coastguard Worker *
482*1c60b9acSAndroid Build Coastguard Worker * - Do we need to forward a hint about the payload
483*1c60b9acSAndroid Build Coastguard Worker * length?
484*1c60b9acSAndroid Build Coastguard Worker */
485*1c60b9acSAndroid Build Coastguard Worker
486*1c60b9acSAndroid Build Coastguard Worker pkt = lws_malloc(pktsize + LWS_PRE, __func__);
487*1c60b9acSAndroid Build Coastguard Worker if (!pkt)
488*1c60b9acSAndroid Build Coastguard Worker goto hangup;
489*1c60b9acSAndroid Build Coastguard Worker cp = p = pkt + LWS_PRE;
490*1c60b9acSAndroid Build Coastguard Worker end = p + pktsize;
491*1c60b9acSAndroid Build Coastguard Worker
492*1c60b9acSAndroid Build Coastguard Worker if (h->metadata_owner.count) {
493*1c60b9acSAndroid Build Coastguard Worker lws_sspc_metadata_t *md = lws_container_of(
494*1c60b9acSAndroid Build Coastguard Worker lws_dll2_get_tail(&h->metadata_owner),
495*1c60b9acSAndroid Build Coastguard Worker lws_sspc_metadata_t, list);
496*1c60b9acSAndroid Build Coastguard Worker
497*1c60b9acSAndroid Build Coastguard Worker n = lws_sspc_serialize_metadata(h, md, p, end);
498*1c60b9acSAndroid Build Coastguard Worker if (n < 0)
499*1c60b9acSAndroid Build Coastguard Worker goto metadata_hangup;
500*1c60b9acSAndroid Build Coastguard Worker
501*1c60b9acSAndroid Build Coastguard Worker goto req_write_and_issue;
502*1c60b9acSAndroid Build Coastguard Worker }
503*1c60b9acSAndroid Build Coastguard Worker
504*1c60b9acSAndroid Build Coastguard Worker if (h->pending_writeable_len) {
505*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "PAYLOAD_LENGTH_HINT %u",
506*1c60b9acSAndroid Build Coastguard Worker (unsigned int)h->writeable_len);
507*1c60b9acSAndroid Build Coastguard Worker s[0] = LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT;
508*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu16be(&s[1], 4);
509*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu32be(&s[3], (uint32_t)h->writeable_len);
510*1c60b9acSAndroid Build Coastguard Worker h->pending_writeable_len = 0;
511*1c60b9acSAndroid Build Coastguard Worker n = 7;
512*1c60b9acSAndroid Build Coastguard Worker goto req_write_and_issue;
513*1c60b9acSAndroid Build Coastguard Worker }
514*1c60b9acSAndroid Build Coastguard Worker
515*1c60b9acSAndroid Build Coastguard Worker /* we can't write anything if we don't have credit */
516*1c60b9acSAndroid Build Coastguard Worker if (!h->ignore_txc && h->txc.tx_cr <= 0) {
517*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "WRITEABLE / OPERATIONAL:"
518*1c60b9acSAndroid Build Coastguard Worker " lack credit (%d)",
519*1c60b9acSAndroid Build Coastguard Worker h->txc.tx_cr);
520*1c60b9acSAndroid Build Coastguard Worker // break;
521*1c60b9acSAndroid Build Coastguard Worker }
522*1c60b9acSAndroid Build Coastguard Worker
523*1c60b9acSAndroid Build Coastguard Worker len = pktsize - LWS_PRE - 19;
524*1c60b9acSAndroid Build Coastguard Worker flags = 0;
525*1c60b9acSAndroid Build Coastguard Worker if (!h->ssi.tx) {
526*1c60b9acSAndroid Build Coastguard Worker n = 0;
527*1c60b9acSAndroid Build Coastguard Worker goto do_write_nz;
528*1c60b9acSAndroid Build Coastguard Worker }
529*1c60b9acSAndroid Build Coastguard Worker
530*1c60b9acSAndroid Build Coastguard Worker n = h->ssi.tx(m, h->ord++, pkt + LWS_PRE + 19, &len,
531*1c60b9acSAndroid Build Coastguard Worker &flags);
532*1c60b9acSAndroid Build Coastguard Worker switch (n) {
533*1c60b9acSAndroid Build Coastguard Worker case LWSSSSRET_TX_DONT_SEND:
534*1c60b9acSAndroid Build Coastguard Worker n = 0;
535*1c60b9acSAndroid Build Coastguard Worker goto do_write_nz;
536*1c60b9acSAndroid Build Coastguard Worker
537*1c60b9acSAndroid Build Coastguard Worker case LWSSSSRET_DISCONNECT_ME:
538*1c60b9acSAndroid Build Coastguard Worker case LWSSSSRET_DESTROY_ME:
539*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: sspc tx DISCONNECT/DESTROY unimplemented\n", __func__);
540*1c60b9acSAndroid Build Coastguard Worker break;
541*1c60b9acSAndroid Build Coastguard Worker default:
542*1c60b9acSAndroid Build Coastguard Worker break;
543*1c60b9acSAndroid Build Coastguard Worker }
544*1c60b9acSAndroid Build Coastguard Worker
545*1c60b9acSAndroid Build Coastguard Worker h->txc.tx_cr = h->txc.tx_cr - (int)len;
546*1c60b9acSAndroid Build Coastguard Worker
547*1c60b9acSAndroid Build Coastguard Worker cp = p;
548*1c60b9acSAndroid Build Coastguard Worker n = (int)(len + 19);
549*1c60b9acSAndroid Build Coastguard Worker us = lws_now_usecs();
550*1c60b9acSAndroid Build Coastguard Worker p[0] = LWSSS_SER_TXPRE_TX_PAYLOAD;
551*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu16be(&p[1], (uint16_t)(len + 19 - 3));
552*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu32be(&p[3], (uint32_t)flags);
553*1c60b9acSAndroid Build Coastguard Worker /* time spent here waiting to send this */
554*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu32be(&p[7], (uint32_t)(us - h->us_earliest_write_req));
555*1c60b9acSAndroid Build Coastguard Worker /* ust that the client write happened */
556*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu64be(&p[11], (uint64_t)us);
557*1c60b9acSAndroid Build Coastguard Worker h->us_earliest_write_req = 0;
558*1c60b9acSAndroid Build Coastguard Worker
559*1c60b9acSAndroid Build Coastguard Worker if (flags & LWSSS_FLAG_EOM)
560*1c60b9acSAndroid Build Coastguard Worker if (h->rsidx + 1 < (int)LWS_ARRAY_SIZE(h->rideshare_ofs) &&
561*1c60b9acSAndroid Build Coastguard Worker h->rideshare_ofs[h->rsidx + 1])
562*1c60b9acSAndroid Build Coastguard Worker h->rsidx++;
563*1c60b9acSAndroid Build Coastguard Worker
564*1c60b9acSAndroid Build Coastguard Worker break;
565*1c60b9acSAndroid Build Coastguard Worker default:
566*1c60b9acSAndroid Build Coastguard Worker break;
567*1c60b9acSAndroid Build Coastguard Worker }
568*1c60b9acSAndroid Build Coastguard Worker
569*1c60b9acSAndroid Build Coastguard Worker do_write_nz:
570*1c60b9acSAndroid Build Coastguard Worker
571*1c60b9acSAndroid Build Coastguard Worker if (!n)
572*1c60b9acSAndroid Build Coastguard Worker break;
573*1c60b9acSAndroid Build Coastguard Worker
574*1c60b9acSAndroid Build Coastguard Worker do_write:
575*1c60b9acSAndroid Build Coastguard Worker if (lws_fi(&h->fic, "sspc_link_write_fail"))
576*1c60b9acSAndroid Build Coastguard Worker n = -1;
577*1c60b9acSAndroid Build Coastguard Worker else
578*1c60b9acSAndroid Build Coastguard Worker n = lws_write(wsi, (uint8_t *)cp, (unsigned int)n, LWS_WRITE_RAW);
579*1c60b9acSAndroid Build Coastguard Worker if (n < 0) {
580*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_notice(h, "WRITEABLE: %d", n);
581*1c60b9acSAndroid Build Coastguard Worker
582*1c60b9acSAndroid Build Coastguard Worker goto hangup;
583*1c60b9acSAndroid Build Coastguard Worker }
584*1c60b9acSAndroid Build Coastguard Worker break;
585*1c60b9acSAndroid Build Coastguard Worker
586*1c60b9acSAndroid Build Coastguard Worker default:
587*1c60b9acSAndroid Build Coastguard Worker break;
588*1c60b9acSAndroid Build Coastguard Worker }
589*1c60b9acSAndroid Build Coastguard Worker
590*1c60b9acSAndroid Build Coastguard Worker lws_free(pkt);
591*1c60b9acSAndroid Build Coastguard Worker
592*1c60b9acSAndroid Build Coastguard Worker return lws_callback_http_dummy(wsi, reason, user, in, len);
593*1c60b9acSAndroid Build Coastguard Worker
594*1c60b9acSAndroid Build Coastguard Worker metadata_hangup:
595*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_err(h, "metadata too large");
596*1c60b9acSAndroid Build Coastguard Worker
597*1c60b9acSAndroid Build Coastguard Worker hangup:
598*1c60b9acSAndroid Build Coastguard Worker lws_free(pkt);
599*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("hangup\n");
600*1c60b9acSAndroid Build Coastguard Worker /* hang up on him */
601*1c60b9acSAndroid Build Coastguard Worker return -1;
602*1c60b9acSAndroid Build Coastguard Worker
603*1c60b9acSAndroid Build Coastguard Worker req_write_and_issue:
604*1c60b9acSAndroid Build Coastguard Worker /* in case anything else to write */
605*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(h->cwsi);
606*1c60b9acSAndroid Build Coastguard Worker goto do_write_nz;
607*1c60b9acSAndroid Build Coastguard Worker }
608*1c60b9acSAndroid Build Coastguard Worker
609*1c60b9acSAndroid Build Coastguard Worker const struct lws_protocols lws_sspc_protocols[] = {
610*1c60b9acSAndroid Build Coastguard Worker {
611*1c60b9acSAndroid Build Coastguard Worker "ssproxy-protocol",
612*1c60b9acSAndroid Build Coastguard Worker callback_sspc_client,
613*1c60b9acSAndroid Build Coastguard Worker 0,
614*1c60b9acSAndroid Build Coastguard Worker 2048, 2048, NULL, 0
615*1c60b9acSAndroid Build Coastguard Worker },
616*1c60b9acSAndroid Build Coastguard Worker { NULL, NULL, 0, 0, 0, NULL, 0 }
617*1c60b9acSAndroid Build Coastguard Worker };
618*1c60b9acSAndroid Build Coastguard Worker
619*1c60b9acSAndroid Build Coastguard Worker int
lws_sspc_create(struct lws_context * context,int tsi,const lws_ss_info_t * ssi,void * opaque_user_data,lws_sspc_handle_t ** ppss,struct lws_sequencer * seq_owner,const char ** ppayload_fmt)620*1c60b9acSAndroid Build Coastguard Worker lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi,
621*1c60b9acSAndroid Build Coastguard Worker void *opaque_user_data, lws_sspc_handle_t **ppss,
622*1c60b9acSAndroid Build Coastguard Worker struct lws_sequencer *seq_owner, const char **ppayload_fmt)
623*1c60b9acSAndroid Build Coastguard Worker {
624*1c60b9acSAndroid Build Coastguard Worker lws_sspc_handle_t *h;
625*1c60b9acSAndroid Build Coastguard Worker uint8_t *ua;
626*1c60b9acSAndroid Build Coastguard Worker char *p;
627*1c60b9acSAndroid Build Coastguard Worker
628*1c60b9acSAndroid Build Coastguard Worker lws_service_assert_loop_thread(context, tsi);
629*1c60b9acSAndroid Build Coastguard Worker
630*1c60b9acSAndroid Build Coastguard Worker /* allocate the handle (including ssi), the user alloc,
631*1c60b9acSAndroid Build Coastguard Worker * and the streamname */
632*1c60b9acSAndroid Build Coastguard Worker
633*1c60b9acSAndroid Build Coastguard Worker h = malloc(sizeof(lws_sspc_handle_t) + ssi->user_alloc +
634*1c60b9acSAndroid Build Coastguard Worker strlen(ssi->streamtype) + 1);
635*1c60b9acSAndroid Build Coastguard Worker if (!h)
636*1c60b9acSAndroid Build Coastguard Worker return 1;
637*1c60b9acSAndroid Build Coastguard Worker memset(h, 0, sizeof(*h));
638*1c60b9acSAndroid Build Coastguard Worker
639*1c60b9acSAndroid Build Coastguard Worker h->lc.log_cx = context->log_cx;
640*1c60b9acSAndroid Build Coastguard Worker
641*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_FAULT_INJECTION)
642*1c60b9acSAndroid Build Coastguard Worker h->fic.name = "sspc";
643*1c60b9acSAndroid Build Coastguard Worker lws_xos_init(&h->fic.xos, lws_xos(&context->fic.xos));
644*1c60b9acSAndroid Build Coastguard Worker if (ssi->fic.fi_owner.count)
645*1c60b9acSAndroid Build Coastguard Worker lws_fi_import(&h->fic, &ssi->fic);
646*1c60b9acSAndroid Build Coastguard Worker
647*1c60b9acSAndroid Build Coastguard Worker lws_fi_inherit_copy(&h->fic, &context->fic, "ss", ssi->streamtype);
648*1c60b9acSAndroid Build Coastguard Worker #endif
649*1c60b9acSAndroid Build Coastguard Worker
650*1c60b9acSAndroid Build Coastguard Worker if (lws_fi(&h->fic, "sspc_create_oom")) {
651*1c60b9acSAndroid Build Coastguard Worker /*
652*1c60b9acSAndroid Build Coastguard Worker * We have to do this a litte later, so we can cleanly inherit
653*1c60b9acSAndroid Build Coastguard Worker * the OOM pieces and drain the info fic
654*1c60b9acSAndroid Build Coastguard Worker */
655*1c60b9acSAndroid Build Coastguard Worker lws_fi_destroy(&h->fic);
656*1c60b9acSAndroid Build Coastguard Worker free(h);
657*1c60b9acSAndroid Build Coastguard Worker return 1;
658*1c60b9acSAndroid Build Coastguard Worker }
659*1c60b9acSAndroid Build Coastguard Worker
660*1c60b9acSAndroid Build Coastguard Worker __lws_lc_tag(context, &context->lcg[LWSLCG_SSP_CLIENT], &h->lc,
661*1c60b9acSAndroid Build Coastguard Worker ssi->streamtype);
662*1c60b9acSAndroid Build Coastguard Worker
663*1c60b9acSAndroid Build Coastguard Worker memcpy(&h->ssi, ssi, sizeof(*ssi));
664*1c60b9acSAndroid Build Coastguard Worker ua = (uint8_t *)&h[1];
665*1c60b9acSAndroid Build Coastguard Worker memset(ua, 0, ssi->user_alloc);
666*1c60b9acSAndroid Build Coastguard Worker p = (char *)ua + ssi->user_alloc;
667*1c60b9acSAndroid Build Coastguard Worker memcpy(p, ssi->streamtype, strlen(ssi->streamtype) + 1);
668*1c60b9acSAndroid Build Coastguard Worker h->ssi.streamtype = (const char *)p;
669*1c60b9acSAndroid Build Coastguard Worker h->context = context;
670*1c60b9acSAndroid Build Coastguard Worker h->us_start_upstream = lws_now_usecs();
671*1c60b9acSAndroid Build Coastguard Worker
672*1c60b9acSAndroid Build Coastguard Worker if (!ssi->manual_initial_tx_credit)
673*1c60b9acSAndroid Build Coastguard Worker h->txc.peer_tx_cr_est = 500000000;
674*1c60b9acSAndroid Build Coastguard Worker else
675*1c60b9acSAndroid Build Coastguard Worker h->txc.peer_tx_cr_est = ssi->manual_initial_tx_credit;
676*1c60b9acSAndroid Build Coastguard Worker
677*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(ssi->streamtype, LWS_SMD_STREAMTYPENAME))
678*1c60b9acSAndroid Build Coastguard Worker h->ignore_txc = 1;
679*1c60b9acSAndroid Build Coastguard Worker
680*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_head(&h->client_list, &context->pt[tsi].ss_client_owner);
681*1c60b9acSAndroid Build Coastguard Worker
682*1c60b9acSAndroid Build Coastguard Worker /* fill in the things the real api does for the caller */
683*1c60b9acSAndroid Build Coastguard Worker
684*1c60b9acSAndroid Build Coastguard Worker *((void **)(ua + ssi->opaque_user_data_offset)) = opaque_user_data;
685*1c60b9acSAndroid Build Coastguard Worker *((void **)(ua + ssi->handle_offset)) = h;
686*1c60b9acSAndroid Build Coastguard Worker
687*1c60b9acSAndroid Build Coastguard Worker if (ppss)
688*1c60b9acSAndroid Build Coastguard Worker *ppss = h;
689*1c60b9acSAndroid Build Coastguard Worker
690*1c60b9acSAndroid Build Coastguard Worker /* try the actual connect */
691*1c60b9acSAndroid Build Coastguard Worker
692*1c60b9acSAndroid Build Coastguard Worker lws_sspc_sul_retry_cb(&h->sul_retry);
693*1c60b9acSAndroid Build Coastguard Worker
694*1c60b9acSAndroid Build Coastguard Worker return 0;
695*1c60b9acSAndroid Build Coastguard Worker }
696*1c60b9acSAndroid Build Coastguard Worker
697*1c60b9acSAndroid Build Coastguard Worker /* used on context destroy when iterating listed lws_ss on a pt */
698*1c60b9acSAndroid Build Coastguard Worker
699*1c60b9acSAndroid Build Coastguard Worker int
lws_sspc_destroy_dll(struct lws_dll2 * d,void * user)700*1c60b9acSAndroid Build Coastguard Worker lws_sspc_destroy_dll(struct lws_dll2 *d, void *user)
701*1c60b9acSAndroid Build Coastguard Worker {
702*1c60b9acSAndroid Build Coastguard Worker lws_sspc_handle_t *h = lws_container_of(d, lws_sspc_handle_t, client_list);
703*1c60b9acSAndroid Build Coastguard Worker
704*1c60b9acSAndroid Build Coastguard Worker lws_sspc_destroy(&h);
705*1c60b9acSAndroid Build Coastguard Worker
706*1c60b9acSAndroid Build Coastguard Worker return 0;
707*1c60b9acSAndroid Build Coastguard Worker }
708*1c60b9acSAndroid Build Coastguard Worker
709*1c60b9acSAndroid Build Coastguard Worker void
lws_sspc_rxmetadata_destroy(lws_sspc_handle_t * h)710*1c60b9acSAndroid Build Coastguard Worker lws_sspc_rxmetadata_destroy(lws_sspc_handle_t *h)
711*1c60b9acSAndroid Build Coastguard Worker {
712*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
713*1c60b9acSAndroid Build Coastguard Worker lws_dll2_get_head(&h->metadata_owner_rx)) {
714*1c60b9acSAndroid Build Coastguard Worker lws_sspc_metadata_t *md =
715*1c60b9acSAndroid Build Coastguard Worker lws_container_of(d, lws_sspc_metadata_t, list);
716*1c60b9acSAndroid Build Coastguard Worker
717*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&md->list);
718*1c60b9acSAndroid Build Coastguard Worker lws_free(md);
719*1c60b9acSAndroid Build Coastguard Worker
720*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(d, d1);
721*1c60b9acSAndroid Build Coastguard Worker }
722*1c60b9acSAndroid Build Coastguard Worker
723*1c60b9acSAndroid Build Coastguard Worker void
lws_sspc_destroy(lws_sspc_handle_t ** ph)724*1c60b9acSAndroid Build Coastguard Worker lws_sspc_destroy(lws_sspc_handle_t **ph)
725*1c60b9acSAndroid Build Coastguard Worker {
726*1c60b9acSAndroid Build Coastguard Worker lws_sspc_handle_t *h;
727*1c60b9acSAndroid Build Coastguard Worker
728*1c60b9acSAndroid Build Coastguard Worker if (!*ph)
729*1c60b9acSAndroid Build Coastguard Worker return;
730*1c60b9acSAndroid Build Coastguard Worker
731*1c60b9acSAndroid Build Coastguard Worker h = *ph;
732*1c60b9acSAndroid Build Coastguard Worker if (h == h->h_in_svc) {
733*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: illegal destroy, return LWSSSSRET_DESTROY_ME instead\n",
734*1c60b9acSAndroid Build Coastguard Worker __func__);
735*1c60b9acSAndroid Build Coastguard Worker assert(0);
736*1c60b9acSAndroid Build Coastguard Worker return;
737*1c60b9acSAndroid Build Coastguard Worker }
738*1c60b9acSAndroid Build Coastguard Worker
739*1c60b9acSAndroid Build Coastguard Worker lws_service_assert_loop_thread(h->context, 0);
740*1c60b9acSAndroid Build Coastguard Worker
741*1c60b9acSAndroid Build Coastguard Worker if (h->destroying)
742*1c60b9acSAndroid Build Coastguard Worker return;
743*1c60b9acSAndroid Build Coastguard Worker
744*1c60b9acSAndroid Build Coastguard Worker h->destroying = 1;
745*1c60b9acSAndroid Build Coastguard Worker
746*1c60b9acSAndroid Build Coastguard Worker /* if this caliper is still dangling at destroy, we failed */
747*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_METRICS)
748*1c60b9acSAndroid Build Coastguard Worker /*
749*1c60b9acSAndroid Build Coastguard Worker * If any hanging caliper measurement, dump it, and free any tags
750*1c60b9acSAndroid Build Coastguard Worker */
751*1c60b9acSAndroid Build Coastguard Worker lws_metrics_caliper_report_hist(h->cal_txn, (struct lws *)NULL);
752*1c60b9acSAndroid Build Coastguard Worker #endif
753*1c60b9acSAndroid Build Coastguard Worker if (h->ss_dangling_connected && h->ssi.state) {
754*1c60b9acSAndroid Build Coastguard Worker lws_sspc_event_helper(h, LWSSSCS_DISCONNECTED, 0);
755*1c60b9acSAndroid Build Coastguard Worker h->ss_dangling_connected = 0;
756*1c60b9acSAndroid Build Coastguard Worker }
757*1c60b9acSAndroid Build Coastguard Worker
758*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_FAULT_INJECTION)
759*1c60b9acSAndroid Build Coastguard Worker lws_fi_destroy(&h->fic);
760*1c60b9acSAndroid Build Coastguard Worker #endif
761*1c60b9acSAndroid Build Coastguard Worker
762*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&h->sul_retry);
763*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&h->client_list);
764*1c60b9acSAndroid Build Coastguard Worker
765*1c60b9acSAndroid Build Coastguard Worker if (h->dsh)
766*1c60b9acSAndroid Build Coastguard Worker lws_dsh_destroy(&h->dsh);
767*1c60b9acSAndroid Build Coastguard Worker if (h->cwsi) {
768*1c60b9acSAndroid Build Coastguard Worker lws_set_opaque_user_data(h->cwsi, NULL);
769*1c60b9acSAndroid Build Coastguard Worker lws_wsi_close(h->cwsi, LWS_TO_KILL_ASYNC);
770*1c60b9acSAndroid Build Coastguard Worker h->cwsi = NULL;
771*1c60b9acSAndroid Build Coastguard Worker }
772*1c60b9acSAndroid Build Coastguard Worker
773*1c60b9acSAndroid Build Coastguard Worker /* clean out any pending metadata changes that didn't make it */
774*1c60b9acSAndroid Build Coastguard Worker
775*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
776*1c60b9acSAndroid Build Coastguard Worker lws_dll2_get_head(&(*ph)->metadata_owner)) {
777*1c60b9acSAndroid Build Coastguard Worker lws_sspc_metadata_t *md =
778*1c60b9acSAndroid Build Coastguard Worker lws_container_of(d, lws_sspc_metadata_t, list);
779*1c60b9acSAndroid Build Coastguard Worker
780*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&md->list);
781*1c60b9acSAndroid Build Coastguard Worker lws_free(md);
782*1c60b9acSAndroid Build Coastguard Worker
783*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(d, d1);
784*1c60b9acSAndroid Build Coastguard Worker
785*1c60b9acSAndroid Build Coastguard Worker lws_sspc_rxmetadata_destroy(h);
786*1c60b9acSAndroid Build Coastguard Worker
787*1c60b9acSAndroid Build Coastguard Worker lws_sspc_event_helper(h, LWSSSCS_DESTROYING, 0);
788*1c60b9acSAndroid Build Coastguard Worker *ph = NULL;
789*1c60b9acSAndroid Build Coastguard Worker
790*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&h->sul_retry);
791*1c60b9acSAndroid Build Coastguard Worker
792*1c60b9acSAndroid Build Coastguard Worker
793*1c60b9acSAndroid Build Coastguard Worker /* confirm no sul left scheduled in handle or user allocation object */
794*1c60b9acSAndroid Build Coastguard Worker lws_sul_debug_zombies(h->context, h, sizeof(*h) + h->ssi.user_alloc,
795*1c60b9acSAndroid Build Coastguard Worker __func__);
796*1c60b9acSAndroid Build Coastguard Worker
797*1c60b9acSAndroid Build Coastguard Worker __lws_lc_untag(h->context, &h->lc);
798*1c60b9acSAndroid Build Coastguard Worker
799*1c60b9acSAndroid Build Coastguard Worker free(h);
800*1c60b9acSAndroid Build Coastguard Worker }
801*1c60b9acSAndroid Build Coastguard Worker
802*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_return_t
lws_sspc_request_tx(lws_sspc_handle_t * h)803*1c60b9acSAndroid Build Coastguard Worker lws_sspc_request_tx(lws_sspc_handle_t *h)
804*1c60b9acSAndroid Build Coastguard Worker {
805*1c60b9acSAndroid Build Coastguard Worker if (!h || !h->cwsi)
806*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
807*1c60b9acSAndroid Build Coastguard Worker
808*1c60b9acSAndroid Build Coastguard Worker lws_service_assert_loop_thread(h->context, 0);
809*1c60b9acSAndroid Build Coastguard Worker
810*1c60b9acSAndroid Build Coastguard Worker if (!h->us_earliest_write_req)
811*1c60b9acSAndroid Build Coastguard Worker h->us_earliest_write_req = lws_now_usecs();
812*1c60b9acSAndroid Build Coastguard Worker
813*1c60b9acSAndroid Build Coastguard Worker if (h->state == LPCSCLI_LOCAL_CONNECTED &&
814*1c60b9acSAndroid Build Coastguard Worker h->conn_req_state == LWSSSPC_ONW_NONE)
815*1c60b9acSAndroid Build Coastguard Worker h->conn_req_state = LWSSSPC_ONW_REQ;
816*1c60b9acSAndroid Build Coastguard Worker
817*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(h->cwsi);
818*1c60b9acSAndroid Build Coastguard Worker
819*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
820*1c60b9acSAndroid Build Coastguard Worker }
821*1c60b9acSAndroid Build Coastguard Worker
822*1c60b9acSAndroid Build Coastguard Worker /*
823*1c60b9acSAndroid Build Coastguard Worker * Currently we fulfil the writeable part locally by just enabling POLLOUT on
824*1c60b9acSAndroid Build Coastguard Worker * the UDS link, without serialization footprint, which is reasonable as far as
825*1c60b9acSAndroid Build Coastguard Worker * it goes.
826*1c60b9acSAndroid Build Coastguard Worker *
827*1c60b9acSAndroid Build Coastguard Worker * But for the ..._len() variant, the expected payload length hint we are being
828*1c60b9acSAndroid Build Coastguard Worker * told is something that must be serialized to the onward peer, since either
829*1c60b9acSAndroid Build Coastguard Worker * that guy or someone upstream of him is the guy who will compose the framing
830*1c60b9acSAndroid Build Coastguard Worker * with it that actually goes out.
831*1c60b9acSAndroid Build Coastguard Worker *
832*1c60b9acSAndroid Build Coastguard Worker * This information is needed at the upstream guy before we have sent any
833*1c60b9acSAndroid Build Coastguard Worker * payload, eg, for http POST, he has to prepare the content-length in the
834*1c60b9acSAndroid Build Coastguard Worker * headers, before any payload. So we have to issue a serialization of the
835*1c60b9acSAndroid Build Coastguard Worker * length at this point.
836*1c60b9acSAndroid Build Coastguard Worker */
837*1c60b9acSAndroid Build Coastguard Worker
838*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_return_t
lws_sspc_request_tx_len(lws_sspc_handle_t * h,unsigned long len)839*1c60b9acSAndroid Build Coastguard Worker lws_sspc_request_tx_len(lws_sspc_handle_t *h, unsigned long len)
840*1c60b9acSAndroid Build Coastguard Worker {
841*1c60b9acSAndroid Build Coastguard Worker /*
842*1c60b9acSAndroid Build Coastguard Worker * for client conns, they cannot even complete creation of the handle
843*1c60b9acSAndroid Build Coastguard Worker * without the onwared connection to the proxy, it's not legal to start
844*1c60b9acSAndroid Build Coastguard Worker * using it until it's operation and has the onward connection (and the
845*1c60b9acSAndroid Build Coastguard Worker * link has called CREATED state)
846*1c60b9acSAndroid Build Coastguard Worker */
847*1c60b9acSAndroid Build Coastguard Worker
848*1c60b9acSAndroid Build Coastguard Worker if (!h)
849*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
850*1c60b9acSAndroid Build Coastguard Worker
851*1c60b9acSAndroid Build Coastguard Worker lws_service_assert_loop_thread(h->context, 0);
852*1c60b9acSAndroid Build Coastguard Worker
853*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_notice(h, "setting writeable_len %u", (unsigned int)len);
854*1c60b9acSAndroid Build Coastguard Worker h->writeable_len = len;
855*1c60b9acSAndroid Build Coastguard Worker h->pending_writeable_len = 1;
856*1c60b9acSAndroid Build Coastguard Worker
857*1c60b9acSAndroid Build Coastguard Worker if (!h->us_earliest_write_req)
858*1c60b9acSAndroid Build Coastguard Worker h->us_earliest_write_req = lws_now_usecs();
859*1c60b9acSAndroid Build Coastguard Worker
860*1c60b9acSAndroid Build Coastguard Worker if (h->state == LPCSCLI_LOCAL_CONNECTED &&
861*1c60b9acSAndroid Build Coastguard Worker h->conn_req_state == LWSSSPC_ONW_NONE)
862*1c60b9acSAndroid Build Coastguard Worker h->conn_req_state = LWSSSPC_ONW_REQ;
863*1c60b9acSAndroid Build Coastguard Worker
864*1c60b9acSAndroid Build Coastguard Worker /*
865*1c60b9acSAndroid Build Coastguard Worker * We're going to use this up with serializing h->writeable_len... that
866*1c60b9acSAndroid Build Coastguard Worker * will request again.
867*1c60b9acSAndroid Build Coastguard Worker */
868*1c60b9acSAndroid Build Coastguard Worker
869*1c60b9acSAndroid Build Coastguard Worker if (h->cwsi)
870*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(h->cwsi);
871*1c60b9acSAndroid Build Coastguard Worker
872*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
873*1c60b9acSAndroid Build Coastguard Worker }
874*1c60b9acSAndroid Build Coastguard Worker
875*1c60b9acSAndroid Build Coastguard Worker int
lws_sspc_client_connect(lws_sspc_handle_t * h)876*1c60b9acSAndroid Build Coastguard Worker lws_sspc_client_connect(lws_sspc_handle_t *h)
877*1c60b9acSAndroid Build Coastguard Worker {
878*1c60b9acSAndroid Build Coastguard Worker if (!h || h->state == LPCSCLI_OPERATIONAL)
879*1c60b9acSAndroid Build Coastguard Worker return 0;
880*1c60b9acSAndroid Build Coastguard Worker
881*1c60b9acSAndroid Build Coastguard Worker lws_service_assert_loop_thread(h->context, 0);
882*1c60b9acSAndroid Build Coastguard Worker
883*1c60b9acSAndroid Build Coastguard Worker assert(h->state == LPCSCLI_LOCAL_CONNECTED);
884*1c60b9acSAndroid Build Coastguard Worker if (h->state == LPCSCLI_LOCAL_CONNECTED &&
885*1c60b9acSAndroid Build Coastguard Worker h->conn_req_state == LWSSSPC_ONW_NONE)
886*1c60b9acSAndroid Build Coastguard Worker h->conn_req_state = LWSSSPC_ONW_REQ;
887*1c60b9acSAndroid Build Coastguard Worker if (h->cwsi)
888*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(h->cwsi);
889*1c60b9acSAndroid Build Coastguard Worker
890*1c60b9acSAndroid Build Coastguard Worker return 0;
891*1c60b9acSAndroid Build Coastguard Worker }
892*1c60b9acSAndroid Build Coastguard Worker
893*1c60b9acSAndroid Build Coastguard Worker struct lws_context *
lws_sspc_get_context(struct lws_sspc_handle * h)894*1c60b9acSAndroid Build Coastguard Worker lws_sspc_get_context(struct lws_sspc_handle *h)
895*1c60b9acSAndroid Build Coastguard Worker {
896*1c60b9acSAndroid Build Coastguard Worker return h->context;
897*1c60b9acSAndroid Build Coastguard Worker }
898*1c60b9acSAndroid Build Coastguard Worker
899*1c60b9acSAndroid Build Coastguard Worker const char *
lws_sspc_rideshare(struct lws_sspc_handle * h)900*1c60b9acSAndroid Build Coastguard Worker lws_sspc_rideshare(struct lws_sspc_handle *h)
901*1c60b9acSAndroid Build Coastguard Worker {
902*1c60b9acSAndroid Build Coastguard Worker /*
903*1c60b9acSAndroid Build Coastguard Worker * ...the serialized RX rideshare name if any...
904*1c60b9acSAndroid Build Coastguard Worker */
905*1c60b9acSAndroid Build Coastguard Worker
906*1c60b9acSAndroid Build Coastguard Worker if (h->parser.rideshare[0]) {
907*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "parser %s", h->parser.rideshare);
908*1c60b9acSAndroid Build Coastguard Worker
909*1c60b9acSAndroid Build Coastguard Worker return h->parser.rideshare;
910*1c60b9acSAndroid Build Coastguard Worker }
911*1c60b9acSAndroid Build Coastguard Worker
912*1c60b9acSAndroid Build Coastguard Worker /*
913*1c60b9acSAndroid Build Coastguard Worker * The tx rideshare index
914*1c60b9acSAndroid Build Coastguard Worker */
915*1c60b9acSAndroid Build Coastguard Worker
916*1c60b9acSAndroid Build Coastguard Worker if (h->rideshare_list[0]) {
917*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "tx list %s",
918*1c60b9acSAndroid Build Coastguard Worker &h->rideshare_list[h->rideshare_ofs[h->rsidx]]);
919*1c60b9acSAndroid Build Coastguard Worker return &h->rideshare_list[h->rideshare_ofs[h->rsidx]];
920*1c60b9acSAndroid Build Coastguard Worker }
921*1c60b9acSAndroid Build Coastguard Worker
922*1c60b9acSAndroid Build Coastguard Worker /*
923*1c60b9acSAndroid Build Coastguard Worker * ... otherwise default to our stream type name
924*1c60b9acSAndroid Build Coastguard Worker */
925*1c60b9acSAndroid Build Coastguard Worker
926*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "def %s\n", h->ssi.streamtype);
927*1c60b9acSAndroid Build Coastguard Worker
928*1c60b9acSAndroid Build Coastguard Worker return h->ssi.streamtype;
929*1c60b9acSAndroid Build Coastguard Worker }
930*1c60b9acSAndroid Build Coastguard Worker
931*1c60b9acSAndroid Build Coastguard Worker static int
_lws_sspc_set_metadata(struct lws_sspc_handle * h,const char * name,const void * value,size_t len,int tx_cr_adjust)932*1c60b9acSAndroid Build Coastguard Worker _lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name,
933*1c60b9acSAndroid Build Coastguard Worker const void *value, size_t len, int tx_cr_adjust)
934*1c60b9acSAndroid Build Coastguard Worker {
935*1c60b9acSAndroid Build Coastguard Worker lws_sspc_metadata_t *md;
936*1c60b9acSAndroid Build Coastguard Worker
937*1c60b9acSAndroid Build Coastguard Worker lws_service_assert_loop_thread(h->context, 0);
938*1c60b9acSAndroid Build Coastguard Worker
939*1c60b9acSAndroid Build Coastguard Worker /*
940*1c60b9acSAndroid Build Coastguard Worker * Are we replacing a pending metadata of the same name? It's not
941*1c60b9acSAndroid Build Coastguard Worker * efficient to do this but user code can do what it likes... let's
942*1c60b9acSAndroid Build Coastguard Worker * optimize away the old one.
943*1c60b9acSAndroid Build Coastguard Worker *
944*1c60b9acSAndroid Build Coastguard Worker * Tx credit adjust always has name ""
945*1c60b9acSAndroid Build Coastguard Worker */
946*1c60b9acSAndroid Build Coastguard Worker
947*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
948*1c60b9acSAndroid Build Coastguard Worker lws_dll2_get_head(&h->metadata_owner)) {
949*1c60b9acSAndroid Build Coastguard Worker md = lws_container_of(d, lws_sspc_metadata_t, list);
950*1c60b9acSAndroid Build Coastguard Worker
951*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(name, md->name)) {
952*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&md->list);
953*1c60b9acSAndroid Build Coastguard Worker lws_free(md);
954*1c60b9acSAndroid Build Coastguard Worker break;
955*1c60b9acSAndroid Build Coastguard Worker }
956*1c60b9acSAndroid Build Coastguard Worker
957*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(d, d1);
958*1c60b9acSAndroid Build Coastguard Worker
959*1c60b9acSAndroid Build Coastguard Worker /*
960*1c60b9acSAndroid Build Coastguard Worker * We have to stash the metadata and pass it to the proxy
961*1c60b9acSAndroid Build Coastguard Worker */
962*1c60b9acSAndroid Build Coastguard Worker
963*1c60b9acSAndroid Build Coastguard Worker if (lws_fi(&h->fic, "sspc_fail_metadata_set"))
964*1c60b9acSAndroid Build Coastguard Worker md = NULL;
965*1c60b9acSAndroid Build Coastguard Worker else
966*1c60b9acSAndroid Build Coastguard Worker md = lws_malloc(sizeof(*md) + len, "set metadata");
967*1c60b9acSAndroid Build Coastguard Worker if (!md) {
968*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_err(h, "OOM");
969*1c60b9acSAndroid Build Coastguard Worker
970*1c60b9acSAndroid Build Coastguard Worker return 1;
971*1c60b9acSAndroid Build Coastguard Worker }
972*1c60b9acSAndroid Build Coastguard Worker
973*1c60b9acSAndroid Build Coastguard Worker memset(md, 0, sizeof(*md));
974*1c60b9acSAndroid Build Coastguard Worker
975*1c60b9acSAndroid Build Coastguard Worker md->tx_cr_adjust = tx_cr_adjust;
976*1c60b9acSAndroid Build Coastguard Worker h->txc.peer_tx_cr_est += tx_cr_adjust;
977*1c60b9acSAndroid Build Coastguard Worker
978*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(md->name, name, sizeof(md->name));
979*1c60b9acSAndroid Build Coastguard Worker md->len = len;
980*1c60b9acSAndroid Build Coastguard Worker if (len)
981*1c60b9acSAndroid Build Coastguard Worker memcpy(&md[1], value, len);
982*1c60b9acSAndroid Build Coastguard Worker
983*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&md->list, &h->metadata_owner);
984*1c60b9acSAndroid Build Coastguard Worker
985*1c60b9acSAndroid Build Coastguard Worker if (len) {
986*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "set metadata %s", name);
987*1c60b9acSAndroid Build Coastguard Worker lwsl_hexdump_sspc_info(h, value, len);
988*1c60b9acSAndroid Build Coastguard Worker } else
989*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_info(h, "serializing tx cr adj %d",
990*1c60b9acSAndroid Build Coastguard Worker (int)tx_cr_adjust);
991*1c60b9acSAndroid Build Coastguard Worker
992*1c60b9acSAndroid Build Coastguard Worker if (h->cwsi)
993*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(h->cwsi);
994*1c60b9acSAndroid Build Coastguard Worker
995*1c60b9acSAndroid Build Coastguard Worker return 0;
996*1c60b9acSAndroid Build Coastguard Worker }
997*1c60b9acSAndroid Build Coastguard Worker
998*1c60b9acSAndroid Build Coastguard Worker int
lws_sspc_set_metadata(struct lws_sspc_handle * h,const char * name,const void * value,size_t len)999*1c60b9acSAndroid Build Coastguard Worker lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name,
1000*1c60b9acSAndroid Build Coastguard Worker const void *value, size_t len)
1001*1c60b9acSAndroid Build Coastguard Worker {
1002*1c60b9acSAndroid Build Coastguard Worker return _lws_sspc_set_metadata(h, name, value, len, 0);
1003*1c60b9acSAndroid Build Coastguard Worker }
1004*1c60b9acSAndroid Build Coastguard Worker
1005*1c60b9acSAndroid Build Coastguard Worker int
lws_sspc_get_metadata(struct lws_sspc_handle * h,const char * name,const void ** value,size_t * len)1006*1c60b9acSAndroid Build Coastguard Worker lws_sspc_get_metadata(struct lws_sspc_handle *h, const char *name,
1007*1c60b9acSAndroid Build Coastguard Worker const void **value, size_t *len)
1008*1c60b9acSAndroid Build Coastguard Worker {
1009*1c60b9acSAndroid Build Coastguard Worker lws_sspc_metadata_t *md;
1010*1c60b9acSAndroid Build Coastguard Worker
1011*1c60b9acSAndroid Build Coastguard Worker /*
1012*1c60b9acSAndroid Build Coastguard Worker * client side does not have access to policy
1013*1c60b9acSAndroid Build Coastguard Worker * and any metadata are new to it each time,
1014*1c60b9acSAndroid Build Coastguard Worker * we allocate them, removing any existing with
1015*1c60b9acSAndroid Build Coastguard Worker * the same name first
1016*1c60b9acSAndroid Build Coastguard Worker */
1017*1c60b9acSAndroid Build Coastguard Worker
1018*1c60b9acSAndroid Build Coastguard Worker lws_service_assert_loop_thread(h->context, 0);
1019*1c60b9acSAndroid Build Coastguard Worker
1020*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
1021*1c60b9acSAndroid Build Coastguard Worker lws_dll2_get_head(&h->metadata_owner_rx)) {
1022*1c60b9acSAndroid Build Coastguard Worker md = lws_container_of(d,
1023*1c60b9acSAndroid Build Coastguard Worker lws_sspc_metadata_t, list);
1024*1c60b9acSAndroid Build Coastguard Worker
1025*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(md->name, name)) {
1026*1c60b9acSAndroid Build Coastguard Worker *len = md->len;
1027*1c60b9acSAndroid Build Coastguard Worker *value = &md[1];
1028*1c60b9acSAndroid Build Coastguard Worker
1029*1c60b9acSAndroid Build Coastguard Worker return 0;
1030*1c60b9acSAndroid Build Coastguard Worker }
1031*1c60b9acSAndroid Build Coastguard Worker
1032*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(d, d1);
1033*1c60b9acSAndroid Build Coastguard Worker
1034*1c60b9acSAndroid Build Coastguard Worker return 1;
1035*1c60b9acSAndroid Build Coastguard Worker }
1036*1c60b9acSAndroid Build Coastguard Worker
1037*1c60b9acSAndroid Build Coastguard Worker int
lws_sspc_add_peer_tx_credit(struct lws_sspc_handle * h,int32_t bump)1038*1c60b9acSAndroid Build Coastguard Worker lws_sspc_add_peer_tx_credit(struct lws_sspc_handle *h, int32_t bump)
1039*1c60b9acSAndroid Build Coastguard Worker {
1040*1c60b9acSAndroid Build Coastguard Worker lws_service_assert_loop_thread(h->context, 0);
1041*1c60b9acSAndroid Build Coastguard Worker lwsl_sspc_notice(h, "%d\n", bump);
1042*1c60b9acSAndroid Build Coastguard Worker return _lws_sspc_set_metadata(h, "", NULL, 0, (int)bump);
1043*1c60b9acSAndroid Build Coastguard Worker }
1044*1c60b9acSAndroid Build Coastguard Worker
1045*1c60b9acSAndroid Build Coastguard Worker int
lws_sspc_get_est_peer_tx_credit(struct lws_sspc_handle * h)1046*1c60b9acSAndroid Build Coastguard Worker lws_sspc_get_est_peer_tx_credit(struct lws_sspc_handle *h)
1047*1c60b9acSAndroid Build Coastguard Worker {
1048*1c60b9acSAndroid Build Coastguard Worker lws_service_assert_loop_thread(h->context, 0);
1049*1c60b9acSAndroid Build Coastguard Worker return h->txc.peer_tx_cr_est;
1050*1c60b9acSAndroid Build Coastguard Worker }
1051*1c60b9acSAndroid Build Coastguard Worker
1052*1c60b9acSAndroid Build Coastguard Worker void
lws_sspc_start_timeout(struct lws_sspc_handle * h,unsigned int timeout_ms)1053*1c60b9acSAndroid Build Coastguard Worker lws_sspc_start_timeout(struct lws_sspc_handle *h, unsigned int timeout_ms)
1054*1c60b9acSAndroid Build Coastguard Worker {
1055*1c60b9acSAndroid Build Coastguard Worker lws_service_assert_loop_thread(h->context, 0);
1056*1c60b9acSAndroid Build Coastguard Worker if (!h->cwsi)
1057*1c60b9acSAndroid Build Coastguard Worker /* we can't fulfil it */
1058*1c60b9acSAndroid Build Coastguard Worker return;
1059*1c60b9acSAndroid Build Coastguard Worker h->timeout_ms = (uint32_t)timeout_ms;
1060*1c60b9acSAndroid Build Coastguard Worker h->pending_timeout_update = 1;
1061*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(h->cwsi);
1062*1c60b9acSAndroid Build Coastguard Worker }
1063*1c60b9acSAndroid Build Coastguard Worker
1064*1c60b9acSAndroid Build Coastguard Worker void
lws_sspc_cancel_timeout(struct lws_sspc_handle * h)1065*1c60b9acSAndroid Build Coastguard Worker lws_sspc_cancel_timeout(struct lws_sspc_handle *h)
1066*1c60b9acSAndroid Build Coastguard Worker {
1067*1c60b9acSAndroid Build Coastguard Worker lws_sspc_start_timeout(h, (unsigned int)-1);
1068*1c60b9acSAndroid Build Coastguard Worker }
1069*1c60b9acSAndroid Build Coastguard Worker
1070*1c60b9acSAndroid Build Coastguard Worker void *
lws_sspc_to_user_object(struct lws_sspc_handle * h)1071*1c60b9acSAndroid Build Coastguard Worker lws_sspc_to_user_object(struct lws_sspc_handle *h)
1072*1c60b9acSAndroid Build Coastguard Worker {
1073*1c60b9acSAndroid Build Coastguard Worker return (void *)&h[1];
1074*1c60b9acSAndroid Build Coastguard Worker }
1075*1c60b9acSAndroid Build Coastguard Worker
1076*1c60b9acSAndroid Build Coastguard Worker void
lws_sspc_change_handlers(struct lws_sspc_handle * h,lws_ss_state_return_t (* rx)(void * userobj,const uint8_t * buf,size_t len,int flags),lws_ss_state_return_t (* tx)(void * userobj,lws_ss_tx_ordinal_t ord,uint8_t * buf,size_t * len,int * flags),lws_ss_state_return_t (* state)(void * userobj,void * h_src,lws_ss_constate_t state,lws_ss_tx_ordinal_t ack))1077*1c60b9acSAndroid Build Coastguard Worker lws_sspc_change_handlers(struct lws_sspc_handle *h,
1078*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_return_t (*rx)(void *userobj, const uint8_t *buf, size_t len, int flags),
1079*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_return_t (*tx)(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf,
1080*1c60b9acSAndroid Build Coastguard Worker size_t *len, int *flags),
1081*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_return_t (*state)(void *userobj, void *h_src /* ss handle type */,
1082*1c60b9acSAndroid Build Coastguard Worker lws_ss_constate_t state, lws_ss_tx_ordinal_t ack))
1083*1c60b9acSAndroid Build Coastguard Worker {
1084*1c60b9acSAndroid Build Coastguard Worker if (rx)
1085*1c60b9acSAndroid Build Coastguard Worker h->ssi.rx = rx;
1086*1c60b9acSAndroid Build Coastguard Worker if (tx)
1087*1c60b9acSAndroid Build Coastguard Worker h->ssi.tx = tx;
1088*1c60b9acSAndroid Build Coastguard Worker if (state)
1089*1c60b9acSAndroid Build Coastguard Worker h->ssi.state = state;
1090*1c60b9acSAndroid Build Coastguard Worker }
1091*1c60b9acSAndroid Build Coastguard Worker
1092*1c60b9acSAndroid Build Coastguard Worker const char *
lws_sspc_tag(struct lws_sspc_handle * h)1093*1c60b9acSAndroid Build Coastguard Worker lws_sspc_tag(struct lws_sspc_handle *h)
1094*1c60b9acSAndroid Build Coastguard Worker {
1095*1c60b9acSAndroid Build Coastguard Worker if (!h)
1096*1c60b9acSAndroid Build Coastguard Worker return "[null sspc]";
1097*1c60b9acSAndroid Build Coastguard Worker return lws_lc_tag(&h->lc);
1098*1c60b9acSAndroid Build Coastguard Worker }
1099*1c60b9acSAndroid Build Coastguard Worker
1100*1c60b9acSAndroid Build Coastguard Worker int
lws_sspc_cancel_notify_dll(struct lws_dll2 * d,void * user)1101*1c60b9acSAndroid Build Coastguard Worker lws_sspc_cancel_notify_dll(struct lws_dll2 *d, void *user)
1102*1c60b9acSAndroid Build Coastguard Worker {
1103*1c60b9acSAndroid Build Coastguard Worker lws_sspc_handle_t *h = lws_container_of(d, lws_sspc_handle_t, client_list);
1104*1c60b9acSAndroid Build Coastguard Worker
1105*1c60b9acSAndroid Build Coastguard Worker lws_sspc_event_helper(h, LWSSSCS_EVENT_WAIT_CANCELLED, 0);
1106*1c60b9acSAndroid Build Coastguard Worker
1107*1c60b9acSAndroid Build Coastguard Worker return 0;
1108*1c60b9acSAndroid Build Coastguard Worker }
1109*1c60b9acSAndroid Build Coastguard Worker
1110