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