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