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