1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * lws-minimal-secure-streams-smd
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Written in 2010-2021 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 demonstrates a minimal http client using secure streams to access the
11*1c60b9acSAndroid Build Coastguard Worker * SMD api. This file is only built when LWS_SS_USE_SSPC defined.
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * This is an alternative test implementation selected by --multi at runtime,
14*1c60b9acSAndroid Build Coastguard Worker * it's in its own file to stop muddying up the main test sources. It's only
15*1c60b9acSAndroid Build Coastguard Worker * available when built with SSPC / produces -client executable.
16*1c60b9acSAndroid Build Coastguard Worker *
17*1c60b9acSAndroid Build Coastguard Worker * We will fork several times, the original thread and the forks hook up to
18*1c60b9acSAndroid Build Coastguard Worker * the proxy with smd SS, each fork waits a second for everyone to have joined,
19*1c60b9acSAndroid Build Coastguard Worker * and then each fork (NOT the original process) sends a bunch of user messages
20*1c60b9acSAndroid Build Coastguard Worker * that all the forks should receive, having been distributed by SMD and the
21*1c60b9acSAndroid Build Coastguard Worker * ss proxy.
22*1c60b9acSAndroid Build Coastguard Worker *
23*1c60b9acSAndroid Build Coastguard Worker * The participants check they received all the messages expected from everyone
24*1c60b9acSAndroid Build Coastguard Worker * and then send a final message indicating success and exits. The original
25*1c60b9acSAndroid Build Coastguard Worker * fork is watching for these to arrive before the timeout, if so it's a PASS.
26*1c60b9acSAndroid Build Coastguard Worker */
27*1c60b9acSAndroid Build Coastguard Worker
28*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
29*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
30*1c60b9acSAndroid Build Coastguard Worker #include <signal.h>
31*1c60b9acSAndroid Build Coastguard Worker
32*1c60b9acSAndroid Build Coastguard Worker static int bad = 1, interrupted;
33*1c60b9acSAndroid Build Coastguard Worker
34*1c60b9acSAndroid Build Coastguard Worker /* number of forks */
35*1c60b9acSAndroid Build Coastguard Worker #define FORKS 4
36*1c60b9acSAndroid Build Coastguard Worker /* number of messages each will send, eg, 4 forks 64 message == 256 messages */
37*1c60b9acSAndroid Build Coastguard Worker #define MSGCOUNT 64
38*1c60b9acSAndroid Build Coastguard Worker
39*1c60b9acSAndroid Build Coastguard Worker typedef struct myss {
40*1c60b9acSAndroid Build Coastguard Worker struct lws_ss_handle *ss;
41*1c60b9acSAndroid Build Coastguard Worker void *opaque_data;
42*1c60b9acSAndroid Build Coastguard Worker /* ... application specific state ... */
43*1c60b9acSAndroid Build Coastguard Worker uint64_t seen_mask[FORKS];
44*1c60b9acSAndroid Build Coastguard Worker int seen_msgs[FORKS];
45*1c60b9acSAndroid Build Coastguard Worker lws_sorted_usec_list_t sul;
46*1c60b9acSAndroid Build Coastguard Worker int count;
47*1c60b9acSAndroid Build Coastguard Worker char seen_all;
48*1c60b9acSAndroid Build Coastguard Worker char send_seen_all;
49*1c60b9acSAndroid Build Coastguard Worker char starting;
50*1c60b9acSAndroid Build Coastguard Worker } myss_t;
51*1c60b9acSAndroid Build Coastguard Worker
52*1c60b9acSAndroid Build Coastguard Worker
53*1c60b9acSAndroid Build Coastguard Worker /* secure streams payload interface */
54*1c60b9acSAndroid Build Coastguard Worker
55*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
multi_myss_rx(void * userobj,const uint8_t * buf,size_t len,int flags)56*1c60b9acSAndroid Build Coastguard Worker multi_myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
57*1c60b9acSAndroid Build Coastguard Worker {
58*1c60b9acSAndroid Build Coastguard Worker myss_t *m = (myss_t *)userobj;
59*1c60b9acSAndroid Build Coastguard Worker const char *p;
60*1c60b9acSAndroid Build Coastguard Worker int fk, t, n;
61*1c60b9acSAndroid Build Coastguard Worker size_t al;
62*1c60b9acSAndroid Build Coastguard Worker
63*1c60b9acSAndroid Build Coastguard Worker /* ignore our and other forks announcing their result */
64*1c60b9acSAndroid Build Coastguard Worker
65*1c60b9acSAndroid Build Coastguard Worker if (lws_json_simple_find((const char *)buf, len, "\"seen_all\":", &al))
66*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
67*1c60b9acSAndroid Build Coastguard Worker
68*1c60b9acSAndroid Build Coastguard Worker /*
69*1c60b9acSAndroid Build Coastguard Worker * otherwise once we saw the expected messages, any other messages
70*1c60b9acSAndroid Build Coastguard Worker * coming in this class are wrong
71*1c60b9acSAndroid Build Coastguard Worker */
72*1c60b9acSAndroid Build Coastguard Worker
73*1c60b9acSAndroid Build Coastguard Worker if (m->seen_all) {
74*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: unexpected extra messages\n", __func__);
75*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
76*1c60b9acSAndroid Build Coastguard Worker }
77*1c60b9acSAndroid Build Coastguard Worker
78*1c60b9acSAndroid Build Coastguard Worker p = lws_json_simple_find((const char *)buf, len, "\"fork\":", &al);
79*1c60b9acSAndroid Build Coastguard Worker if (!p)
80*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
81*1c60b9acSAndroid Build Coastguard Worker fk = atoi(p);
82*1c60b9acSAndroid Build Coastguard Worker if (fk < 1 || fk > FORKS)
83*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
84*1c60b9acSAndroid Build Coastguard Worker
85*1c60b9acSAndroid Build Coastguard Worker p = lws_json_simple_find((const char *)buf, len, "\"test\":", &al);
86*1c60b9acSAndroid Build Coastguard Worker if (!p)
87*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
88*1c60b9acSAndroid Build Coastguard Worker t = atoi(p);
89*1c60b9acSAndroid Build Coastguard Worker
90*1c60b9acSAndroid Build Coastguard Worker if (t < 0 || t >= MSGCOUNT)
91*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
92*1c60b9acSAndroid Build Coastguard Worker
93*1c60b9acSAndroid Build Coastguard Worker m->seen_mask[fk - 1] |= 1ull << t;
94*1c60b9acSAndroid Build Coastguard Worker m->seen_msgs[fk - 1]++; /* keep an eye on dupes */
95*1c60b9acSAndroid Build Coastguard Worker
96*1c60b9acSAndroid Build Coastguard Worker /* Have we seen a full set of messages from everyone? */
97*1c60b9acSAndroid Build Coastguard Worker
98*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < FORKS; n++) {
99*1c60b9acSAndroid Build Coastguard Worker if (m->seen_msgs[n] != (int)MSGCOUNT)
100*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
101*1c60b9acSAndroid Build Coastguard Worker if (m->seen_mask[n] != 0xffffffffffffffffull)
102*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
103*1c60b9acSAndroid Build Coastguard Worker }
104*1c60b9acSAndroid Build Coastguard Worker
105*1c60b9acSAndroid Build Coastguard Worker /*
106*1c60b9acSAndroid Build Coastguard Worker * Oh... so we have finished collecting messages
107*1c60b9acSAndroid Build Coastguard Worker */
108*1c60b9acSAndroid Build Coastguard Worker
109*1c60b9acSAndroid Build Coastguard Worker lwsl_user("%s: test thread %d: %s received all messages\n", __func__,
110*1c60b9acSAndroid Build Coastguard Worker (int)(intptr_t)lws_context_user(lws_ss_get_context(m->ss)),
111*1c60b9acSAndroid Build Coastguard Worker lws_ss_tag(m->ss));
112*1c60b9acSAndroid Build Coastguard Worker m->seen_all = m->send_seen_all = 1;
113*1c60b9acSAndroid Build Coastguard Worker
114*1c60b9acSAndroid Build Coastguard Worker /*
115*1c60b9acSAndroid Build Coastguard Worker * Prepare to inform the original process we saw everything
116*1c60b9acSAndroid Build Coastguard Worker * from everyone OK
117*1c60b9acSAndroid Build Coastguard Worker */
118*1c60b9acSAndroid Build Coastguard Worker
119*1c60b9acSAndroid Build Coastguard Worker lws_ss_request_tx(m->ss);
120*1c60b9acSAndroid Build Coastguard Worker
121*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
122*1c60b9acSAndroid Build Coastguard Worker }
123*1c60b9acSAndroid Build Coastguard Worker
124*1c60b9acSAndroid Build Coastguard Worker static void
sul_multi_tx_periodic_cb(lws_sorted_usec_list_t * sul)125*1c60b9acSAndroid Build Coastguard Worker sul_multi_tx_periodic_cb(lws_sorted_usec_list_t *sul)
126*1c60b9acSAndroid Build Coastguard Worker {
127*1c60b9acSAndroid Build Coastguard Worker myss_t *m = lws_container_of(sul, myss_t, sul);
128*1c60b9acSAndroid Build Coastguard Worker
129*1c60b9acSAndroid Build Coastguard Worker if (!m->send_seen_all && m->seen_all) {
130*1c60b9acSAndroid Build Coastguard Worker lws_ss_destroy(&m->ss);
131*1c60b9acSAndroid Build Coastguard Worker return;
132*1c60b9acSAndroid Build Coastguard Worker }
133*1c60b9acSAndroid Build Coastguard Worker
134*1c60b9acSAndroid Build Coastguard Worker m->starting = 1;
135*1c60b9acSAndroid Build Coastguard Worker if (m->count < MSGCOUNT || m->send_seen_all)
136*1c60b9acSAndroid Build Coastguard Worker lws_ss_request_tx(m->ss);
137*1c60b9acSAndroid Build Coastguard Worker }
138*1c60b9acSAndroid Build Coastguard Worker
139*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
multi_myss_tx(void * userobj,lws_ss_tx_ordinal_t ord,uint8_t * buf,size_t * len,int * flags)140*1c60b9acSAndroid Build Coastguard Worker multi_myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len,
141*1c60b9acSAndroid Build Coastguard Worker int *flags)
142*1c60b9acSAndroid Build Coastguard Worker {
143*1c60b9acSAndroid Build Coastguard Worker myss_t *m = (myss_t *)userobj;
144*1c60b9acSAndroid Build Coastguard Worker
145*1c60b9acSAndroid Build Coastguard Worker /*
146*1c60b9acSAndroid Build Coastguard Worker * We want to send exactly MSGCOUNT user class smd messages
147*1c60b9acSAndroid Build Coastguard Worker */
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker if (!m->starting || (m->count == MSGCOUNT && !m->send_seen_all))
150*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_TX_DONT_SEND;
151*1c60b9acSAndroid Build Coastguard Worker
152*1c60b9acSAndroid Build Coastguard Worker // lwsl_notice("%s: sending SS smd\n", __func__);
153*1c60b9acSAndroid Build Coastguard Worker
154*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu64be(buf, 1 << LWSSMDCL_USER_BASE_BITNUM);
155*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu64be(buf + 8, 0); /* valgrind notices uninitialized if left */
156*1c60b9acSAndroid Build Coastguard Worker
157*1c60b9acSAndroid Build Coastguard Worker if (m->send_seen_all) {
158*1c60b9acSAndroid Build Coastguard Worker *len = LWS_SMD_SS_RX_HEADER_LEN + (unsigned int)
159*1c60b9acSAndroid Build Coastguard Worker lws_snprintf((char *)buf + LWS_SMD_SS_RX_HEADER_LEN, *len,
160*1c60b9acSAndroid Build Coastguard Worker "{\"class\":\"user\",\"fork\": %d,\"seen_all\":true}",
161*1c60b9acSAndroid Build Coastguard Worker (int)(intptr_t)lws_context_user(lws_ss_get_context(m->ss)));
162*1c60b9acSAndroid Build Coastguard Worker
163*1c60b9acSAndroid Build Coastguard Worker m->send_seen_all = 0;
164*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: test thread %d: sent summary message\n", __func__,
165*1c60b9acSAndroid Build Coastguard Worker (int)(intptr_t)lws_context_user(lws_ss_get_context(m->ss)));
166*1c60b9acSAndroid Build Coastguard Worker } else
167*1c60b9acSAndroid Build Coastguard Worker *len = LWS_SMD_SS_RX_HEADER_LEN + (unsigned int)
168*1c60b9acSAndroid Build Coastguard Worker lws_snprintf((char *)buf + LWS_SMD_SS_RX_HEADER_LEN, *len,
169*1c60b9acSAndroid Build Coastguard Worker "{\"class\":\"user\",\"fork\": %d,\"test\":%u}",
170*1c60b9acSAndroid Build Coastguard Worker (int)(intptr_t)lws_context_user(lws_ss_get_context(m->ss)),
171*1c60b9acSAndroid Build Coastguard Worker m->count++);
172*1c60b9acSAndroid Build Coastguard Worker
173*1c60b9acSAndroid Build Coastguard Worker *flags = LWSSS_FLAG_SOM | LWSSS_FLAG_EOM;
174*1c60b9acSAndroid Build Coastguard Worker
175*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul,
176*1c60b9acSAndroid Build Coastguard Worker sul_multi_tx_periodic_cb, 25 * LWS_US_PER_MS);
177*1c60b9acSAndroid Build Coastguard Worker
178*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
179*1c60b9acSAndroid Build Coastguard Worker }
180*1c60b9acSAndroid Build Coastguard Worker
181*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
multi_myss_state(void * userobj,void * h_src,lws_ss_constate_t state,lws_ss_tx_ordinal_t ack)182*1c60b9acSAndroid Build Coastguard Worker multi_myss_state(void *userobj, void *h_src, lws_ss_constate_t state,
183*1c60b9acSAndroid Build Coastguard Worker lws_ss_tx_ordinal_t ack)
184*1c60b9acSAndroid Build Coastguard Worker {
185*1c60b9acSAndroid Build Coastguard Worker myss_t *m = (myss_t *)userobj;
186*1c60b9acSAndroid Build Coastguard Worker int n;
187*1c60b9acSAndroid Build Coastguard Worker
188*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: %s: %s (%d), ord 0x%x\n", __func__, lws_ss_tag(m->ss),
189*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_name((int)state), state, (unsigned int)ack);
190*1c60b9acSAndroid Build Coastguard Worker
191*1c60b9acSAndroid Build Coastguard Worker switch (state) {
192*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_DESTROYING:
193*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&m->sul);
194*1c60b9acSAndroid Build Coastguard Worker interrupted = 1;
195*1c60b9acSAndroid Build Coastguard Worker return 0;
196*1c60b9acSAndroid Build Coastguard Worker
197*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_CONNECTED:
198*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: CONNECTED: test fork %d\n", __func__,
199*1c60b9acSAndroid Build Coastguard Worker (int)(intptr_t)lws_context_user(lws_ss_get_context(m->ss)));
200*1c60b9acSAndroid Build Coastguard Worker /*
201*1c60b9acSAndroid Build Coastguard Worker * Because in this test everybody is watching and counting
202*1c60b9acSAndroid Build Coastguard Worker * everybody else's messages from different forks, we have to
203*1c60b9acSAndroid Build Coastguard Worker * hold off starting sending for 2s so all forks can join the
204*1c60b9acSAndroid Build Coastguard Worker * proxy first and not miss anything
205*1c60b9acSAndroid Build Coastguard Worker */
206*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul,
207*1c60b9acSAndroid Build Coastguard Worker sul_multi_tx_periodic_cb, 2 * LWS_US_PER_SEC);
208*1c60b9acSAndroid Build Coastguard Worker m->starting = 0;
209*1c60b9acSAndroid Build Coastguard Worker return 0;
210*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_DISCONNECTED:
211*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < FORKS; n++)
212*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: testfork %d: peer %d: seen_msg = %d, "
213*1c60b9acSAndroid Build Coastguard Worker "seen make = 0x%llx\n", __func__,
214*1c60b9acSAndroid Build Coastguard Worker (int)(intptr_t)lws_context_user(lws_ss_get_context(m->ss)),
215*1c60b9acSAndroid Build Coastguard Worker n, m->seen_msgs[n],
216*1c60b9acSAndroid Build Coastguard Worker (unsigned long long)m->seen_mask[n]);
217*1c60b9acSAndroid Build Coastguard Worker break;
218*1c60b9acSAndroid Build Coastguard Worker default:
219*1c60b9acSAndroid Build Coastguard Worker break;
220*1c60b9acSAndroid Build Coastguard Worker }
221*1c60b9acSAndroid Build Coastguard Worker
222*1c60b9acSAndroid Build Coastguard Worker return 0;
223*1c60b9acSAndroid Build Coastguard Worker }
224*1c60b9acSAndroid Build Coastguard Worker
225*1c60b9acSAndroid Build Coastguard Worker static const lws_ss_info_t ssi_multi_lws_smd = {
226*1c60b9acSAndroid Build Coastguard Worker .handle_offset = offsetof(myss_t, ss),
227*1c60b9acSAndroid Build Coastguard Worker .opaque_user_data_offset = offsetof(myss_t, opaque_data),
228*1c60b9acSAndroid Build Coastguard Worker .rx = multi_myss_rx,
229*1c60b9acSAndroid Build Coastguard Worker .tx = multi_myss_tx,
230*1c60b9acSAndroid Build Coastguard Worker .state = multi_myss_state,
231*1c60b9acSAndroid Build Coastguard Worker .user_alloc = sizeof(myss_t),
232*1c60b9acSAndroid Build Coastguard Worker .streamtype = LWS_SMD_STREAMTYPENAME,
233*1c60b9acSAndroid Build Coastguard Worker .manual_initial_tx_credit = 1 << LWSSMDCL_USER_BASE_BITNUM,
234*1c60b9acSAndroid Build Coastguard Worker };
235*1c60b9acSAndroid Build Coastguard Worker
236*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
multi_myss_rx_monitor(void * userobj,const uint8_t * buf,size_t len,int flags)237*1c60b9acSAndroid Build Coastguard Worker multi_myss_rx_monitor(void *userobj, const uint8_t *buf, size_t len, int flags)
238*1c60b9acSAndroid Build Coastguard Worker {
239*1c60b9acSAndroid Build Coastguard Worker myss_t *m = (myss_t *)userobj;
240*1c60b9acSAndroid Build Coastguard Worker const char *p;
241*1c60b9acSAndroid Build Coastguard Worker size_t al;
242*1c60b9acSAndroid Build Coastguard Worker int fk, n;
243*1c60b9acSAndroid Build Coastguard Worker
244*1c60b9acSAndroid Build Coastguard Worker /* ignore our and other forks announcing their result */
245*1c60b9acSAndroid Build Coastguard Worker
246*1c60b9acSAndroid Build Coastguard Worker if (!lws_json_simple_find((const char *)buf, len, "\"seen_all\":", &al))
247*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
248*1c60b9acSAndroid Build Coastguard Worker
249*1c60b9acSAndroid Build Coastguard Worker p = lws_json_simple_find((const char *)buf, len, "\"fork\":", &al);
250*1c60b9acSAndroid Build Coastguard Worker if (!p)
251*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
252*1c60b9acSAndroid Build Coastguard Worker fk = atoi(p);
253*1c60b9acSAndroid Build Coastguard Worker if (fk < 1 || fk > FORKS)
254*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
255*1c60b9acSAndroid Build Coastguard Worker
256*1c60b9acSAndroid Build Coastguard Worker if (m->seen_msgs[fk - 1])
257*1c60b9acSAndroid Build Coastguard Worker /* expected only once ... dupe */
258*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
259*1c60b9acSAndroid Build Coastguard Worker
260*1c60b9acSAndroid Build Coastguard Worker m->seen_msgs[fk - 1] = 1;
261*1c60b9acSAndroid Build Coastguard Worker
262*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < FORKS; n++)
263*1c60b9acSAndroid Build Coastguard Worker if (!m->seen_msgs[n])
264*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
265*1c60b9acSAndroid Build Coastguard Worker
266*1c60b9acSAndroid Build Coastguard Worker /* the test has succeeded */
267*1c60b9acSAndroid Build Coastguard Worker
268*1c60b9acSAndroid Build Coastguard Worker bad = 0;
269*1c60b9acSAndroid Build Coastguard Worker interrupted = 1;
270*1c60b9acSAndroid Build Coastguard Worker
271*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
272*1c60b9acSAndroid Build Coastguard Worker }
273*1c60b9acSAndroid Build Coastguard Worker
274*1c60b9acSAndroid Build Coastguard Worker static const lws_ss_info_t ssi_multi_lws_smd_monitor = {
275*1c60b9acSAndroid Build Coastguard Worker .handle_offset = offsetof(myss_t, ss),
276*1c60b9acSAndroid Build Coastguard Worker .opaque_user_data_offset = offsetof(myss_t, opaque_data),
277*1c60b9acSAndroid Build Coastguard Worker .rx = multi_myss_rx_monitor,
278*1c60b9acSAndroid Build Coastguard Worker // .state = multi_myss_state_monitor,
279*1c60b9acSAndroid Build Coastguard Worker .user_alloc = sizeof(myss_t),
280*1c60b9acSAndroid Build Coastguard Worker .streamtype = LWS_SMD_STREAMTYPENAME,
281*1c60b9acSAndroid Build Coastguard Worker .manual_initial_tx_credit = 1 << LWSSMDCL_USER_BASE_BITNUM,
282*1c60b9acSAndroid Build Coastguard Worker };
283*1c60b9acSAndroid Build Coastguard Worker
284*1c60b9acSAndroid Build Coastguard Worker /* for comparison, this is a non-SS lws_smd participant */
285*1c60b9acSAndroid Build Coastguard Worker
286*1c60b9acSAndroid Build Coastguard Worker static int
direct_smd_cb(void * opaque,lws_smd_class_t _class,lws_usec_t timestamp,void * buf,size_t len)287*1c60b9acSAndroid Build Coastguard Worker direct_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp,
288*1c60b9acSAndroid Build Coastguard Worker void *buf, size_t len)
289*1c60b9acSAndroid Build Coastguard Worker {
290*1c60b9acSAndroid Build Coastguard Worker struct lws_context **pctx = (struct lws_context **)opaque;
291*1c60b9acSAndroid Build Coastguard Worker
292*1c60b9acSAndroid Build Coastguard Worker if (_class != LWSSMDCL_SYSTEM_STATE)
293*1c60b9acSAndroid Build Coastguard Worker return 0;
294*1c60b9acSAndroid Build Coastguard Worker
295*1c60b9acSAndroid Build Coastguard Worker if (!lws_json_simple_strcmp(buf, len, "\"state\":", "OPERATIONAL")) {
296*1c60b9acSAndroid Build Coastguard Worker
297*1c60b9acSAndroid Build Coastguard Worker /*
298*1c60b9acSAndroid Build Coastguard Worker * Create the SSPC link to lws_smd... notice in ssi_lws_smd
299*1c60b9acSAndroid Build Coastguard Worker * above, we tell this link to use the user class filter.
300*1c60b9acSAndroid Build Coastguard Worker *
301*1c60b9acSAndroid Build Coastguard Worker * If context->user is zero, we are the original process
302*1c60b9acSAndroid Build Coastguard Worker * monitoring the progress of the others, otherwise we are
303*1c60b9acSAndroid Build Coastguard Worker * 1 .. FORKS and producing / checking the smd messages
304*1c60b9acSAndroid Build Coastguard Worker */
305*1c60b9acSAndroid Build Coastguard Worker
306*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: starting ss for test fork %d\n", __func__,
307*1c60b9acSAndroid Build Coastguard Worker (int)(intptr_t)lws_context_user(*pctx));
308*1c60b9acSAndroid Build Coastguard Worker
309*1c60b9acSAndroid Build Coastguard Worker if (lws_ss_create(*pctx, 0, lws_context_user(*pctx) ?
310*1c60b9acSAndroid Build Coastguard Worker &ssi_multi_lws_smd /* forked process send / check */:
311*1c60b9acSAndroid Build Coastguard Worker &ssi_multi_lws_smd_monitor /* original monitors */,
312*1c60b9acSAndroid Build Coastguard Worker NULL, NULL, NULL, NULL)) {
313*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: failed to create secure stream\n",
314*1c60b9acSAndroid Build Coastguard Worker __func__);
315*1c60b9acSAndroid Build Coastguard Worker
316*1c60b9acSAndroid Build Coastguard Worker return -1;
317*1c60b9acSAndroid Build Coastguard Worker }
318*1c60b9acSAndroid Build Coastguard Worker }
319*1c60b9acSAndroid Build Coastguard Worker
320*1c60b9acSAndroid Build Coastguard Worker return 0;
321*1c60b9acSAndroid Build Coastguard Worker }
322*1c60b9acSAndroid Build Coastguard Worker
323*1c60b9acSAndroid Build Coastguard Worker
324*1c60b9acSAndroid Build Coastguard Worker static void
sul_timeout_cb(lws_sorted_usec_list_t * sul)325*1c60b9acSAndroid Build Coastguard Worker sul_timeout_cb(lws_sorted_usec_list_t *sul)
326*1c60b9acSAndroid Build Coastguard Worker {
327*1c60b9acSAndroid Build Coastguard Worker interrupted = 1;
328*1c60b9acSAndroid Build Coastguard Worker }
329*1c60b9acSAndroid Build Coastguard Worker
330*1c60b9acSAndroid Build Coastguard Worker int
smd_ss_multi_test(int argc,const char ** argv)331*1c60b9acSAndroid Build Coastguard Worker smd_ss_multi_test(int argc, const char **argv)
332*1c60b9acSAndroid Build Coastguard Worker {
333*1c60b9acSAndroid Build Coastguard Worker struct lws_context_creation_info info;
334*1c60b9acSAndroid Build Coastguard Worker lws_sorted_usec_list_t sul_timeout;
335*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context;
336*1c60b9acSAndroid Build Coastguard Worker pid_t pid;
337*1c60b9acSAndroid Build Coastguard Worker int n;
338*1c60b9acSAndroid Build Coastguard Worker
339*1c60b9acSAndroid Build Coastguard Worker lwsl_user("LWS Secure Streams SMD MULTI test client [-d<verb>]\n");
340*1c60b9acSAndroid Build Coastguard Worker
341*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < FORKS; n++) {
342*1c60b9acSAndroid Build Coastguard Worker pid = fork();
343*1c60b9acSAndroid Build Coastguard Worker if (!pid) /* forked child */ {
344*1c60b9acSAndroid Build Coastguard Worker break;
345*1c60b9acSAndroid Build Coastguard Worker }
346*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: forked test process %u\n", __func__, pid);
347*1c60b9acSAndroid Build Coastguard Worker }
348*1c60b9acSAndroid Build Coastguard Worker
349*1c60b9acSAndroid Build Coastguard Worker if (n == FORKS)
350*1c60b9acSAndroid Build Coastguard Worker /* the original process */
351*1c60b9acSAndroid Build Coastguard Worker n = -1; /* so original ends up with context.user as 0 below */
352*1c60b9acSAndroid Build Coastguard Worker
353*1c60b9acSAndroid Build Coastguard Worker memset(&info, 0, sizeof info);
354*1c60b9acSAndroid Build Coastguard Worker memset(&sul_timeout, 0, sizeof sul_timeout);
355*1c60b9acSAndroid Build Coastguard Worker
356*1c60b9acSAndroid Build Coastguard Worker lws_cmdline_option_handle_builtin(argc, argv, &info);
357*1c60b9acSAndroid Build Coastguard Worker
358*1c60b9acSAndroid Build Coastguard Worker {
359*1c60b9acSAndroid Build Coastguard Worker const char *p;
360*1c60b9acSAndroid Build Coastguard Worker
361*1c60b9acSAndroid Build Coastguard Worker /* connect to ssproxy via UDS by default, else via
362*1c60b9acSAndroid Build Coastguard Worker * tcp connection to this port */
363*1c60b9acSAndroid Build Coastguard Worker if ((p = lws_cmdline_option(argc, argv, "-p")))
364*1c60b9acSAndroid Build Coastguard Worker info.ss_proxy_port = (uint16_t)atoi(p);
365*1c60b9acSAndroid Build Coastguard Worker
366*1c60b9acSAndroid Build Coastguard Worker /* UDS "proxy.ss.lws" in abstract namespace, else this socket
367*1c60b9acSAndroid Build Coastguard Worker * path; when -p given this can specify the network interface
368*1c60b9acSAndroid Build Coastguard Worker * to bind to */
369*1c60b9acSAndroid Build Coastguard Worker if ((p = lws_cmdline_option(argc, argv, "-i")))
370*1c60b9acSAndroid Build Coastguard Worker info.ss_proxy_bind = p;
371*1c60b9acSAndroid Build Coastguard Worker
372*1c60b9acSAndroid Build Coastguard Worker /* if -p given, -a specifies the proxy address to connect to */
373*1c60b9acSAndroid Build Coastguard Worker if ((p = lws_cmdline_option(argc, argv, "-a")))
374*1c60b9acSAndroid Build Coastguard Worker info.ss_proxy_address = p;
375*1c60b9acSAndroid Build Coastguard Worker }
376*1c60b9acSAndroid Build Coastguard Worker
377*1c60b9acSAndroid Build Coastguard Worker info.fd_limit_per_thread = 1 + 6 + 1;
378*1c60b9acSAndroid Build Coastguard Worker info.port = CONTEXT_PORT_NO_LISTEN;
379*1c60b9acSAndroid Build Coastguard Worker info.protocols = lws_sspc_protocols;
380*1c60b9acSAndroid Build Coastguard Worker info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
381*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
382*1c60b9acSAndroid Build Coastguard Worker
383*1c60b9acSAndroid Build Coastguard Worker info.early_smd_cb = direct_smd_cb;
384*1c60b9acSAndroid Build Coastguard Worker info.early_smd_class_filter = 0xffffffff;
385*1c60b9acSAndroid Build Coastguard Worker info.early_smd_opaque = &context;
386*1c60b9acSAndroid Build Coastguard Worker
387*1c60b9acSAndroid Build Coastguard Worker info.user = (void *)(intptr_t)(n + 1);
388*1c60b9acSAndroid Build Coastguard Worker
389*1c60b9acSAndroid Build Coastguard Worker /* create the context */
390*1c60b9acSAndroid Build Coastguard Worker
391*1c60b9acSAndroid Build Coastguard Worker context = lws_create_context(&info);
392*1c60b9acSAndroid Build Coastguard Worker if (!context) {
393*1c60b9acSAndroid Build Coastguard Worker lwsl_err("lws init failed\n");
394*1c60b9acSAndroid Build Coastguard Worker return 1;
395*1c60b9acSAndroid Build Coastguard Worker }
396*1c60b9acSAndroid Build Coastguard Worker
397*1c60b9acSAndroid Build Coastguard Worker if (!lws_create_vhost(context, &info)) {
398*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: failed to create default vhost\n", __func__);
399*1c60b9acSAndroid Build Coastguard Worker goto bail;
400*1c60b9acSAndroid Build Coastguard Worker }
401*1c60b9acSAndroid Build Coastguard Worker
402*1c60b9acSAndroid Build Coastguard Worker /* set up the test timeout */
403*1c60b9acSAndroid Build Coastguard Worker
404*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(context, 0, &sul_timeout, sul_timeout_cb,
405*1c60b9acSAndroid Build Coastguard Worker 10 * LWS_US_PER_SEC);
406*1c60b9acSAndroid Build Coastguard Worker
407*1c60b9acSAndroid Build Coastguard Worker /* the event loop */
408*1c60b9acSAndroid Build Coastguard Worker
409*1c60b9acSAndroid Build Coastguard Worker while (lws_service(context, 0) >= 0 && !interrupted)
410*1c60b9acSAndroid Build Coastguard Worker ;
411*1c60b9acSAndroid Build Coastguard Worker
412*1c60b9acSAndroid Build Coastguard Worker bail:
413*1c60b9acSAndroid Build Coastguard Worker lws_context_destroy(context);
414*1c60b9acSAndroid Build Coastguard Worker
415*1c60b9acSAndroid Build Coastguard Worker if (n == -1)
416*1c60b9acSAndroid Build Coastguard Worker lwsl_user("%s: finished %s\n", __func__, bad ? "FAIL" : "PASS");
417*1c60b9acSAndroid Build Coastguard Worker
418*1c60b9acSAndroid Build Coastguard Worker return bad;
419*1c60b9acSAndroid Build Coastguard Worker }
420