1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * lws-minimal-secure-streams-tx
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 proxied mass tx from secure streams, this example is a
11*1c60b9acSAndroid Build Coastguard Worker * client that has no policy of its own, but gets stuff done via the ss proxy.
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * It opens a websocket stream and fires 100 x small 80-byte payloads on it
14*1c60b9acSAndroid Build Coastguard Worker * at 20Hz (50ms)
15*1c60b9acSAndroid Build Coastguard Worker */
16*1c60b9acSAndroid Build Coastguard Worker
17*1c60b9acSAndroid Build Coastguard Worker #define LWS_SS_USE_SSPC
18*1c60b9acSAndroid Build Coastguard Worker
19*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
20*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
21*1c60b9acSAndroid Build Coastguard Worker #include <signal.h>
22*1c60b9acSAndroid Build Coastguard Worker
23*1c60b9acSAndroid Build Coastguard Worker #define PKT_SIZE 80
24*1c60b9acSAndroid Build Coastguard Worker #define RATE_US 50000
25*1c60b9acSAndroid Build Coastguard Worker
26*1c60b9acSAndroid Build Coastguard Worker static int interrupted, bad = 1, reads = 100;
27*1c60b9acSAndroid Build Coastguard Worker
28*1c60b9acSAndroid Build Coastguard Worker typedef struct myss {
29*1c60b9acSAndroid Build Coastguard Worker struct lws_ss_handle *ss;
30*1c60b9acSAndroid Build Coastguard Worker void *opaque_data;
31*1c60b9acSAndroid Build Coastguard Worker /* ... application specific state ... */
32*1c60b9acSAndroid Build Coastguard Worker lws_sorted_usec_list_t sul;
33*1c60b9acSAndroid Build Coastguard Worker
34*1c60b9acSAndroid Build Coastguard Worker int count;
35*1c60b9acSAndroid Build Coastguard Worker char due;
36*1c60b9acSAndroid Build Coastguard Worker } myss_t;
37*1c60b9acSAndroid Build Coastguard Worker
38*1c60b9acSAndroid Build Coastguard Worker /* secure streams payload interface */
39*1c60b9acSAndroid Build Coastguard Worker
40*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
myss_rx(void * userobj,const uint8_t * buf,size_t len,int flags)41*1c60b9acSAndroid Build Coastguard Worker myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
42*1c60b9acSAndroid Build Coastguard Worker {
43*1c60b9acSAndroid Build Coastguard Worker /* this example isn't interested in rx */
44*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
45*1c60b9acSAndroid Build Coastguard Worker }
46*1c60b9acSAndroid Build Coastguard Worker
47*1c60b9acSAndroid Build Coastguard Worker static void
txcb(struct lws_sorted_usec_list * sul)48*1c60b9acSAndroid Build Coastguard Worker txcb(struct lws_sorted_usec_list *sul)
49*1c60b9acSAndroid Build Coastguard Worker {
50*1c60b9acSAndroid Build Coastguard Worker myss_t *m = lws_container_of(sul, myss_t, sul);
51*1c60b9acSAndroid Build Coastguard Worker
52*1c60b9acSAndroid Build Coastguard Worker /*
53*1c60b9acSAndroid Build Coastguard Worker * We want to do 100 of these ws messages, and then exit, so we can run
54*1c60b9acSAndroid Build Coastguard Worker * this as a pass / fail test.
55*1c60b9acSAndroid Build Coastguard Worker */
56*1c60b9acSAndroid Build Coastguard Worker
57*1c60b9acSAndroid Build Coastguard Worker if (m->count == reads) {
58*1c60b9acSAndroid Build Coastguard Worker interrupted = 1;
59*1c60b9acSAndroid Build Coastguard Worker bad = 0;
60*1c60b9acSAndroid Build Coastguard Worker } else {
61*1c60b9acSAndroid Build Coastguard Worker m->due = 1;
62*1c60b9acSAndroid Build Coastguard Worker lws_ss_request_tx(m->ss);
63*1c60b9acSAndroid Build Coastguard Worker }
64*1c60b9acSAndroid Build Coastguard Worker
65*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul, txcb, RATE_US);
66*1c60b9acSAndroid Build Coastguard Worker }
67*1c60b9acSAndroid Build Coastguard Worker
68*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
myss_tx(void * userobj,lws_ss_tx_ordinal_t ord,uint8_t * buf,size_t * len,int * flags)69*1c60b9acSAndroid Build Coastguard Worker myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len,
70*1c60b9acSAndroid Build Coastguard Worker int *flags)
71*1c60b9acSAndroid Build Coastguard Worker {
72*1c60b9acSAndroid Build Coastguard Worker myss_t *m = (myss_t *)userobj;
73*1c60b9acSAndroid Build Coastguard Worker
74*1c60b9acSAndroid Build Coastguard Worker if (!m->due)
75*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_TX_DONT_SEND;
76*1c60b9acSAndroid Build Coastguard Worker
77*1c60b9acSAndroid Build Coastguard Worker m->due = 0;
78*1c60b9acSAndroid Build Coastguard Worker
79*1c60b9acSAndroid Build Coastguard Worker if (lws_get_random(lws_ss_get_context(m->ss), buf, PKT_SIZE) != PKT_SIZE)
80*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_TX_DONT_SEND;
81*1c60b9acSAndroid Build Coastguard Worker
82*1c60b9acSAndroid Build Coastguard Worker *len = PKT_SIZE;
83*1c60b9acSAndroid Build Coastguard Worker *flags = LWSSS_FLAG_SOM | LWSSS_FLAG_EOM;
84*1c60b9acSAndroid Build Coastguard Worker
85*1c60b9acSAndroid Build Coastguard Worker m->count++;
86*1c60b9acSAndroid Build Coastguard Worker
87*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul, txcb, RATE_US);
88*1c60b9acSAndroid Build Coastguard Worker
89*1c60b9acSAndroid Build Coastguard Worker lwsl_user("%s: sending pkt %d\n", __func__, m->count);
90*1c60b9acSAndroid Build Coastguard Worker
91*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
92*1c60b9acSAndroid Build Coastguard Worker }
93*1c60b9acSAndroid Build Coastguard Worker
94*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
myss_state(void * userobj,void * sh,lws_ss_constate_t state,lws_ss_tx_ordinal_t ack)95*1c60b9acSAndroid Build Coastguard Worker myss_state(void *userobj, void *sh, lws_ss_constate_t state,
96*1c60b9acSAndroid Build Coastguard Worker lws_ss_tx_ordinal_t ack)
97*1c60b9acSAndroid Build Coastguard Worker {
98*1c60b9acSAndroid Build Coastguard Worker myss_t *m = (myss_t *)userobj;
99*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = lws_ss_get_context(m->ss);
100*1c60b9acSAndroid Build Coastguard Worker
101*1c60b9acSAndroid Build Coastguard Worker lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name((int)state),
102*1c60b9acSAndroid Build Coastguard Worker (unsigned int)ack);
103*1c60b9acSAndroid Build Coastguard Worker
104*1c60b9acSAndroid Build Coastguard Worker switch (state) {
105*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_CREATING:
106*1c60b9acSAndroid Build Coastguard Worker return lws_ss_client_connect(m->ss);
107*1c60b9acSAndroid Build Coastguard Worker
108*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_CONNECTED:
109*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(context, 0, &m->sul, txcb, RATE_US);
110*1c60b9acSAndroid Build Coastguard Worker break;
111*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_DISCONNECTED:
112*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&m->sul);
113*1c60b9acSAndroid Build Coastguard Worker break;
114*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_ALL_RETRIES_FAILED:
115*1c60b9acSAndroid Build Coastguard Worker /* if we're out of retries, we want to close the app and FAIL */
116*1c60b9acSAndroid Build Coastguard Worker interrupted = 1;
117*1c60b9acSAndroid Build Coastguard Worker break;
118*1c60b9acSAndroid Build Coastguard Worker default:
119*1c60b9acSAndroid Build Coastguard Worker break;
120*1c60b9acSAndroid Build Coastguard Worker }
121*1c60b9acSAndroid Build Coastguard Worker
122*1c60b9acSAndroid Build Coastguard Worker return 0;
123*1c60b9acSAndroid Build Coastguard Worker }
124*1c60b9acSAndroid Build Coastguard Worker
125*1c60b9acSAndroid Build Coastguard Worker static void
sigint_handler(int sig)126*1c60b9acSAndroid Build Coastguard Worker sigint_handler(int sig)
127*1c60b9acSAndroid Build Coastguard Worker {
128*1c60b9acSAndroid Build Coastguard Worker interrupted = 1;
129*1c60b9acSAndroid Build Coastguard Worker }
130*1c60b9acSAndroid Build Coastguard Worker
131*1c60b9acSAndroid Build Coastguard Worker static const lws_ss_info_t ssi = {
132*1c60b9acSAndroid Build Coastguard Worker .handle_offset = offsetof(myss_t, ss),
133*1c60b9acSAndroid Build Coastguard Worker .opaque_user_data_offset = offsetof(myss_t, opaque_data),
134*1c60b9acSAndroid Build Coastguard Worker .rx = myss_rx,
135*1c60b9acSAndroid Build Coastguard Worker .tx = myss_tx,
136*1c60b9acSAndroid Build Coastguard Worker .state = myss_state,
137*1c60b9acSAndroid Build Coastguard Worker .user_alloc = sizeof(myss_t),
138*1c60b9acSAndroid Build Coastguard Worker .streamtype = "spam"
139*1c60b9acSAndroid Build Coastguard Worker };
140*1c60b9acSAndroid Build Coastguard Worker
main(int argc,const char ** argv)141*1c60b9acSAndroid Build Coastguard Worker int main(int argc, const char **argv)
142*1c60b9acSAndroid Build Coastguard Worker {
143*1c60b9acSAndroid Build Coastguard Worker int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
144*1c60b9acSAndroid Build Coastguard Worker struct lws_context_creation_info info;
145*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context;
146*1c60b9acSAndroid Build Coastguard Worker const char *p;
147*1c60b9acSAndroid Build Coastguard Worker
148*1c60b9acSAndroid Build Coastguard Worker signal(SIGINT, sigint_handler);
149*1c60b9acSAndroid Build Coastguard Worker
150*1c60b9acSAndroid Build Coastguard Worker if ((p = lws_cmdline_option(argc, argv, "-d")))
151*1c60b9acSAndroid Build Coastguard Worker logs = atoi(p);
152*1c60b9acSAndroid Build Coastguard Worker
153*1c60b9acSAndroid Build Coastguard Worker if ((p = lws_cmdline_option(argc, argv, "-c")))
154*1c60b9acSAndroid Build Coastguard Worker reads = atoi(p);
155*1c60b9acSAndroid Build Coastguard Worker
156*1c60b9acSAndroid Build Coastguard Worker lws_set_log_level(logs, NULL);
157*1c60b9acSAndroid Build Coastguard Worker lwsl_user("LWS secure streams client TX [-d<verb>]\n");
158*1c60b9acSAndroid Build Coastguard Worker
159*1c60b9acSAndroid Build Coastguard Worker memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
160*1c60b9acSAndroid Build Coastguard Worker
161*1c60b9acSAndroid Build Coastguard Worker info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
162*1c60b9acSAndroid Build Coastguard Worker info.fd_limit_per_thread = 1 + 6 + 1;
163*1c60b9acSAndroid Build Coastguard Worker info.port = CONTEXT_PORT_NO_LISTEN;
164*1c60b9acSAndroid Build Coastguard Worker info.protocols = lws_sspc_protocols;
165*1c60b9acSAndroid Build Coastguard Worker {
166*1c60b9acSAndroid Build Coastguard Worker const char *p;
167*1c60b9acSAndroid Build Coastguard Worker
168*1c60b9acSAndroid Build Coastguard Worker /* connect to ssproxy via UDS by default, else via
169*1c60b9acSAndroid Build Coastguard Worker * tcp connection to this port */
170*1c60b9acSAndroid Build Coastguard Worker if ((p = lws_cmdline_option(argc, argv, "-p")))
171*1c60b9acSAndroid Build Coastguard Worker info.ss_proxy_port = (uint16_t)atoi(p);
172*1c60b9acSAndroid Build Coastguard Worker
173*1c60b9acSAndroid Build Coastguard Worker /* UDS "proxy.ss.lws" in abstract namespace, else this socket
174*1c60b9acSAndroid Build Coastguard Worker * path; when -p given this can specify the network interface
175*1c60b9acSAndroid Build Coastguard Worker * to bind to */
176*1c60b9acSAndroid Build Coastguard Worker if ((p = lws_cmdline_option(argc, argv, "-i")))
177*1c60b9acSAndroid Build Coastguard Worker info.ss_proxy_bind = p;
178*1c60b9acSAndroid Build Coastguard Worker
179*1c60b9acSAndroid Build Coastguard Worker /* if -p given, -a specifies the proxy address to connect to */
180*1c60b9acSAndroid Build Coastguard Worker if ((p = lws_cmdline_option(argc, argv, "-a")))
181*1c60b9acSAndroid Build Coastguard Worker info.ss_proxy_address = p;
182*1c60b9acSAndroid Build Coastguard Worker }
183*1c60b9acSAndroid Build Coastguard Worker
184*1c60b9acSAndroid Build Coastguard Worker context = lws_create_context(&info);
185*1c60b9acSAndroid Build Coastguard Worker if (!context) {
186*1c60b9acSAndroid Build Coastguard Worker lwsl_err("lws init failed\n");
187*1c60b9acSAndroid Build Coastguard Worker goto bail1;
188*1c60b9acSAndroid Build Coastguard Worker }
189*1c60b9acSAndroid Build Coastguard Worker
190*1c60b9acSAndroid Build Coastguard Worker if (lws_ss_create(context, 0, &ssi, NULL, NULL, NULL, NULL)) {
191*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: create secure stream failed\n", __func__);
192*1c60b9acSAndroid Build Coastguard Worker goto bail;
193*1c60b9acSAndroid Build Coastguard Worker }
194*1c60b9acSAndroid Build Coastguard Worker
195*1c60b9acSAndroid Build Coastguard Worker /* the event loop */
196*1c60b9acSAndroid Build Coastguard Worker
197*1c60b9acSAndroid Build Coastguard Worker while (n >= 0 && !interrupted)
198*1c60b9acSAndroid Build Coastguard Worker n = lws_service(context, 0);
199*1c60b9acSAndroid Build Coastguard Worker
200*1c60b9acSAndroid Build Coastguard Worker bail:
201*1c60b9acSAndroid Build Coastguard Worker lws_context_destroy(context);
202*1c60b9acSAndroid Build Coastguard Worker
203*1c60b9acSAndroid Build Coastguard Worker bail1:
204*1c60b9acSAndroid Build Coastguard Worker lwsl_user("Completed: %s\n", bad ? "failed" : "OK");
205*1c60b9acSAndroid Build Coastguard Worker
206*1c60b9acSAndroid Build Coastguard Worker return bad;
207*1c60b9acSAndroid Build Coastguard Worker }
208