1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * lws-minimal-raw-adopt-udp
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Written in 2010-2019 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 * This demonstrates integrating a connected udp
10*1c60b9acSAndroid Build Coastguard Worker * socket into the lws event loop as a RAW wsi. It's interesting in
11*1c60b9acSAndroid Build Coastguard Worker * the kind of situation where you already have a connected socket
12*1c60b9acSAndroid Build Coastguard Worker * in your application, and you need to hand it over to lws to deal with.
13*1c60b9acSAndroid Build Coastguard Worker *
14*1c60b9acSAndroid Build Coastguard Worker * Lws supports "adopting" these foreign sockets, and also has a helper API
15*1c60b9acSAndroid Build Coastguard Worker * to create, bind, and adopt them inside lws.
16*1c60b9acSAndroid Build Coastguard Worker */
17*1c60b9acSAndroid Build Coastguard Worker
18*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
19*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
20*1c60b9acSAndroid Build Coastguard Worker #include <signal.h>
21*1c60b9acSAndroid Build Coastguard Worker #if !defined(WIN32)
22*1c60b9acSAndroid Build Coastguard Worker #include <sys/socket.h>
23*1c60b9acSAndroid Build Coastguard Worker #include <netinet/in.h>
24*1c60b9acSAndroid Build Coastguard Worker #include <netdb.h>
25*1c60b9acSAndroid Build Coastguard Worker #include <arpa/inet.h>
26*1c60b9acSAndroid Build Coastguard Worker #endif
27*1c60b9acSAndroid Build Coastguard Worker #include <sys/types.h>
28*1c60b9acSAndroid Build Coastguard Worker #include <stdio.h>
29*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
30*1c60b9acSAndroid Build Coastguard Worker #include <stdlib.h>
31*1c60b9acSAndroid Build Coastguard Worker #if !defined(WIN32)
32*1c60b9acSAndroid Build Coastguard Worker #include <unistd.h>
33*1c60b9acSAndroid Build Coastguard Worker #endif
34*1c60b9acSAndroid Build Coastguard Worker #include <errno.h>
35*1c60b9acSAndroid Build Coastguard Worker
36*1c60b9acSAndroid Build Coastguard Worker static uint8_t sendbuf[4096];
37*1c60b9acSAndroid Build Coastguard Worker static size_t sendlen;
38*1c60b9acSAndroid Build Coastguard Worker struct lws_udp udp;
39*1c60b9acSAndroid Build Coastguard Worker
40*1c60b9acSAndroid Build Coastguard Worker static int
callback_raw_test(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)41*1c60b9acSAndroid Build Coastguard Worker callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason,
42*1c60b9acSAndroid Build Coastguard Worker void *user, void *in, size_t len)
43*1c60b9acSAndroid Build Coastguard Worker {
44*1c60b9acSAndroid Build Coastguard Worker ssize_t n;
45*1c60b9acSAndroid Build Coastguard Worker lws_sockfd_type fd;
46*1c60b9acSAndroid Build Coastguard Worker
47*1c60b9acSAndroid Build Coastguard Worker switch (reason) {
48*1c60b9acSAndroid Build Coastguard Worker
49*1c60b9acSAndroid Build Coastguard Worker /* callbacks related to raw socket descriptor */
50*1c60b9acSAndroid Build Coastguard Worker
51*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_ADOPT:
52*1c60b9acSAndroid Build Coastguard Worker lwsl_user("LWS_CALLBACK_RAW_ADOPT\n");
53*1c60b9acSAndroid Build Coastguard Worker break;
54*1c60b9acSAndroid Build Coastguard Worker
55*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_CLOSE:
56*1c60b9acSAndroid Build Coastguard Worker lwsl_user("LWS_CALLBACK_RAW_CLOSE\n");
57*1c60b9acSAndroid Build Coastguard Worker break;
58*1c60b9acSAndroid Build Coastguard Worker
59*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_RX:
60*1c60b9acSAndroid Build Coastguard Worker lwsl_user("LWS_CALLBACK_RAW_RX (%d)\n", (int)len);
61*1c60b9acSAndroid Build Coastguard Worker lwsl_hexdump_level(LLL_NOTICE, in, len);
62*1c60b9acSAndroid Build Coastguard Worker /*
63*1c60b9acSAndroid Build Coastguard Worker * Take a copy of the buffer and the source socket address...
64*1c60b9acSAndroid Build Coastguard Worker */
65*1c60b9acSAndroid Build Coastguard Worker udp = *(lws_get_udp(wsi));
66*1c60b9acSAndroid Build Coastguard Worker sendlen = len;
67*1c60b9acSAndroid Build Coastguard Worker if (sendlen > sizeof(sendbuf))
68*1c60b9acSAndroid Build Coastguard Worker sendlen = sizeof(sendbuf);
69*1c60b9acSAndroid Build Coastguard Worker memcpy(sendbuf, in, sendlen);
70*1c60b9acSAndroid Build Coastguard Worker /*
71*1c60b9acSAndroid Build Coastguard Worker * ... and we send it next time around the event loop. This
72*1c60b9acSAndroid Build Coastguard Worker * can be extended to having a ringbuffer of different send
73*1c60b9acSAndroid Build Coastguard Worker * buffers and targets queued.
74*1c60b9acSAndroid Build Coastguard Worker *
75*1c60b9acSAndroid Build Coastguard Worker * Note that UDP is ALWAYS writable as far as poll() knows
76*1c60b9acSAndroid Build Coastguard Worker * because there is no mechanism like the tcp window to
77*1c60b9acSAndroid Build Coastguard Worker * understand that packets are not being acknowledged. But
78*1c60b9acSAndroid Build Coastguard Worker * this allows the event loop to share out the work.
79*1c60b9acSAndroid Build Coastguard Worker */
80*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(wsi);
81*1c60b9acSAndroid Build Coastguard Worker break;
82*1c60b9acSAndroid Build Coastguard Worker
83*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_RAW_WRITEABLE:
84*1c60b9acSAndroid Build Coastguard Worker
85*1c60b9acSAndroid Build Coastguard Worker if (!sendlen)
86*1c60b9acSAndroid Build Coastguard Worker break;
87*1c60b9acSAndroid Build Coastguard Worker
88*1c60b9acSAndroid Build Coastguard Worker fd = lws_get_socket_fd(wsi);
89*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32)
90*1c60b9acSAndroid Build Coastguard Worker if ((int)fd < 0)
91*1c60b9acSAndroid Build Coastguard Worker break;
92*1c60b9acSAndroid Build Coastguard Worker #else
93*1c60b9acSAndroid Build Coastguard Worker if (fd < 0) /* keep Coverity happy: actually it cannot be < 0 */
94*1c60b9acSAndroid Build Coastguard Worker break;
95*1c60b9acSAndroid Build Coastguard Worker #endif
96*1c60b9acSAndroid Build Coastguard Worker
97*1c60b9acSAndroid Build Coastguard Worker /*
98*1c60b9acSAndroid Build Coastguard Worker * We can write directly on the UDP socket, specifying
99*1c60b9acSAndroid Build Coastguard Worker * the peer the write is directed to.
100*1c60b9acSAndroid Build Coastguard Worker *
101*1c60b9acSAndroid Build Coastguard Worker * However the kernel may only accept parts of large sendto()s,
102*1c60b9acSAndroid Build Coastguard Worker * leaving you to try to resend the remainder later. However
103*1c60b9acSAndroid Build Coastguard Worker * depending on how your protocol on top of UDP works, that
104*1c60b9acSAndroid Build Coastguard Worker * may involve sticking new headers before the remainder.
105*1c60b9acSAndroid Build Coastguard Worker *
106*1c60b9acSAndroid Build Coastguard Worker * For clarity partial sends just drop the remainder here.
107*1c60b9acSAndroid Build Coastguard Worker */
108*1c60b9acSAndroid Build Coastguard Worker n = sendto(fd,
109*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32)
110*1c60b9acSAndroid Build Coastguard Worker (const char *)
111*1c60b9acSAndroid Build Coastguard Worker #endif
112*1c60b9acSAndroid Build Coastguard Worker sendbuf,
113*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32)
114*1c60b9acSAndroid Build Coastguard Worker (int)
115*1c60b9acSAndroid Build Coastguard Worker #endif
116*1c60b9acSAndroid Build Coastguard Worker sendlen, 0, sa46_sockaddr(&udp.sa46),
117*1c60b9acSAndroid Build Coastguard Worker sa46_socklen(&udp.sa46));
118*1c60b9acSAndroid Build Coastguard Worker if (n < (ssize_t)len)
119*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: send returned %d\n", __func__, (int)n);
120*1c60b9acSAndroid Build Coastguard Worker break;
121*1c60b9acSAndroid Build Coastguard Worker
122*1c60b9acSAndroid Build Coastguard Worker default:
123*1c60b9acSAndroid Build Coastguard Worker break;
124*1c60b9acSAndroid Build Coastguard Worker }
125*1c60b9acSAndroid Build Coastguard Worker
126*1c60b9acSAndroid Build Coastguard Worker return 0;
127*1c60b9acSAndroid Build Coastguard Worker }
128*1c60b9acSAndroid Build Coastguard Worker
129*1c60b9acSAndroid Build Coastguard Worker static struct lws_protocols protocols[] = {
130*1c60b9acSAndroid Build Coastguard Worker { "raw-test", callback_raw_test, 0, 0, 0, NULL, 0 },
131*1c60b9acSAndroid Build Coastguard Worker LWS_PROTOCOL_LIST_TERM
132*1c60b9acSAndroid Build Coastguard Worker };
133*1c60b9acSAndroid Build Coastguard Worker
134*1c60b9acSAndroid Build Coastguard Worker static int interrupted;
135*1c60b9acSAndroid Build Coastguard Worker
sigint_handler(int sig)136*1c60b9acSAndroid Build Coastguard Worker void sigint_handler(int sig)
137*1c60b9acSAndroid Build Coastguard Worker {
138*1c60b9acSAndroid Build Coastguard Worker interrupted = 1;
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 struct lws_context_creation_info info;
144*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context;
145*1c60b9acSAndroid Build Coastguard Worker struct lws_vhost *vhost;
146*1c60b9acSAndroid Build Coastguard Worker const char *p;
147*1c60b9acSAndroid Build Coastguard Worker int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
148*1c60b9acSAndroid Build Coastguard Worker /* for LLL_ verbosity above NOTICE to be built into lws,
149*1c60b9acSAndroid Build Coastguard Worker * lws must have been configured and built with
150*1c60b9acSAndroid Build Coastguard Worker * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
151*1c60b9acSAndroid Build Coastguard Worker /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
152*1c60b9acSAndroid Build Coastguard Worker /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
153*1c60b9acSAndroid Build Coastguard Worker /* | LLL_DEBUG */;
154*1c60b9acSAndroid Build Coastguard Worker
155*1c60b9acSAndroid Build Coastguard Worker signal(SIGINT, sigint_handler);
156*1c60b9acSAndroid Build Coastguard Worker
157*1c60b9acSAndroid Build Coastguard Worker if ((p = lws_cmdline_option(argc, argv, "-d")))
158*1c60b9acSAndroid Build Coastguard Worker logs = atoi(p);
159*1c60b9acSAndroid Build Coastguard Worker
160*1c60b9acSAndroid Build Coastguard Worker lws_set_log_level(logs, NULL);
161*1c60b9acSAndroid Build Coastguard Worker lwsl_user("LWS minimal raw adopt udp | nc -u 127.0.0.1 7681\n");
162*1c60b9acSAndroid Build Coastguard Worker
163*1c60b9acSAndroid Build Coastguard Worker memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
164*1c60b9acSAndroid Build Coastguard Worker info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS;
165*1c60b9acSAndroid Build Coastguard Worker
166*1c60b9acSAndroid Build Coastguard Worker context = lws_create_context(&info);
167*1c60b9acSAndroid Build Coastguard Worker if (!context) {
168*1c60b9acSAndroid Build Coastguard Worker lwsl_err("lws init failed\n");
169*1c60b9acSAndroid Build Coastguard Worker return 1;
170*1c60b9acSAndroid Build Coastguard Worker }
171*1c60b9acSAndroid Build Coastguard Worker
172*1c60b9acSAndroid Build Coastguard Worker info.port = CONTEXT_PORT_NO_LISTEN_SERVER;
173*1c60b9acSAndroid Build Coastguard Worker info.protocols = protocols;
174*1c60b9acSAndroid Build Coastguard Worker
175*1c60b9acSAndroid Build Coastguard Worker vhost = lws_create_vhost(context, &info);
176*1c60b9acSAndroid Build Coastguard Worker if (!vhost) {
177*1c60b9acSAndroid Build Coastguard Worker lwsl_err("lws vhost creation failed\n");
178*1c60b9acSAndroid Build Coastguard Worker goto bail;
179*1c60b9acSAndroid Build Coastguard Worker }
180*1c60b9acSAndroid Build Coastguard Worker
181*1c60b9acSAndroid Build Coastguard Worker /*
182*1c60b9acSAndroid Build Coastguard Worker * Create our own "foreign" UDP socket bound to 7681/udp
183*1c60b9acSAndroid Build Coastguard Worker */
184*1c60b9acSAndroid Build Coastguard Worker if (!lws_create_adopt_udp(vhost, NULL, 7681, LWS_CAUDP_BIND,
185*1c60b9acSAndroid Build Coastguard Worker protocols[0].name, NULL, NULL, NULL, NULL,
186*1c60b9acSAndroid Build Coastguard Worker "user")) {
187*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: foreign socket adoption failed\n", __func__);
188*1c60b9acSAndroid Build Coastguard Worker goto bail;
189*1c60b9acSAndroid Build Coastguard Worker }
190*1c60b9acSAndroid Build Coastguard Worker
191*1c60b9acSAndroid Build Coastguard Worker while (n >= 0 && !interrupted)
192*1c60b9acSAndroid Build Coastguard Worker n = lws_service(context, 0);
193*1c60b9acSAndroid Build Coastguard Worker
194*1c60b9acSAndroid Build Coastguard Worker bail:
195*1c60b9acSAndroid Build Coastguard Worker lws_context_destroy(context);
196*1c60b9acSAndroid Build Coastguard Worker
197*1c60b9acSAndroid Build Coastguard Worker return 0;
198*1c60b9acSAndroid Build Coastguard Worker }
199