introduce-client-support.patch
[profile/ivi/libwebsockets.git] / lib / libwebsockets.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 Andy Green <andy@warmcat.com>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation:
9  *  version 2.1 of the License.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *  MA  02110-1301  USA
20  */
21
22 #include "private-libwebsockets.h"
23
24 #ifdef LWS_OPENSSL_SUPPORT
25 SSL_CTX *ssl_ctx;
26 int use_ssl;
27 #endif
28
29 void
30 libwebsocket_close_and_free_session(struct libwebsocket *wsi)
31 {
32         int n;
33
34         if ((unsigned long)wsi < LWS_MAX_PROTOCOLS)
35                 return;
36
37         n = wsi->state;
38
39         wsi->state = WSI_STATE_DEAD_SOCKET;
40
41         if (wsi->protocol->callback && n == WSI_STATE_ESTABLISHED)
42                 wsi->protocol->callback(wsi, LWS_CALLBACK_CLOSED,
43                                                       wsi->user_space, NULL, 0);
44
45         for (n = 0; n < WSI_TOKEN_COUNT; n++)
46                 if (wsi->utf8_token[n].token)
47                         free(wsi->utf8_token[n].token);
48
49 /*      fprintf(stderr, "closing fd=%d\n", wsi->sock); */
50
51 #ifdef LWS_OPENSSL_SUPPORT
52         if (use_ssl) {
53                 n = SSL_get_fd(wsi->ssl);
54                 SSL_shutdown(wsi->ssl);
55                 close(n);
56                 SSL_free(wsi->ssl);
57         } else {
58 #endif
59                 shutdown(wsi->sock, SHUT_RDWR);
60                 close(wsi->sock);
61 #ifdef LWS_OPENSSL_SUPPORT
62         }
63 #endif
64         if (wsi->user_space)
65                 free(wsi->user_space);
66
67         free(wsi);
68 }
69
70 static int
71 libwebsocket_poll_connections(struct libwebsocket_context *this)
72 {
73         unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_BROADCAST_PAYLOAD +
74                                                   LWS_SEND_BUFFER_POST_PADDING];
75         int client = this->count_protocols + 1;
76         struct libwebsocket *wsi;
77         int n;
78         size_t len;
79
80         /* check for activity on client sockets */
81
82         for (; client < this->fds_count; client++) {
83
84                 /* handle session socket closed */
85
86                 if (this->fds[client].revents & (POLLERR | POLLHUP)) {
87
88                         debug("Session Socket %d %p (fd=%d) dead\n",
89                                   client, this->wsi[client], this->fds[client]);
90
91                         libwebsocket_close_and_free_session(this->wsi[client]);
92                         goto nuke_this;
93                 }
94
95                 /* any incoming data ready? */
96
97                 if (!(this->fds[client].revents & POLLIN))
98                         continue;
99
100                 /* broadcast? */
101
102                 if ((unsigned long)this->wsi[client] < LWS_MAX_PROTOCOLS) {
103
104                         /* get the issued broadcast payload from the socket */
105
106                         len = read(this->fds[client].fd,
107                                    buf + LWS_SEND_BUFFER_PRE_PADDING,
108                                    MAX_BROADCAST_PAYLOAD);
109
110                         if (len < 0) {
111                                 fprintf(stderr,
112                                            "Error reading broadcast payload\n");
113                                 continue;
114                         }
115
116                         /* broadcast it to all guys with this protocol index */
117
118                         for (n = this->count_protocols + 1;
119                                                      n < this->fds_count; n++) {
120
121                                 wsi = this->wsi[n];
122
123                                 if ((unsigned long)wsi < LWS_MAX_PROTOCOLS)
124                                         continue;
125
126                                 /*
127                                  * never broadcast to non-established
128                                  * connection
129                                  */
130
131                                 if (wsi->state != WSI_STATE_ESTABLISHED)
132                                         continue;
133
134                                 /* only to clients connected to us */
135                                 
136                                 if (wsi->client_mode)
137                                         continue;
138
139                                 /*
140                                  * only broadcast to connections using
141                                  * the requested protocol
142                                  */
143
144                                 if (wsi->protocol->protocol_index !=
145                                           (int)(unsigned long)this->wsi[client])
146                                         continue;
147
148                                 /* broadcast it to this connection */
149
150                                 wsi->protocol->callback(wsi,
151                                         LWS_CALLBACK_BROADCAST,
152                                         wsi->user_space,
153                                         buf + LWS_SEND_BUFFER_PRE_PADDING, len);
154                         }
155
156                         continue;
157                 }
158
159 #ifdef LWS_OPENSSL_SUPPORT
160                 if (this->use_ssl)
161                         n = SSL_read(this->wsi[client]->ssl, buf, sizeof buf);
162                 else
163 #endif
164                         n = recv(this->fds[client].fd, buf, sizeof buf, 0);
165
166                 if (n < 0) {
167                         fprintf(stderr, "Socket read returned %d\n", n);
168                         continue;
169                 }
170                 if (!n) {
171                         libwebsocket_close_and_free_session(this->wsi[client]);
172                         goto nuke_this;
173                 }
174
175                 /* service incoming data */
176
177                 if (libwebsocket_read(this->wsi[client], buf, n) >= 0)
178                         continue;
179
180                 /*
181                  * it closed and nuked wsi[client], so remove the
182                  * socket handle and wsi from our service list
183                  */
184 nuke_this:
185
186                 debug("nuking wsi %p, fsd_count = %d\n",
187                                         this->wsi[client], this->fds_count - 1);
188
189                 this->fds_count--;
190                 for (n = client; n < this->fds_count; n++) {
191                         this->fds[n] = this->fds[n + 1];
192                         this->wsi[n] = this->wsi[n + 1];
193                 }
194                 break;
195         }
196
197         return 0;
198 }
199
200
201 int
202 libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
203 {
204         int n;
205         int client;
206         unsigned int clilen;
207         struct sockaddr_in cli_addr;
208         int fd;
209
210         /* stay dead once we are dead */
211
212         if (this == NULL)
213                 return 1;
214
215         /* don't check listen socket if we are not listening */
216
217         if (this->listen_port)
218                 n = poll(this->fds, this->fds_count, timeout_ms);
219         else
220                 n = poll(&this->fds[1], this->fds_count - 1, timeout_ms);
221         
222
223         if (n < 0 || this->fds[0].revents & (POLLERR | POLLHUP)) {
224                 fprintf(stderr, "Listen Socket dead\n");
225                 goto fatal;
226         }
227         if (n == 0) /* poll timeout */
228                 return 0;
229
230         /* handle accept on listening socket? */
231
232         for (client = 0; client < this->count_protocols + 1; client++) {
233
234                 if (!this->fds[client].revents & POLLIN)
235                         continue;
236
237                 /* listen socket got an unencrypted connection... */
238
239                 clilen = sizeof(cli_addr);
240                 fd  = accept(this->fds[client].fd,
241                              (struct sockaddr *)&cli_addr, &clilen);
242                 if (fd < 0) {
243                         fprintf(stderr, "ERROR on accept");
244                         continue;
245                 }
246
247                 if (this->fds_count >= MAX_CLIENTS) {
248                         fprintf(stderr, "too busy");
249                         close(fd);
250                         continue;
251                 }
252
253                 if (client) {
254                         /*
255                          * accepting a connection to broadcast socket
256                          * set wsi to be protocol index not pointer
257                          */
258
259                         this->wsi[this->fds_count] =
260                               (struct libwebsocket *)(long)(client - 1);
261
262                         goto fill_in_fds;
263                 }
264
265                 /* accepting connection to main listener */
266
267                 this->wsi[this->fds_count] =
268                                     malloc(sizeof(struct libwebsocket));
269                 if (!this->wsi[this->fds_count]) {
270                         fprintf(stderr, "Out of memory for new connection\n");
271                         continue;
272                 }
273
274 #ifdef LWS_OPENSSL_SUPPORT
275                 if (this->use_ssl) {
276
277                         this->wsi[this->fds_count]->ssl = SSL_new(ssl_ctx);
278                         if (this->wsi[this->fds_count]->ssl == NULL) {
279                                 fprintf(stderr, "SSL_new failed: %s\n",
280                                     ERR_error_string(SSL_get_error(
281                                     this->wsi[this->fds_count]->ssl, 0),
282                                                                  NULL));
283                                 free(this->wsi[this->fds_count]);
284                                 continue;
285                         }
286
287                         SSL_set_fd(this->wsi[this->fds_count]->ssl, fd);
288
289                         n = SSL_accept(this->wsi[this->fds_count]->ssl);
290                         if (n != 1) {
291                                 /*
292                                  * browsers seem to probe with various
293                                  * ssl params which fail then retry
294                                  * and succeed
295                                  */
296                                 debug("SSL_accept failed skt %u: %s\n",
297                                       fd,
298                                       ERR_error_string(SSL_get_error(
299                                       this->wsi[this->fds_count]->ssl,
300                                                              n), NULL));
301                                 SSL_free(
302                                        this->wsi[this->fds_count]->ssl);
303                                 free(this->wsi[this->fds_count]);
304                                 continue;
305                         }
306                         debug("accepted new SSL conn  "
307                               "port %u on fd=%d SSL ver %s\n",
308                                 ntohs(cli_addr.sin_port), fd,
309                                   SSL_get_version(this->wsi[
310                                                 this->fds_count]->ssl));
311
312                 } else
313 #endif
314                         debug("accepted new conn  port %u on fd=%d\n",
315                                           ntohs(cli_addr.sin_port), fd);
316
317                 /* intialize the instance struct */
318
319                 this->wsi[this->fds_count]->sock = fd;
320                 this->wsi[this->fds_count]->state = WSI_STATE_HTTP;
321                 this->wsi[this->fds_count]->name_buffer_pos = 0;
322                 this->wsi[this->fds_count]->client_mode = 0;
323
324                 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
325                         this->wsi[this->fds_count]->
326                                              utf8_token[n].token = NULL;
327                         this->wsi[this->fds_count]->
328                                             utf8_token[n].token_len = 0;
329                 }
330
331                 /*
332                  * these can only be set once the protocol is known
333                  * we set an unestablished connection's protocol pointer
334                  * to the start of the supported list, so it can look
335                  * for matching ones during the handshake
336                  */
337                 this->wsi[this->fds_count]->protocol = this->protocols;
338                 this->wsi[this->fds_count]->user_space = NULL;
339
340                 /*
341                  * Default protocol is 76 / 00
342                  * After 76, there's a header specified to inform which
343                  * draft the client wants, when that's seen we modify
344                  * the individual connection's spec revision accordingly
345                  */
346                 this->wsi[this->fds_count]->ietf_spec_revision = 0;
347
348 fill_in_fds:
349
350                 /*
351                  * make sure NO events are seen yet on this new socket
352                  * (otherwise we inherit old fds[client].revents from
353                  * previous socket there and die mysteriously! )
354                  */
355                 this->fds[this->fds_count].revents = 0;
356
357                 this->fds[this->fds_count].events = POLLIN;
358                 this->fds[this->fds_count++].fd = fd;
359
360         }
361
362         /* service anything incoming on websocket connection */
363
364         libwebsocket_poll_connections(this);
365
366         /* this round is done */
367
368         return 0;
369
370 fatal:
371
372         /* close listening skt and per-protocol broadcast sockets */
373         for (client = 0; client < this->fds_count; client++)
374                 close(this->fds[0].fd);
375
376 #ifdef LWS_OPENSSL_SUPPORT
377         SSL_CTX_free(ssl_ctx);
378 #endif
379         kill(0, SIGTERM);
380
381         if (this)
382                 free(this);
383
384         this = NULL;
385
386         /* inform caller we are dead */
387
388         return 1;
389 }
390
391
392 /**
393  * libwebsocket_create_context() - Create the websocket handler
394  * @port:       Port to listen on... you can use 0 to suppress listening on
395  *              any port, that's what you want if you are not running a
396  *              websocket server at all but just using it as a client
397  * @protocols:  Array of structures listing supported protocols and a protocol-
398  *              specific callback for each one.  The list is ended with an
399  *              entry that has a NULL callback pointer.
400  *              It's not const because we write the owning_server member
401  * @ssl_cert_filepath:  If libwebsockets was compiled to use ssl, and you want
402  *                      to listen using SSL, set to the filepath to fetch the
403  *                      server cert from, otherwise NULL for unencrypted
404  * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
405  *                      else ignored
406  * @gid:        group id to change to after setting listen socket, or -1.
407  * @uid:        user id to change to after setting listen socket, or -1.
408  *
409  *      This function creates the listening socket and takes care
410  *      of all initialization in one step.
411  *
412  *      After initialization, it returns a struct libwebsocket_context * that
413  *      represents this server.  After calling, user code needs to take care
414  *      of calling libwebsocket_service() with the context pointer to get the
415  *      server's sockets serviced.  This can be done in the same process context
416  *      or a forked process, or another thread,
417  *
418  *      The protocol callback functions are called for a handful of events
419  *      including http requests coming in, websocket connections becoming
420  *      established, and data arriving; it's also called periodically to allow
421  *      async transmission.
422  *
423  *      HTTP requests are sent always to the FIRST protocol in @protocol, since
424  *      at that time websocket protocol has not been negotiated.  Other
425  *      protocols after the first one never see any HTTP callack activity.
426  *
427  *      The server created is a simple http server by default; part of the
428  *      websocket standard is upgrading this http connection to a websocket one.
429  *
430  *      This allows the same server to provide files like scripts and favicon /
431  *      images or whatever over http and dynamic data over websockets all in
432  *      one place; they're all handled in the user callback.
433  */
434
435 struct libwebsocket_context *
436 libwebsocket_create_context(int port,
437                                struct libwebsocket_protocols *protocols,
438                                const char *ssl_cert_filepath,
439                                const char *ssl_private_key_filepath,
440                                int gid, int uid)
441 {
442         int n;
443         int sockfd = 0;
444         int fd;
445         struct sockaddr_in serv_addr, cli_addr;
446         int opt = 1;
447         struct libwebsocket_context *this = NULL;
448         unsigned int slen;
449
450 #ifdef LWS_OPENSSL_SUPPORT
451         SSL_METHOD *method;
452         char ssl_err_buf[512];
453
454         use_ssl = ssl_cert_filepath != NULL && ssl_private_key_filepath != NULL;
455         if (use_ssl)
456                 fprintf(stderr, " Compiled with SSL support, using it\n");
457         else
458                 fprintf(stderr, " Compiled with SSL support, not using it\n");
459
460 #else
461         if (ssl_cert_filepath != NULL && ssl_private_key_filepath != NULL) {
462                 fprintf(stderr, " Not compiled for OpenSSl support!\n");
463                 return NULL;
464         }
465         fprintf(stderr, " Compiled without SSL support, serving unencrypted\n");
466 #endif
467
468 #ifdef LWS_OPENSSL_SUPPORT
469         if (use_ssl) {
470                 SSL_library_init();
471
472                 OpenSSL_add_all_algorithms();
473                 SSL_load_error_strings();
474
475                 /*
476                  * Firefox insists on SSLv23 not SSLv3
477                  * Konq disables SSLv2 by default now, SSLv23 works
478                  */
479
480                 method = (SSL_METHOD *)SSLv23_server_method();
481                 if (!method) {
482                         fprintf(stderr, "problem creating ssl method: %s\n",
483                                 ERR_error_string(ERR_get_error(), ssl_err_buf));
484                         return NULL;
485                 }
486                 ssl_ctx = SSL_CTX_new(method);  /* create context */
487                 if (!ssl_ctx) {
488                         printf("problem creating ssl context: %s\n",
489                                 ERR_error_string(ERR_get_error(), ssl_err_buf));
490                         return NULL;
491                 }
492                 /* set the local certificate from CertFile */
493                 n = SSL_CTX_use_certificate_file(ssl_ctx,
494                                         ssl_cert_filepath, SSL_FILETYPE_PEM);
495                 if (n != 1) {
496                         fprintf(stderr, "problem getting cert '%s': %s\n",
497                                 ssl_cert_filepath,
498                                 ERR_error_string(ERR_get_error(), ssl_err_buf));
499                         return NULL;
500                 }
501                 /* set the private key from KeyFile */
502                 if (SSL_CTX_use_PrivateKey_file(ssl_ctx,
503                                                 ssl_private_key_filepath,
504                                                        SSL_FILETYPE_PEM) != 1) {
505                         fprintf(stderr, "ssl problem getting key '%s': %s\n",
506                                                 ssl_private_key_filepath,
507                                 ERR_error_string(ERR_get_error(), ssl_err_buf));
508                         return NULL;
509                 }
510                 /* verify private key */
511                 if (!SSL_CTX_check_private_key(ssl_ctx)) {
512                         fprintf(stderr, "Private SSL key doesn't match cert\n");
513                         return NULL;
514                 }
515
516                 /* SSL is happy and has a cert it's content with */
517         }
518 #endif
519
520         /* selftest */
521
522         if (lws_b64_selftest())
523                 return NULL;
524
525
526         this = malloc(sizeof(struct libwebsocket_context));
527
528         this->protocols = protocols;
529         this->listen_port = port;
530
531         /* set up our external listening socket we serve on */
532
533         if (port) {
534
535                 sockfd = socket(AF_INET, SOCK_STREAM, 0);
536                 if (sockfd < 0) {
537                         fprintf(stderr, "ERROR opening socket");
538                         return NULL;
539                 }
540
541                 /* allow us to restart even if old sockets in TIME_WAIT */
542                 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
543
544                 bzero((char *) &serv_addr, sizeof(serv_addr));
545                 serv_addr.sin_family = AF_INET;
546                 serv_addr.sin_addr.s_addr = INADDR_ANY;
547                 serv_addr.sin_port = htons(port);
548
549                 n = bind(sockfd, (struct sockaddr *) &serv_addr,
550                                                              sizeof(serv_addr));
551                 if (n < 0) {
552                         fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
553                                                                 port, n, errno);
554                         return NULL;
555                 }
556         }
557
558         /* drop any root privs for this process */
559
560         if (gid != -1)
561                 if (setgid(gid))
562                         fprintf(stderr, "setgid: %s\n", strerror(errno));
563         if (uid != -1)
564                 if (setuid(uid))
565                         fprintf(stderr, "setuid: %s\n", strerror(errno));
566
567         /*
568          * prepare the poll() fd array... it's like this
569          *
570          * [0] = external listening socket
571          * [1 .. this->count_protocols] = per-protocol broadcast sockets
572          * [this->count_protocols + 1 ... this->fds_count-1] = connection skts
573          */
574
575         this->fds_count = 1;
576         this->fds[0].fd = sockfd;
577         this->fds[0].events = POLLIN;
578         this->count_protocols = 0;
579 #ifdef LWS_OPENSSL_SUPPORT
580         this->use_ssl = use_ssl;
581 #endif
582
583         if (port) {
584                 listen(sockfd, 5);
585                 fprintf(stderr, " Listening on port %d\n", port);
586         }
587
588         /* set up our internal broadcast trigger sockets per-protocol */
589
590         for (; protocols[this->count_protocols].callback;
591                                                       this->count_protocols++) {
592                 protocols[this->count_protocols].owning_server = this;
593                 protocols[this->count_protocols].protocol_index =
594                                                           this->count_protocols;
595
596                 fd = socket(AF_INET, SOCK_STREAM, 0);
597                 if (fd < 0) {
598                         fprintf(stderr, "ERROR opening socket");
599                         return NULL;
600                 }
601
602                 /* allow us to restart even if old sockets in TIME_WAIT */
603                 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
604
605                 bzero((char *) &serv_addr, sizeof(serv_addr));
606                 serv_addr.sin_family = AF_INET;
607                 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
608                 serv_addr.sin_port = 0; /* pick the port for us */
609
610                 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
611                 if (n < 0) {
612                         fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
613                                                                 port, n, errno);
614                         return NULL;
615                 }
616
617                 slen = sizeof cli_addr;
618                 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
619                 if (n < 0) {
620                         fprintf(stderr, "getsockname failed\n");
621                         return NULL;
622                 }
623                 protocols[this->count_protocols].broadcast_socket_port =
624                                                        ntohs(cli_addr.sin_port);
625                 listen(fd, 5);
626
627                 debug("  Protocol %s broadcast socket %d\n",
628                                 protocols[this->count_protocols].name,
629                                                       ntohs(cli_addr.sin_port));
630
631                 this->fds[this->fds_count].fd = fd;
632                 this->fds[this->fds_count].events = POLLIN;
633                 /* wsi only exists for connections, not broadcast listener */
634                 this->wsi[this->fds_count] = NULL;
635                 this->fds_count++;
636         }
637
638         return this;
639 }
640
641
642 #ifndef LWS_NO_FORK
643
644 /**
645  * libwebsockets_fork_service_loop() - Optional helper function forks off
646  *                                a process for the websocket server loop.
647  *                              You don't have to use this but if not, you
648  *                              have to make sure you are calling
649  *                              libwebsocket_service periodically to service
650  *                              the websocket traffic
651  * @this:       server context returned by creation function
652  */
653
654 int
655 libwebsockets_fork_service_loop(struct libwebsocket_context *this)
656 {
657         int client;
658         int fd;
659         struct sockaddr_in cli_addr;
660         int n;
661
662         n = fork();
663         if (n < 0)
664                 return n;
665
666         if (!n) {
667
668                 /* main process context */
669
670                 for (client = 1; client < this->count_protocols + 1; client++) {
671                         fd = socket(AF_INET, SOCK_STREAM, 0);
672                         if (fd < 0) {
673                                 fprintf(stderr, "Unable to create socket\n");
674                                 return -1;
675                         }
676                         cli_addr.sin_family = AF_INET;
677                         cli_addr.sin_port = htons(
678                              this->protocols[client - 1].broadcast_socket_port);
679                         cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
680                         n = connect(fd, (struct sockaddr *)&cli_addr,
681                                                                sizeof cli_addr);
682                         if (n < 0) {
683                                 fprintf(stderr, "Unable to connect to "
684                                                 "broadcast socket %d, %s\n",
685                                                 client, strerror(errno));
686                                 return -1;
687                         }
688
689                         this->protocols[client - 1].broadcast_socket_user_fd =
690                                                                              fd;
691                 }
692
693
694                 return 0;
695         }
696
697         /* we want a SIGHUP when our parent goes down */
698         prctl(PR_SET_PDEATHSIG, SIGHUP);
699
700         /* in this forked process, sit and service websocket connections */
701
702         while (1)
703                 if (libwebsocket_service(this, 1000))
704                         return -1;
705
706         return 0;
707 }
708
709 #endif
710
711 /**
712  * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
713  *                                connection.
714  * @wsi:        pointer to struct websocket you want to know the protocol of
715  *
716  *
717  *      This is useful to get the protocol to broadcast back to from inside
718  * the callback.
719  */
720
721 const struct libwebsocket_protocols *
722 libwebsockets_get_protocol(struct libwebsocket *wsi)
723 {
724         return wsi->protocol;
725 }
726
727 /**
728  * libwebsockets_broadcast() - Sends a buffer to the callback for all active
729  *                                connections of the given protocol.
730  * @protocol:   pointer to the protocol you will broadcast to all members of
731  * @buf:  buffer containing the data to be broadcase.  NOTE: this has to be
732  *              allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
733  *              the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
734  *              case you are calling this function from callback context.
735  * @len:        length of payload data in buf, starting from buf.
736  *
737  *      This function allows bulk sending of a packet to every connection using
738  * the given protocol.  It does not send the data directly; instead it calls
739  * the callback with a reason type of LWS_CALLBACK_BROADCAST.  If the callback
740  * wants to actually send the data for that connection, the callback itself
741  * should call libwebsocket_write().
742  *
743  * libwebsockets_broadcast() can be called from another fork context without
744  * having to take any care about data visibility between the processes, it'll
745  * "just work".
746  */
747
748
749 int
750 libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
751                                                  unsigned char *buf, size_t len)
752 {
753         struct libwebsocket_context *this = protocol->owning_server;
754         int n;
755
756         if (!protocol->broadcast_socket_user_fd) {
757                 /*
758                  * We are either running unforked / flat, or we are being
759                  * called from poll thread context
760                  * eg, from a callback.  In that case don't use sockets for
761                  * broadcast IPC (since we can't open a socket connection to
762                  * a socket listening on our own thread) but directly do the
763                  * send action.
764                  *
765                  * Locking is not needed because we are by definition being
766                  * called in the poll thread context and are serialized.
767                  */
768
769                 for (n = this->count_protocols + 1; n < this->fds_count; n++) {
770
771                         if ((unsigned long)this->wsi[n] < LWS_MAX_PROTOCOLS)
772                                 continue;
773
774                         /* never broadcast to non-established connection */
775                         if (this->wsi[n]->state != WSI_STATE_ESTABLISHED)
776                                 continue;
777
778                         /* only broadcast to guys using requested protocol */
779                         if (this->wsi[n]->protocol != protocol)
780                                 continue;
781
782                         this->wsi[n]->protocol->callback(this->wsi[n],
783                                          LWS_CALLBACK_BROADCAST,
784                                          this->wsi[n]->user_space,
785                                          buf, len);
786                 }
787
788                 return 0;
789         }
790
791         /*
792          * We're being called from a different process context than the server
793          * loop.  Instead of broadcasting directly, we send our
794          * payload on a socket to do the IPC; the server process will serialize
795          * the broadcast action in its main poll() loop.
796          *
797          * There's one broadcast socket listening for each protocol supported
798          * set up when the websocket server initializes
799          */
800
801         n = send(protocol->broadcast_socket_user_fd, buf, len, 0);
802
803         return n;
804 }