blob: ec1e482f9a22942d0205437b497097fd406a0914 [file] [log] [blame]
Andy Green05a0a7b2010-10-31 17:51:39 +00001/*
Andy Greena0da8a82010-11-08 17:12:19 +00002 * libwebsockets - small server side websockets and web server implementation
Andy Green8f037e42010-12-19 22:13:26 +00003 *
Andy Greena0da8a82010-11-08 17:12:19 +00004 * 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
Andy Green05a0a7b2010-10-31 17:51:39 +000020 */
21
Andy Green7c212cc2010-11-08 20:20:42 +000022#include "private-libwebsockets.h"
Andy Greenff95d7a2010-10-28 22:36:01 +010023
Andy Green0d338332011-02-12 11:57:43 +000024/* file descriptor hash management */
25
26struct libwebsocket *
27wsi_from_fd(struct libwebsocket_context *this, int fd)
28{
29 int h = LWS_FD_HASH(fd);
30 int n = 0;
31
32 for (n = 0; n < this->fd_hashtable[h].length; n++)
33 if (this->fd_hashtable[h].wsi[n]->sock == fd)
34 return this->fd_hashtable[h].wsi[n];
35
36 return NULL;
37}
38
39int
40insert_wsi(struct libwebsocket_context *this, struct libwebsocket *wsi)
41{
42 int h = LWS_FD_HASH(wsi->sock);
43
44 if (this->fd_hashtable[h].length == MAX_CLIENTS - 1) {
45 fprintf(stderr, "hash table overflow\n");
46 return 1;
47 }
48
49 this->fd_hashtable[h].wsi[this->fd_hashtable[h].length++] = wsi;
50
51 return 0;
52}
53
54int
55delete_from_fd(struct libwebsocket_context *this, int fd)
56{
57 int h = LWS_FD_HASH(fd);
58 int n = 0;
59
60 for (n = 0; n < this->fd_hashtable[h].length; n++)
61 if (this->fd_hashtable[h].wsi[n]->sock == fd) {
62 while (n < this->fd_hashtable[h].length) {
63 this->fd_hashtable[h].wsi[n] =
64 this->fd_hashtable[h].wsi[n + 1];
65 n++;
66 }
67 this->fd_hashtable[h].length--;
68
69 return 0;
70 }
71
72 fprintf(stderr, "Failed to find fd %d requested for "
73 "delete in hashtable\n", fd);
74 return 1;
75}
76
77
Andy Green8f037e42010-12-19 22:13:26 +000078void
Andy Green4b6fbe12011-02-14 08:03:48 +000079libwebsocket_close_and_free_session(struct libwebsocket_context *this,
80 struct libwebsocket *wsi)
Andy Green251f6fa2010-11-03 11:13:06 +000081{
Andy Greenb45993c2010-12-18 15:13:50 +000082 int n;
Andy Green62c54d22011-02-14 09:14:25 +000083 int old_state;
Andy Green5e1fa172011-02-10 09:07:05 +000084 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
85 LWS_SEND_BUFFER_POST_PADDING];
Andy Greenb45993c2010-12-18 15:13:50 +000086
Andy Green4b6fbe12011-02-14 08:03:48 +000087 if (!wsi)
Andy Greenb45993c2010-12-18 15:13:50 +000088 return;
89
Andy Green62c54d22011-02-14 09:14:25 +000090 old_state = wsi->state;
Andy Green251f6fa2010-11-03 11:13:06 +000091
Andy Green62c54d22011-02-14 09:14:25 +000092 if (old_state == WSI_STATE_DEAD_SOCKET)
Andy Green5e1fa172011-02-10 09:07:05 +000093 return;
94
Andy Green4b6fbe12011-02-14 08:03:48 +000095 /* remove this fd from wsi mapping hashtable */
96
97 delete_from_fd(this, wsi->sock);
98
99 /* delete it from the internal poll list if still present */
100
101 for (n = 0; n < this->fds_count; n++) {
102 if (this->fds[n].fd != wsi->sock)
103 continue;
104 while (n < this->fds_count - 1) {
105 this->fds[n] = this->fds[n + 1];
106 n++;
107 }
108 this->fds_count--;
109 /* we only have to deal with one */
110 n = this->fds_count;
111 }
112
113 /* remove also from external POLL support via protocol 0 */
114
Andy Green62c54d22011-02-14 09:14:25 +0000115 this->protocols[0].callback(this, wsi,
Andy Green4b6fbe12011-02-14 08:03:48 +0000116 LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
117
Andy Green5e1fa172011-02-10 09:07:05 +0000118 /*
119 * signal we are closing, libsocket_write will
120 * add any necessary version-specific stuff. If the write fails,
121 * no worries we are closing anyway. If we didn't initiate this
122 * close, then our state has been changed to
Andy Green4b6fbe12011-02-14 08:03:48 +0000123 * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this
Andy Green5e1fa172011-02-10 09:07:05 +0000124 */
125
Andy Green62c54d22011-02-14 09:14:25 +0000126 if (old_state == WSI_STATE_ESTABLISHED)
Andy Green5e1fa172011-02-10 09:07:05 +0000127 libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 0,
128 LWS_WRITE_CLOSE);
129
Andy Green251f6fa2010-11-03 11:13:06 +0000130 wsi->state = WSI_STATE_DEAD_SOCKET;
131
Andy Green4b6fbe12011-02-14 08:03:48 +0000132 /* tell the user it's all over for this guy */
133
Andy Green62c54d22011-02-14 09:14:25 +0000134 if (wsi->protocol->callback && old_state == WSI_STATE_ESTABLISHED)
135 wsi->protocol->callback(this, wsi, LWS_CALLBACK_CLOSED,
Andy Greene77ddd82010-11-13 10:03:47 +0000136 wsi->user_space, NULL, 0);
Andy Green251f6fa2010-11-03 11:13:06 +0000137
Andy Green4b6fbe12011-02-14 08:03:48 +0000138 /* free up his allocations */
139
Andy Green251f6fa2010-11-03 11:13:06 +0000140 for (n = 0; n < WSI_TOKEN_COUNT; n++)
141 if (wsi->utf8_token[n].token)
142 free(wsi->utf8_token[n].token);
143
Andy Green0ca6a172010-12-19 20:50:01 +0000144/* fprintf(stderr, "closing fd=%d\n", wsi->sock); */
Andy Green251f6fa2010-11-03 11:13:06 +0000145
Andy Green3faa9c72010-11-08 17:03:03 +0000146#ifdef LWS_OPENSSL_SUPPORT
Andy Green90c7cbc2011-01-27 06:26:52 +0000147 if (wsi->ssl) {
Andy Green3faa9c72010-11-08 17:03:03 +0000148 n = SSL_get_fd(wsi->ssl);
149 SSL_shutdown(wsi->ssl);
150 close(n);
151 SSL_free(wsi->ssl);
152 } else {
153#endif
154 shutdown(wsi->sock, SHUT_RDWR);
155 close(wsi->sock);
156#ifdef LWS_OPENSSL_SUPPORT
157 }
158#endif
Andy Green4f3943a2010-11-12 10:44:16 +0000159 if (wsi->user_space)
160 free(wsi->user_space);
161
Andy Green251f6fa2010-11-03 11:13:06 +0000162 free(wsi);
163}
164
Andy Green07034092011-02-13 08:37:12 +0000165/**
Andy Greenf7ee5492011-02-13 09:04:21 +0000166 * libwebsockets_hangup_on_client() - Server calls to terminate client
167 * connection
168 * @this: libwebsockets context
169 * @fd: Connection socket descriptor
170 */
171
172void
173libwebsockets_hangup_on_client(struct libwebsocket_context *this, int fd)
174{
175 struct libwebsocket *wsi = wsi_from_fd(this, fd);
Andy Greende6ab322011-02-13 09:15:10 +0000176 int n;
Andy Greenf7ee5492011-02-13 09:04:21 +0000177
178 if (wsi == NULL)
179 return;
180
Andy Greende6ab322011-02-13 09:15:10 +0000181 delete_from_fd(this, fd);
182
183 for (n = 0; n < this->fds_count - 1; n++)
184 if (this->fds[n].fd == fd) {
185 while (n < this->fds_count - 1) {
186 this->fds[n] = this->fds[n + 1];
187 n++;
188 }
189 n = this->fds_count;
190 this->fds_count--;
191 }
192
Andy Green4b6fbe12011-02-14 08:03:48 +0000193 libwebsocket_close_and_free_session(this, wsi);
Andy Greenf7ee5492011-02-13 09:04:21 +0000194}
195
196
197/**
Andy Green07034092011-02-13 08:37:12 +0000198 * libwebsockets_get_peer_addresses() - Get client address information
199 * @fd: Connection socket descriptor
200 * @name: Buffer to take client address name
201 * @name_len: Length of client address name buffer
202 * @rip: Buffer to take client address IP qotted quad
203 * @rip_len: Length of client address IP buffer
204 *
205 * This function fills in @name and @rip with the name and IP of
206 * the client connected with socket descriptor @fd. Names may be
207 * truncated if there is not enough room. If either cannot be
208 * determined, they will be returned as valid zero-length strings.
209 */
210
211void
212libwebsockets_get_peer_addresses(int fd, char *name, int name_len,
213 char *rip, int rip_len)
214{
215 unsigned int len;
216 struct sockaddr_in sin;
217 struct hostent *host;
218 struct hostent *host1;
219 char ip[128];
220 char *p;
221 int n;
222
223 rip[0] = '\0';
224 name[0] = '\0';
225
226 len = sizeof sin;
227 if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
228 perror("getpeername");
229 return;
230 }
231
232 host = gethostbyaddr((char *) &sin.sin_addr, sizeof sin.sin_addr,
233 AF_INET);
234 if (host == NULL) {
235 perror("gethostbyaddr");
236 return;
237 }
238
239 strncpy(name, host->h_name, name_len);
240 name[name_len - 1] = '\0';
241
242 host1 = gethostbyname(host->h_name);
243 if (host1 == NULL)
244 return;
245 p = (char *)host1;
246 n = 0;
247 while (p != NULL) {
248 p = host1->h_addr_list[n++];
249 if (p == NULL)
250 continue;
251 if (host1->h_addrtype != AF_INET)
252 continue;
253
254 sprintf(ip, "%d.%d.%d.%d",
255 p[0], p[1], p[2], p[3]);
256 p = NULL;
257 strncpy(rip, ip, rip_len);
258 rip[rip_len - 1] = '\0';
259 }
260}
Andy Green9f990342011-02-12 11:57:45 +0000261
262/**
263 * libwebsocket_service_fd() - Service polled socket with something waiting
264 * @this: Websocket context
265 * @pollfd: The pollfd entry describing the socket fd and which events
266 * happened.
267 *
268 * This function closes any active connections and then frees the
269 * context. After calling this, any further use of the context is
270 * undefined.
271 */
272
273int
Andy Green0d338332011-02-12 11:57:43 +0000274libwebsocket_service_fd(struct libwebsocket_context *this,
275 struct pollfd *pollfd)
Andy Greenb45993c2010-12-18 15:13:50 +0000276{
277 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_BROADCAST_PAYLOAD +
278 LWS_SEND_BUFFER_POST_PADDING];
Andy Green0d338332011-02-12 11:57:43 +0000279 struct libwebsocket *wsi = wsi_from_fd(this, pollfd->fd);
280 struct libwebsocket *new_wsi;
Andy Greenb45993c2010-12-18 15:13:50 +0000281 int n;
Andy Green0d338332011-02-12 11:57:43 +0000282 int m;
Andy Greenb45993c2010-12-18 15:13:50 +0000283 size_t len;
Andy Green0d338332011-02-12 11:57:43 +0000284 int accept_fd;
285 unsigned int clilen;
286 struct sockaddr_in cli_addr;
Andy Greenb45993c2010-12-18 15:13:50 +0000287
Andy Green0d338332011-02-12 11:57:43 +0000288 if (wsi == NULL)
289 return 1;
Andy Green8f037e42010-12-19 22:13:26 +0000290
Andy Green0d338332011-02-12 11:57:43 +0000291 switch (wsi->mode) {
292 case LWS_CONNMODE_SERVER_LISTENER:
293
294 /* pollin means a client has connected to us then */
295
296 if (!pollfd->revents & POLLIN)
297 break;
298
299 /* listen socket got an unencrypted connection... */
300
301 clilen = sizeof(cli_addr);
302 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
303 &clilen);
304 if (accept_fd < 0) {
305 fprintf(stderr, "ERROR on accept");
306 break;
307 }
308
309 if (this->fds_count >= MAX_CLIENTS) {
Andy Green3221f922011-02-12 13:14:11 +0000310 fprintf(stderr, "too busy to accept new client\n");
Andy Green0d338332011-02-12 11:57:43 +0000311 close(accept_fd);
312 break;
313 }
314
Andy Green07034092011-02-13 08:37:12 +0000315 /*
316 * look at who we connected to and give user code a chance
317 * to reject based on client IP. There's no protocol selected
318 * yet so we issue this to protocols[0]
319 */
320
Andy Green62c54d22011-02-14 09:14:25 +0000321 if ((this->protocols[0].callback)(this, wsi,
Andy Green07034092011-02-13 08:37:12 +0000322 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
323 (void*)(long)accept_fd, NULL, 0)) {
324 fprintf(stderr, "Callback denied network connection\n");
325 close(accept_fd);
326 break;
327 }
328
Andy Green0d338332011-02-12 11:57:43 +0000329 /* accepting connection to main listener */
330
331 new_wsi = malloc(sizeof(struct libwebsocket));
332 if (new_wsi == NULL) {
333 fprintf(stderr, "Out of memory for new connection\n");
334 break;
335 }
336
337 memset(new_wsi, 0, sizeof (struct libwebsocket));
338 new_wsi->sock = accept_fd;
339
340#ifdef LWS_OPENSSL_SUPPORT
341 new_wsi->ssl = NULL;
342 this->ssl_ctx = NULL;
343
344 if (this->use_ssl) {
345
346 new_wsi->ssl = SSL_new(this->ssl_ctx);
347 if (new_wsi->ssl == NULL) {
348 fprintf(stderr, "SSL_new failed: %s\n",
349 ERR_error_string(SSL_get_error(
350 new_wsi->ssl, 0), NULL));
351 free(new_wsi);
352 break;
353 }
354
355 SSL_set_fd(new_wsi->ssl, accept_fd);
356
357 n = SSL_accept(new_wsi->ssl);
358 if (n != 1) {
359 /*
360 * browsers seem to probe with various
361 * ssl params which fail then retry
362 * and succeed
363 */
364 debug("SSL_accept failed skt %u: %s\n",
365 pollfd->fd,
366 ERR_error_string(SSL_get_error(
367 new_wsi->ssl, n), NULL));
368 SSL_free(
369 new_wsi->ssl);
370 free(new_wsi);
371 break;
372 }
373 debug("accepted new SSL conn "
374 "port %u on fd=%d SSL ver %s\n",
375 ntohs(cli_addr.sin_port), accept_fd,
376 SSL_get_version(new_wsi->ssl));
377
378 } else
379#endif
380 debug("accepted new conn port %u on fd=%d\n",
381 ntohs(cli_addr.sin_port), accept_fd);
382
383 /* intialize the instance struct */
384
385 new_wsi->state = WSI_STATE_HTTP;
386 new_wsi->name_buffer_pos = 0;
387 new_wsi->mode = LWS_CONNMODE_WS_SERVING;
388
389 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
390 new_wsi->utf8_token[n].token = NULL;
391 new_wsi->utf8_token[n].token_len = 0;
392 }
393
394 /*
395 * these can only be set once the protocol is known
396 * we set an unestablished connection's protocol pointer
397 * to the start of the supported list, so it can look
398 * for matching ones during the handshake
399 */
400 new_wsi->protocol = this->protocols;
401 new_wsi->user_space = NULL;
402
403 /*
404 * Default protocol is 76 / 00
405 * After 76, there's a header specified to inform which
406 * draft the client wants, when that's seen we modify
407 * the individual connection's spec revision accordingly
408 */
409 new_wsi->ietf_spec_revision = 0;
410
411 insert_wsi(this, new_wsi);
412
Andy Green0d338332011-02-12 11:57:43 +0000413 /*
414 * make sure NO events are seen yet on this new socket
415 * (otherwise we inherit old fds[client].revents from
416 * previous socket there and die mysteriously! )
417 */
418 this->fds[this->fds_count].revents = 0;
419
420 this->fds[this->fds_count].events = POLLIN;
421 this->fds[this->fds_count++].fd = accept_fd;
422
Andy Green3221f922011-02-12 13:14:11 +0000423 /* external POLL support via protocol 0 */
Andy Green62c54d22011-02-14 09:14:25 +0000424 this->protocols[0].callback(this, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +0000425 LWS_CALLBACK_ADD_POLL_FD,
426 (void *)(long)accept_fd, NULL, POLLIN);
427
Andy Green0d338332011-02-12 11:57:43 +0000428 break;
429
430 case LWS_CONNMODE_BROADCAST_PROXY_LISTENER:
431
432 /* as we are listening, POLLIN means accept() is needed */
433
434 if (!pollfd->revents & POLLIN)
435 break;
436
437 /* listen socket got an unencrypted connection... */
438
439 clilen = sizeof(cli_addr);
440 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
441 &clilen);
442 if (accept_fd < 0) {
443 fprintf(stderr, "ERROR on accept");
444 break;
445 }
446
447 if (this->fds_count >= MAX_CLIENTS) {
Andy Green3221f922011-02-12 13:14:11 +0000448 fprintf(stderr, "too busy to accept new broadcast "
449 "proxy client\n");
Andy Green0d338332011-02-12 11:57:43 +0000450 close(accept_fd);
451 break;
452 }
453
454 /* create a dummy wsi for the connection and add it */
455
456 new_wsi = malloc(sizeof(struct libwebsocket));
457 memset(new_wsi, 0, sizeof (struct libwebsocket));
458 new_wsi->sock = accept_fd;
459 new_wsi->mode = LWS_CONNMODE_BROADCAST_PROXY;
460 new_wsi->state = WSI_STATE_ESTABLISHED;
461 /* note which protocol we are proxying */
462 new_wsi->protocol_index_for_broadcast_proxy =
463 wsi->protocol_index_for_broadcast_proxy;
464 insert_wsi(this, new_wsi);
465
466 /* add connected socket to internal poll array */
467
468 this->fds[this->fds_count].revents = 0;
469 this->fds[this->fds_count].events = POLLIN;
470 this->fds[this->fds_count++].fd = accept_fd;
471
Andy Green3221f922011-02-12 13:14:11 +0000472 /* external POLL support via protocol 0 */
Andy Green62c54d22011-02-14 09:14:25 +0000473 this->protocols[0].callback(this, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +0000474 LWS_CALLBACK_ADD_POLL_FD,
475 (void *)(long)accept_fd, NULL, POLLIN);
476
Andy Green0d338332011-02-12 11:57:43 +0000477 break;
478
479 case LWS_CONNMODE_BROADCAST_PROXY:
Andy Green8f037e42010-12-19 22:13:26 +0000480
Andy Greenb45993c2010-12-18 15:13:50 +0000481 /* handle session socket closed */
Andy Green8f037e42010-12-19 22:13:26 +0000482
Andy Green0d338332011-02-12 11:57:43 +0000483 if (pollfd->revents & (POLLERR | POLLHUP)) {
Andy Green8f037e42010-12-19 22:13:26 +0000484
Andy Green0d338332011-02-12 11:57:43 +0000485 debug("Session Socket %p (fd=%d) dead\n",
486 (void *)wsi, accept_fd);
Andy Greenb45993c2010-12-18 15:13:50 +0000487
Andy Green4b6fbe12011-02-14 08:03:48 +0000488 libwebsocket_close_and_free_session(this, wsi);
489 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +0000490 }
Andy Green8f037e42010-12-19 22:13:26 +0000491
Andy Green90c7cbc2011-01-27 06:26:52 +0000492 /* the guy requested a callback when it was OK to write */
493
Andy Green0d338332011-02-12 11:57:43 +0000494 if (pollfd->revents & POLLOUT) {
Andy Green90c7cbc2011-01-27 06:26:52 +0000495
Andy Green0d338332011-02-12 11:57:43 +0000496 /* one shot */
Andy Green90c7cbc2011-01-27 06:26:52 +0000497
Andy Green0d338332011-02-12 11:57:43 +0000498 pollfd->events &= ~POLLOUT;
499
Andy Green3221f922011-02-12 13:14:11 +0000500 /* external POLL support via protocol 0 */
Andy Green62c54d22011-02-14 09:14:25 +0000501 this->protocols[0].callback(this, wsi,
Andy Green3221f922011-02-12 13:14:11 +0000502 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
503 (void *)(long)wsi->sock, NULL, POLLOUT);
504
Andy Green62c54d22011-02-14 09:14:25 +0000505 wsi->protocol->callback(this, wsi,
Andy Green90c7cbc2011-01-27 06:26:52 +0000506 LWS_CALLBACK_CLIENT_WRITEABLE,
Andy Green0d338332011-02-12 11:57:43 +0000507 wsi->user_space,
Andy Green90c7cbc2011-01-27 06:26:52 +0000508 NULL, 0);
509 }
510
Andy Greenb45993c2010-12-18 15:13:50 +0000511 /* any incoming data ready? */
512
Andy Green0d338332011-02-12 11:57:43 +0000513 if (!(pollfd->revents & POLLIN))
514 break;
Andy Greenb45993c2010-12-18 15:13:50 +0000515
Andy Green0d338332011-02-12 11:57:43 +0000516 /* get the issued broadcast payload from the socket */
Andy Greenb45993c2010-12-18 15:13:50 +0000517
Andy Green0d338332011-02-12 11:57:43 +0000518 len = read(pollfd->fd, buf + LWS_SEND_BUFFER_PRE_PADDING,
519 MAX_BROADCAST_PAYLOAD);
520 if (len < 0) {
521 fprintf(stderr, "Error reading broadcast payload\n");
Andy Green4b6fbe12011-02-14 08:03:48 +0000522 break;
Andy Green0d338332011-02-12 11:57:43 +0000523 }
Andy Greenb45993c2010-12-18 15:13:50 +0000524
Andy Green0d338332011-02-12 11:57:43 +0000525 /* broadcast it to all guys with this protocol index */
Andy Green8f037e42010-12-19 22:13:26 +0000526
Andy Green0d338332011-02-12 11:57:43 +0000527 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Green8f037e42010-12-19 22:13:26 +0000528
Andy Green0d338332011-02-12 11:57:43 +0000529 for (m = 0; m < this->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +0000530
Andy Green0d338332011-02-12 11:57:43 +0000531 new_wsi = this->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +0000532
Andy Green0d338332011-02-12 11:57:43 +0000533 /* only to clients we are serving to */
Andy Greenb45993c2010-12-18 15:13:50 +0000534
Andy Green0d338332011-02-12 11:57:43 +0000535 if (new_wsi->mode != LWS_CONNMODE_WS_SERVING)
Andy Greenb45993c2010-12-18 15:13:50 +0000536 continue;
537
538 /*
539 * never broadcast to non-established
540 * connection
541 */
542
Andy Green0d338332011-02-12 11:57:43 +0000543 if (new_wsi->state != WSI_STATE_ESTABLISHED)
Andy Green4739e5c2011-01-22 12:51:57 +0000544 continue;
545
Andy Greenb45993c2010-12-18 15:13:50 +0000546 /*
547 * only broadcast to connections using
548 * the requested protocol
549 */
550
Andy Green0d338332011-02-12 11:57:43 +0000551 if (new_wsi->protocol->protocol_index !=
552 wsi->protocol_index_for_broadcast_proxy)
Andy Greenb45993c2010-12-18 15:13:50 +0000553 continue;
554
Andy Green8f037e42010-12-19 22:13:26 +0000555 /* broadcast it to this connection */
556
Andy Green62c54d22011-02-14 09:14:25 +0000557 new_wsi->protocol->callback(this, new_wsi,
Andy Green8f037e42010-12-19 22:13:26 +0000558 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +0000559 new_wsi->user_space,
Andy Green0ca6a172010-12-19 20:50:01 +0000560 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
Andy Greenb45993c2010-12-18 15:13:50 +0000561 }
Andy Green0d338332011-02-12 11:57:43 +0000562 }
563 break;
Andy Greenb45993c2010-12-18 15:13:50 +0000564
Andy Green0d338332011-02-12 11:57:43 +0000565 case LWS_CONNMODE_WS_SERVING:
566 case LWS_CONNMODE_WS_CLIENT:
567
568 /* handle session socket closed */
569
570 if (pollfd->revents & (POLLERR | POLLHUP)) {
571
Andy Green62c54d22011-02-14 09:14:25 +0000572 fprintf(stderr, "Session Socket %p (fd=%d) dead\n",
Andy Green0d338332011-02-12 11:57:43 +0000573 (void *)wsi, pollfd->fd);
574
Andy Green4b6fbe12011-02-14 08:03:48 +0000575 libwebsocket_close_and_free_session(this, wsi);
576 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +0000577 }
578
Andy Green0d338332011-02-12 11:57:43 +0000579 /* the guy requested a callback when it was OK to write */
580
581 if (pollfd->revents & POLLOUT) {
582
583 pollfd->events &= ~POLLOUT;
584
Andy Green3221f922011-02-12 13:14:11 +0000585 /* external POLL support via protocol 0 */
Andy Green62c54d22011-02-14 09:14:25 +0000586 this->protocols[0].callback(this, wsi,
Andy Green3221f922011-02-12 13:14:11 +0000587 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
588 (void *)(long)wsi->sock, NULL, POLLOUT);
589
Andy Green62c54d22011-02-14 09:14:25 +0000590 wsi->protocol->callback(this, wsi,
Andy Green0d338332011-02-12 11:57:43 +0000591 LWS_CALLBACK_CLIENT_WRITEABLE,
592 wsi->user_space,
593 NULL, 0);
594 }
595
596 /* any incoming data ready? */
597
598 if (!(pollfd->revents & POLLIN))
599 break;
600
Andy Greenb45993c2010-12-18 15:13:50 +0000601#ifdef LWS_OPENSSL_SUPPORT
Andy Green0d338332011-02-12 11:57:43 +0000602 if (wsi->ssl)
603 n = SSL_read(wsi->ssl, buf, sizeof buf);
Andy Greenb45993c2010-12-18 15:13:50 +0000604 else
605#endif
Andy Green0d338332011-02-12 11:57:43 +0000606 n = recv(pollfd->fd, buf, sizeof buf, 0);
Andy Greenb45993c2010-12-18 15:13:50 +0000607
608 if (n < 0) {
609 fprintf(stderr, "Socket read returned %d\n", n);
Andy Green4b6fbe12011-02-14 08:03:48 +0000610 break;
Andy Greenb45993c2010-12-18 15:13:50 +0000611 }
612 if (!n) {
Andy Green4b6fbe12011-02-14 08:03:48 +0000613 libwebsocket_close_and_free_session(this, wsi);
614 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +0000615 }
616
Andy Greenb45993c2010-12-18 15:13:50 +0000617 /* service incoming data */
618
Andy Green4b6fbe12011-02-14 08:03:48 +0000619 n = libwebsocket_read(this, wsi, buf, n);
Andy Green6964bb52011-01-23 16:50:33 +0000620 if (n >= 0)
Andy Green4b6fbe12011-02-14 08:03:48 +0000621 break;
Andy Greenb45993c2010-12-18 15:13:50 +0000622
Andy Green4b6fbe12011-02-14 08:03:48 +0000623 /* we closed wsi */
Andy Green0d338332011-02-12 11:57:43 +0000624
Andy Green4b6fbe12011-02-14 08:03:48 +0000625 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +0000626 }
627
628 return 0;
629}
630
Andy Green0d338332011-02-12 11:57:43 +0000631
Andy Green6964bb52011-01-23 16:50:33 +0000632/**
633 * libwebsocket_context_destroy() - Destroy the websocket context
634 * @this: Websocket context
635 *
636 * This function closes any active connections and then frees the
637 * context. After calling this, any further use of the context is
638 * undefined.
639 */
640void
641libwebsocket_context_destroy(struct libwebsocket_context *this)
642{
Andy Green0d338332011-02-12 11:57:43 +0000643 int n;
644 int m;
645 struct libwebsocket *wsi;
Andy Green6964bb52011-01-23 16:50:33 +0000646
Andy Green4b6fbe12011-02-14 08:03:48 +0000647 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Andy Green0d338332011-02-12 11:57:43 +0000648 for (m = 0; m < this->fd_hashtable[n].length; m++) {
Andy Green0d338332011-02-12 11:57:43 +0000649 wsi = this->fd_hashtable[n].wsi[m];
Andy Green4b6fbe12011-02-14 08:03:48 +0000650 libwebsocket_close_and_free_session(this, wsi);
Andy Greenf3d3b402011-02-09 07:16:34 +0000651 }
Andy Green6964bb52011-01-23 16:50:33 +0000652
Andy Green44eee682011-02-10 09:32:24 +0000653 close(this->fd_random);
654
Andy Green6964bb52011-01-23 16:50:33 +0000655#ifdef LWS_OPENSSL_SUPPORT
Andy Green44eee682011-02-10 09:32:24 +0000656 if (this->ssl_ctx)
Andy Green90c7cbc2011-01-27 06:26:52 +0000657 SSL_CTX_free(this->ssl_ctx);
Andy Green44eee682011-02-10 09:32:24 +0000658 if (this->ssl_client_ctx)
Andy Green5e1fa172011-02-10 09:07:05 +0000659 SSL_CTX_free(this->ssl_client_ctx);
Andy Green6964bb52011-01-23 16:50:33 +0000660#endif
661
Andy Green44eee682011-02-10 09:32:24 +0000662 free(this);
Andy Green6964bb52011-01-23 16:50:33 +0000663}
664
665/**
666 * libwebsocket_service() - Service any pending websocket activity
667 * @this: Websocket context
668 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
669 * service otherwise block and service immediately, returning
670 * after the timeout if nothing needed service.
671 *
672 * This function deals with any pending websocket traffic, for three
673 * kinds of event. It handles these events on both server and client
674 * types of connection the same.
675 *
676 * 1) Accept new connections to our context's server
677 *
678 * 2) Perform pending broadcast writes initiated from other forked
679 * processes (effectively serializing asynchronous broadcasts)
680 *
681 * 3) Call the receive callback for incoming frame data received by
682 * server or client connections.
683 *
684 * You need to call this service function periodically to all the above
685 * functions to happen; if your application is single-threaded you can
686 * just call it in your main event loop.
687 *
688 * Alternatively you can fork a new process that asynchronously handles
689 * calling this service in a loop. In that case you are happy if this
690 * call blocks your thread until it needs to take care of something and
691 * would call it with a large nonzero timeout. Your loop then takes no
692 * CPU while there is nothing happening.
693 *
694 * If you are calling it in a single-threaded app, you don't want it to
695 * wait around blocking other things in your loop from happening, so you
696 * would call it with a timeout_ms of 0, so it returns immediately if
697 * nothing is pending, or as soon as it services whatever was pending.
698 */
699
Andy Greenb45993c2010-12-18 15:13:50 +0000700
Andy Greene92cd172011-01-19 13:11:55 +0000701int
702libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
703{
704 int n;
Andy Greene92cd172011-01-19 13:11:55 +0000705
706 /* stay dead once we are dead */
707
708 if (this == NULL)
709 return 1;
710
Andy Green0d338332011-02-12 11:57:43 +0000711 /* wait for something to need service */
Andy Green4739e5c2011-01-22 12:51:57 +0000712
Andy Green0d338332011-02-12 11:57:43 +0000713 n = poll(this->fds, this->fds_count, timeout_ms);
Andy Green3221f922011-02-12 13:14:11 +0000714 if (n == 0) /* poll timeout */
715 return 0;
Andy Greene92cd172011-01-19 13:11:55 +0000716
Andy Green62c54d22011-02-14 09:14:25 +0000717 if (n < 0) {
Andy Green5e1fa172011-02-10 09:07:05 +0000718 /*
Andy Greene92cd172011-01-19 13:11:55 +0000719 fprintf(stderr, "Listen Socket dead\n");
Andy Green5e1fa172011-02-10 09:07:05 +0000720 */
Andy Green0d338332011-02-12 11:57:43 +0000721 return 1;
Andy Greene92cd172011-01-19 13:11:55 +0000722 }
Andy Greene92cd172011-01-19 13:11:55 +0000723
724 /* handle accept on listening socket? */
725
Andy Green0d338332011-02-12 11:57:43 +0000726 for (n = 0; n < this->fds_count; n++)
727 if (this->fds[n].revents)
728 libwebsocket_service_fd(this, &this->fds[n]);
Andy Greene92cd172011-01-19 13:11:55 +0000729
730 return 0;
Andy Greene92cd172011-01-19 13:11:55 +0000731}
732
Andy Green90c7cbc2011-01-27 06:26:52 +0000733/**
734 * libwebsocket_callback_on_writable() - Request a callback when this socket
735 * becomes able to be written to without
736 * blocking
Andy Green3221f922011-02-12 13:14:11 +0000737 * *
Andy Green90c7cbc2011-01-27 06:26:52 +0000738 * @wsi: Websocket connection instance to get callback for
739 */
740
741int
Andy Green62c54d22011-02-14 09:14:25 +0000742libwebsocket_callback_on_writable(struct libwebsocket_context *this,
743 struct libwebsocket *wsi)
Andy Green90c7cbc2011-01-27 06:26:52 +0000744{
Andy Green90c7cbc2011-01-27 06:26:52 +0000745 int n;
746
Andy Green0d338332011-02-12 11:57:43 +0000747 for (n = 0; n < this->fds_count; n++)
748 if (this->fds[n].fd == wsi->sock) {
Andy Green90c7cbc2011-01-27 06:26:52 +0000749 this->fds[n].events |= POLLOUT;
Andy Green3221f922011-02-12 13:14:11 +0000750 n = this->fds_count;
Andy Green90c7cbc2011-01-27 06:26:52 +0000751 }
752
Andy Green3221f922011-02-12 13:14:11 +0000753 /* external POLL support via protocol 0 */
Andy Green62c54d22011-02-14 09:14:25 +0000754 this->protocols[0].callback(this, wsi,
Andy Green3221f922011-02-12 13:14:11 +0000755 LWS_CALLBACK_SET_MODE_POLL_FD,
756 (void *)(long)wsi->sock, NULL, POLLOUT);
757
Andy Green90c7cbc2011-01-27 06:26:52 +0000758 return 1;
759}
760
761/**
762 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
763 * all connections using the given protocol when it
764 * becomes possible to write to each socket without
765 * blocking in turn.
766 *
767 * @protocol: Protocol whose connections will get callbacks
768 */
769
770int
771libwebsocket_callback_on_writable_all_protocol(
772 const struct libwebsocket_protocols *protocol)
773{
774 struct libwebsocket_context *this = protocol->owning_server;
775 int n;
Andy Green0d338332011-02-12 11:57:43 +0000776 int m;
777 struct libwebsocket *wsi;
Andy Green90c7cbc2011-01-27 06:26:52 +0000778
Andy Green0d338332011-02-12 11:57:43 +0000779 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
780
781 for (m = 0; m < this->fd_hashtable[n].length; m++) {
782
783 wsi = this->fd_hashtable[n].wsi[m];
784
785 if (wsi->protocol == protocol)
Andy Green62c54d22011-02-14 09:14:25 +0000786 libwebsocket_callback_on_writable(this, wsi);
Andy Green0d338332011-02-12 11:57:43 +0000787 }
788 }
Andy Green90c7cbc2011-01-27 06:26:52 +0000789
790 return 0;
791}
792
Andy Greena6cbece2011-01-27 20:06:03 +0000793
794/**
795 * libwebsocket_get_socket_fd() - returns the socket file descriptor
796 *
797 * You will not need this unless you are doing something special
798 *
799 * @wsi: Websocket connection instance
800 */
801
802int
803libwebsocket_get_socket_fd(struct libwebsocket *wsi)
804{
805 return wsi->sock;
806}
807
Andy Green90c7cbc2011-01-27 06:26:52 +0000808/**
809 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
810 * receieved packets.
811 *
812 * If the output side of a server process becomes choked, this allows flow
813 * control for the input side.
814 *
815 * @wsi: Websocket connection instance to get callback for
816 * @enable: 0 = disable read servicing for this connection, 1 = enable
817 */
818
819int
820libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
821{
822 struct libwebsocket_context *this = wsi->protocol->owning_server;
823 int n;
824
Andy Green0d338332011-02-12 11:57:43 +0000825 for (n = 0; n < this->fds_count; n++)
826 if (this->fds[n].fd == wsi->sock) {
Andy Green90c7cbc2011-01-27 06:26:52 +0000827 if (enable)
828 this->fds[n].events |= POLLIN;
829 else
830 this->fds[n].events &= ~POLLIN;
831
832 return 0;
833 }
834
Andy Green3221f922011-02-12 13:14:11 +0000835 if (enable)
836 /* external POLL support via protocol 0 */
Andy Green62c54d22011-02-14 09:14:25 +0000837 this->protocols[0].callback(this, wsi,
Andy Green3221f922011-02-12 13:14:11 +0000838 LWS_CALLBACK_SET_MODE_POLL_FD,
839 (void *)(long)wsi->sock, NULL, POLLIN);
840 else
841 /* external POLL support via protocol 0 */
Andy Green62c54d22011-02-14 09:14:25 +0000842 this->protocols[0].callback(this, wsi,
Andy Green3221f922011-02-12 13:14:11 +0000843 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
844 (void *)(long)wsi->sock, NULL, POLLIN);
845
846
Andy Green90c7cbc2011-01-27 06:26:52 +0000847 fprintf(stderr, "libwebsocket_callback_on_writable "
848 "unable to find socket\n");
849 return 1;
850}
851
Andy Green2ac5a6f2011-01-28 10:00:18 +0000852/**
853 * libwebsocket_canonical_hostname() - returns this host's hostname
854 *
855 * This is typically used by client code to fill in the host parameter
856 * when making a client connection. You can only call it after the context
857 * has been created.
858 *
859 * @this: Websocket context
860 */
861
862
863extern const char *
864libwebsocket_canonical_hostname(struct libwebsocket_context *this)
865{
866 return (const char *)this->canonical_hostname;
867}
868
869
Andy Green90c7cbc2011-01-27 06:26:52 +0000870static void sigpipe_handler(int x)
871{
872}
873
Andy Greenb45993c2010-12-18 15:13:50 +0000874
Andy Green0d338332011-02-12 11:57:43 +0000875
Andy Greenab990e42010-10-31 12:42:52 +0000876/**
Andy Green4739e5c2011-01-22 12:51:57 +0000877 * libwebsocket_create_context() - Create the websocket handler
878 * @port: Port to listen on... you can use 0 to suppress listening on
Andy Green6964bb52011-01-23 16:50:33 +0000879 * any port, that's what you want if you are not running a
880 * websocket server at all but just using it as a client
Andy Green4f3943a2010-11-12 10:44:16 +0000881 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +0000882 * specific callback for each one. The list is ended with an
883 * entry that has a NULL callback pointer.
Andy Green6964bb52011-01-23 16:50:33 +0000884 * It's not const because we write the owning_server member
Andy Green3faa9c72010-11-08 17:03:03 +0000885 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +0000886 * to listen using SSL, set to the filepath to fetch the
887 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +0000888 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +0000889 * else ignored
Andy Green3faa9c72010-11-08 17:03:03 +0000890 * @gid: group id to change to after setting listen socket, or -1.
891 * @uid: user id to change to after setting listen socket, or -1.
Andy Greenbfb051f2011-02-09 08:49:14 +0000892 * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
Andy Green05464c62010-11-12 10:44:18 +0000893 *
Andy Green8f037e42010-12-19 22:13:26 +0000894 * This function creates the listening socket and takes care
895 * of all initialization in one step.
896 *
Andy Greene92cd172011-01-19 13:11:55 +0000897 * After initialization, it returns a struct libwebsocket_context * that
898 * represents this server. After calling, user code needs to take care
899 * of calling libwebsocket_service() with the context pointer to get the
900 * server's sockets serviced. This can be done in the same process context
901 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +0000902 *
Andy Green8f037e42010-12-19 22:13:26 +0000903 * The protocol callback functions are called for a handful of events
904 * including http requests coming in, websocket connections becoming
905 * established, and data arriving; it's also called periodically to allow
906 * async transmission.
907 *
908 * HTTP requests are sent always to the FIRST protocol in @protocol, since
909 * at that time websocket protocol has not been negotiated. Other
910 * protocols after the first one never see any HTTP callack activity.
911 *
912 * The server created is a simple http server by default; part of the
913 * websocket standard is upgrading this http connection to a websocket one.
914 *
915 * This allows the same server to provide files like scripts and favicon /
916 * images or whatever over http and dynamic data over websockets all in
917 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +0000918 */
Andy Green4ea60062010-10-30 12:15:07 +0100919
Andy Greene92cd172011-01-19 13:11:55 +0000920struct libwebsocket_context *
Andy Green4739e5c2011-01-22 12:51:57 +0000921libwebsocket_create_context(int port,
Andy Greenb45993c2010-12-18 15:13:50 +0000922 struct libwebsocket_protocols *protocols,
Andy Green8f037e42010-12-19 22:13:26 +0000923 const char *ssl_cert_filepath,
924 const char *ssl_private_key_filepath,
Andy Green8014b292011-01-30 20:57:25 +0000925 int gid, int uid, unsigned int options)
Andy Greenff95d7a2010-10-28 22:36:01 +0100926{
927 int n;
Andy Green4739e5c2011-01-22 12:51:57 +0000928 int sockfd = 0;
Andy Green251f6fa2010-11-03 11:13:06 +0000929 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +0100930 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +0000931 int opt = 1;
Andy Green8f037e42010-12-19 22:13:26 +0000932 struct libwebsocket_context *this = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +0000933 unsigned int slen;
Andy Green9659f372011-01-27 22:01:43 +0000934 char *p;
Andy Green2ac5a6f2011-01-28 10:00:18 +0000935 char hostname[1024];
Andy Green42f69142011-01-30 08:10:02 +0000936 struct hostent *he;
Andy Green0d338332011-02-12 11:57:43 +0000937 struct libwebsocket *wsi;
Andy Greenff95d7a2010-10-28 22:36:01 +0100938
Andy Green3faa9c72010-11-08 17:03:03 +0000939#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +0000940 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +0000941 char ssl_err_buf[512];
Andy Green3faa9c72010-11-08 17:03:03 +0000942#endif
943
Andy Green90c7cbc2011-01-27 06:26:52 +0000944 this = malloc(sizeof(struct libwebsocket_context));
945 if (!this) {
946 fprintf(stderr, "No memory for websocket context\n");
947 return NULL;
948 }
949 this->protocols = protocols;
950 this->listen_port = port;
Andy Green9659f372011-01-27 22:01:43 +0000951 this->http_proxy_port = 0;
952 this->http_proxy_address[0] = '\0';
Andy Green8014b292011-01-30 20:57:25 +0000953 this->options = options;
Andy Green0d338332011-02-12 11:57:43 +0000954 this->fds_count = 0;
Andy Green9659f372011-01-27 22:01:43 +0000955
Andy Green44eee682011-02-10 09:32:24 +0000956 this->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
957 if (this->fd_random < 0) {
958 fprintf(stderr, "Unable to open random device %s %d\n",
959 SYSTEM_RANDOM_FILEPATH, this->fd_random);
960 return NULL;
961 }
962
Andy Green2ac5a6f2011-01-28 10:00:18 +0000963 /* find canonical hostname */
964
965 hostname[(sizeof hostname) - 1] = '\0';
966 gethostname(hostname, (sizeof hostname) - 1);
967 he = gethostbyname(hostname);
968 strncpy(this->canonical_hostname, he->h_name,
969 sizeof this->canonical_hostname - 1);
970 this->canonical_hostname[sizeof this->canonical_hostname - 1] = '\0';
971
Andy Green9659f372011-01-27 22:01:43 +0000972 /* split the proxy ads:port if given */
973
974 p = getenv("http_proxy");
975 if (p) {
976 strncpy(this->http_proxy_address, p,
977 sizeof this->http_proxy_address - 1);
978 this->http_proxy_address[
979 sizeof this->http_proxy_address - 1] = '\0';
980
981 p = strchr(this->http_proxy_address, ':');
982 if (p == NULL) {
983 fprintf(stderr, "http_proxy needs to be ads:port\n");
984 return NULL;
985 }
986 *p = '\0';
987 this->http_proxy_port = atoi(p + 1);
988
989 fprintf(stderr, "Using proxy %s:%u\n",
990 this->http_proxy_address,
991 this->http_proxy_port);
992 }
Andy Green90c7cbc2011-01-27 06:26:52 +0000993
994 if (port) {
995
Andy Green3faa9c72010-11-08 17:03:03 +0000996#ifdef LWS_OPENSSL_SUPPORT
Andy Green90c7cbc2011-01-27 06:26:52 +0000997 this->use_ssl = ssl_cert_filepath != NULL &&
998 ssl_private_key_filepath != NULL;
999 if (this->use_ssl)
1000 fprintf(stderr, " Compiled with SSL support, "
1001 "using it\n");
1002 else
1003 fprintf(stderr, " Compiled with SSL support, "
1004 "not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +00001005
Andy Green90c7cbc2011-01-27 06:26:52 +00001006#else
1007 if (ssl_cert_filepath != NULL &&
1008 ssl_private_key_filepath != NULL) {
1009 fprintf(stderr, " Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +00001010 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00001011 }
Andy Green90c7cbc2011-01-27 06:26:52 +00001012 fprintf(stderr, " Compiled without SSL support, "
1013 "serving unencrypted\n");
1014#endif
1015 }
1016
1017 /* ignore SIGPIPE */
1018
1019 signal(SIGPIPE, sigpipe_handler);
1020
1021
1022#ifdef LWS_OPENSSL_SUPPORT
1023
1024 /* basic openssl init */
1025
1026 SSL_library_init();
1027
1028 OpenSSL_add_all_algorithms();
1029 SSL_load_error_strings();
1030
1031 /*
1032 * Firefox insists on SSLv23 not SSLv3
1033 * Konq disables SSLv2 by default now, SSLv23 works
1034 */
1035
1036 method = (SSL_METHOD *)SSLv23_server_method();
1037 if (!method) {
1038 fprintf(stderr, "problem creating ssl method: %s\n",
1039 ERR_error_string(ERR_get_error(), ssl_err_buf));
1040 return NULL;
1041 }
1042 this->ssl_ctx = SSL_CTX_new(method); /* create context */
1043 if (!this->ssl_ctx) {
1044 fprintf(stderr, "problem creating ssl context: %s\n",
1045 ERR_error_string(ERR_get_error(), ssl_err_buf));
1046 return NULL;
1047 }
1048
1049 /* client context */
1050
1051 method = (SSL_METHOD *)SSLv23_client_method();
1052 if (!method) {
1053 fprintf(stderr, "problem creating ssl method: %s\n",
1054 ERR_error_string(ERR_get_error(), ssl_err_buf));
1055 return NULL;
1056 }
1057 this->ssl_client_ctx = SSL_CTX_new(method); /* create context */
1058 if (!this->ssl_client_ctx) {
1059 fprintf(stderr, "problem creating ssl context: %s\n",
1060 ERR_error_string(ERR_get_error(), ssl_err_buf));
1061 return NULL;
1062 }
1063
1064
1065 /* openssl init for cert verification (used with client sockets) */
1066
1067 if (!SSL_CTX_load_verify_locations(this->ssl_client_ctx, NULL,
1068 LWS_OPENSSL_CLIENT_CERTS)) {
1069 fprintf(stderr, "Unable to load SSL Client certs from %s "
1070 "(set by --with-client-cert-dir= in configure) -- "
1071 " client ssl isn't going to work",
1072 LWS_OPENSSL_CLIENT_CERTS);
1073 }
1074
1075 if (this->use_ssl) {
1076
1077 /* openssl init for server sockets */
1078
Andy Green3faa9c72010-11-08 17:03:03 +00001079 /* set the local certificate from CertFile */
Andy Green90c7cbc2011-01-27 06:26:52 +00001080 n = SSL_CTX_use_certificate_file(this->ssl_ctx,
Andy Green3faa9c72010-11-08 17:03:03 +00001081 ssl_cert_filepath, SSL_FILETYPE_PEM);
1082 if (n != 1) {
1083 fprintf(stderr, "problem getting cert '%s': %s\n",
1084 ssl_cert_filepath,
1085 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00001086 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00001087 }
1088 /* set the private key from KeyFile */
Andy Green90c7cbc2011-01-27 06:26:52 +00001089 if (SSL_CTX_use_PrivateKey_file(this->ssl_ctx,
Andy Green018d8eb2010-11-08 21:04:23 +00001090 ssl_private_key_filepath,
Andy Green4739e5c2011-01-22 12:51:57 +00001091 SSL_FILETYPE_PEM) != 1) {
Andy Green018d8eb2010-11-08 21:04:23 +00001092 fprintf(stderr, "ssl problem getting key '%s': %s\n",
1093 ssl_private_key_filepath,
1094 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00001095 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00001096 }
1097 /* verify private key */
Andy Green90c7cbc2011-01-27 06:26:52 +00001098 if (!SSL_CTX_check_private_key(this->ssl_ctx)) {
Andy Green018d8eb2010-11-08 21:04:23 +00001099 fprintf(stderr, "Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +00001100 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00001101 }
1102
1103 /* SSL is happy and has a cert it's content with */
1104 }
1105#endif
Andy Greenb45993c2010-12-18 15:13:50 +00001106
Andy Greendf736162011-01-18 15:39:02 +00001107 /* selftest */
1108
1109 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +00001110 return NULL;
Andy Greendf736162011-01-18 15:39:02 +00001111
Andy Green0d338332011-02-12 11:57:43 +00001112 /* fd hashtable init */
1113
1114 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
1115 this->fd_hashtable[n].length = 0;
1116
Andy Greenb45993c2010-12-18 15:13:50 +00001117 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +00001118
Andy Green4739e5c2011-01-22 12:51:57 +00001119 if (port) {
Andy Green8f037e42010-12-19 22:13:26 +00001120
Andy Green4739e5c2011-01-22 12:51:57 +00001121 sockfd = socket(AF_INET, SOCK_STREAM, 0);
1122 if (sockfd < 0) {
1123 fprintf(stderr, "ERROR opening socket");
1124 return NULL;
1125 }
Andy Green775c0dd2010-10-29 14:15:22 +01001126
Andy Green4739e5c2011-01-22 12:51:57 +00001127 /* allow us to restart even if old sockets in TIME_WAIT */
1128 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
Andy Greene77ddd82010-11-13 10:03:47 +00001129
Andy Green4739e5c2011-01-22 12:51:57 +00001130 bzero((char *) &serv_addr, sizeof(serv_addr));
1131 serv_addr.sin_family = AF_INET;
1132 serv_addr.sin_addr.s_addr = INADDR_ANY;
1133 serv_addr.sin_port = htons(port);
1134
1135 n = bind(sockfd, (struct sockaddr *) &serv_addr,
1136 sizeof(serv_addr));
1137 if (n < 0) {
1138 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
Andy Green8f037e42010-12-19 22:13:26 +00001139 port, n, errno);
Andy Green4739e5c2011-01-22 12:51:57 +00001140 return NULL;
1141 }
Andy Green0d338332011-02-12 11:57:43 +00001142
1143 wsi = malloc(sizeof(struct libwebsocket));
1144 memset(wsi, 0, sizeof (struct libwebsocket));
1145 wsi->sock = sockfd;
1146 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
1147 insert_wsi(this, wsi);
1148
1149 listen(sockfd, 5);
1150 fprintf(stderr, " Listening on port %d\n", port);
1151
1152 /* list in the internal poll array */
1153
1154 this->fds[this->fds_count].fd = sockfd;
1155 this->fds[this->fds_count++].events = POLLIN;
Andy Green3221f922011-02-12 13:14:11 +00001156
1157 /* external POLL support via protocol 0 */
Andy Green62c54d22011-02-14 09:14:25 +00001158 this->protocols[0].callback(this, wsi,
Andy Green3221f922011-02-12 13:14:11 +00001159 LWS_CALLBACK_ADD_POLL_FD,
1160 (void *)(long)sockfd, NULL, POLLIN);
1161
Andy Green8f037e42010-12-19 22:13:26 +00001162 }
Andy Greenb45993c2010-12-18 15:13:50 +00001163
Andy Greene77ddd82010-11-13 10:03:47 +00001164 /* drop any root privs for this process */
Andy Green3faa9c72010-11-08 17:03:03 +00001165
1166 if (gid != -1)
1167 if (setgid(gid))
1168 fprintf(stderr, "setgid: %s\n", strerror(errno));
1169 if (uid != -1)
1170 if (setuid(uid))
1171 fprintf(stderr, "setuid: %s\n", strerror(errno));
1172
Andy Greenb45993c2010-12-18 15:13:50 +00001173
1174 /* set up our internal broadcast trigger sockets per-protocol */
1175
Andy Green0d338332011-02-12 11:57:43 +00001176 for (this->count_protocols = 0;
1177 protocols[this->count_protocols].callback;
Andy Greenb45993c2010-12-18 15:13:50 +00001178 this->count_protocols++) {
1179 protocols[this->count_protocols].owning_server = this;
1180 protocols[this->count_protocols].protocol_index =
1181 this->count_protocols;
1182
1183 fd = socket(AF_INET, SOCK_STREAM, 0);
1184 if (fd < 0) {
1185 fprintf(stderr, "ERROR opening socket");
Andy Greene92cd172011-01-19 13:11:55 +00001186 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00001187 }
Andy Green8f037e42010-12-19 22:13:26 +00001188
Andy Greenb45993c2010-12-18 15:13:50 +00001189 /* allow us to restart even if old sockets in TIME_WAIT */
1190 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1191
1192 bzero((char *) &serv_addr, sizeof(serv_addr));
1193 serv_addr.sin_family = AF_INET;
1194 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
1195 serv_addr.sin_port = 0; /* pick the port for us */
1196
1197 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
1198 if (n < 0) {
Andy Green8f037e42010-12-19 22:13:26 +00001199 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
Andy Greenb45993c2010-12-18 15:13:50 +00001200 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +00001201 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00001202 }
1203
1204 slen = sizeof cli_addr;
1205 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
1206 if (n < 0) {
1207 fprintf(stderr, "getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +00001208 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00001209 }
1210 protocols[this->count_protocols].broadcast_socket_port =
1211 ntohs(cli_addr.sin_port);
1212 listen(fd, 5);
1213
1214 debug(" Protocol %s broadcast socket %d\n",
1215 protocols[this->count_protocols].name,
1216 ntohs(cli_addr.sin_port));
1217
Andy Green0d338332011-02-12 11:57:43 +00001218 /* dummy wsi per broadcast proxy socket */
1219
1220 wsi = malloc(sizeof(struct libwebsocket));
1221 memset(wsi, 0, sizeof (struct libwebsocket));
1222 wsi->sock = fd;
1223 wsi->mode = LWS_CONNMODE_BROADCAST_PROXY_LISTENER;
1224 /* note which protocol we are proxying */
1225 wsi->protocol_index_for_broadcast_proxy = this->count_protocols;
1226 insert_wsi(this, wsi);
1227
1228 /* list in internal poll array */
1229
Andy Greenb45993c2010-12-18 15:13:50 +00001230 this->fds[this->fds_count].fd = fd;
1231 this->fds[this->fds_count].events = POLLIN;
Andy Green3221f922011-02-12 13:14:11 +00001232 this->fds[this->fds_count].revents = 0;
Andy Greenb45993c2010-12-18 15:13:50 +00001233 this->fds_count++;
Andy Green3221f922011-02-12 13:14:11 +00001234
1235 /* external POLL support via protocol 0 */
Andy Green62c54d22011-02-14 09:14:25 +00001236 this->protocols[0].callback(this, wsi,
Andy Green3221f922011-02-12 13:14:11 +00001237 LWS_CALLBACK_ADD_POLL_FD,
1238 (void *)(long)fd, NULL, POLLIN);
Andy Greenb45993c2010-12-18 15:13:50 +00001239 }
1240
Andy Greene92cd172011-01-19 13:11:55 +00001241 return this;
1242}
Andy Greenb45993c2010-12-18 15:13:50 +00001243
Andy Green4739e5c2011-01-22 12:51:57 +00001244
Andy Greened11a022011-01-20 10:23:50 +00001245#ifndef LWS_NO_FORK
1246
Andy Greene92cd172011-01-19 13:11:55 +00001247/**
1248 * libwebsockets_fork_service_loop() - Optional helper function forks off
1249 * a process for the websocket server loop.
Andy Green6964bb52011-01-23 16:50:33 +00001250 * You don't have to use this but if not, you
1251 * have to make sure you are calling
1252 * libwebsocket_service periodically to service
1253 * the websocket traffic
Andy Greene92cd172011-01-19 13:11:55 +00001254 * @this: server context returned by creation function
1255 */
Andy Greenb45993c2010-12-18 15:13:50 +00001256
Andy Greene92cd172011-01-19 13:11:55 +00001257int
1258libwebsockets_fork_service_loop(struct libwebsocket_context *this)
1259{
Andy Greene92cd172011-01-19 13:11:55 +00001260 int fd;
1261 struct sockaddr_in cli_addr;
1262 int n;
Andy Green3221f922011-02-12 13:14:11 +00001263 int p;
Andy Greenb45993c2010-12-18 15:13:50 +00001264
Andy Greened11a022011-01-20 10:23:50 +00001265 n = fork();
1266 if (n < 0)
1267 return n;
1268
1269 if (!n) {
1270
1271 /* main process context */
1272
Andy Green3221f922011-02-12 13:14:11 +00001273 /*
1274 * set up the proxy sockets to allow broadcast from
1275 * service process context
1276 */
1277
1278 for (p = 0; p < this->count_protocols; p++) {
Andy Greened11a022011-01-20 10:23:50 +00001279 fd = socket(AF_INET, SOCK_STREAM, 0);
1280 if (fd < 0) {
1281 fprintf(stderr, "Unable to create socket\n");
1282 return -1;
1283 }
1284 cli_addr.sin_family = AF_INET;
1285 cli_addr.sin_port = htons(
Andy Green3221f922011-02-12 13:14:11 +00001286 this->protocols[p].broadcast_socket_port);
Andy Greened11a022011-01-20 10:23:50 +00001287 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
1288 n = connect(fd, (struct sockaddr *)&cli_addr,
1289 sizeof cli_addr);
1290 if (n < 0) {
1291 fprintf(stderr, "Unable to connect to "
1292 "broadcast socket %d, %s\n",
Andy Green3221f922011-02-12 13:14:11 +00001293 n, strerror(errno));
Andy Greened11a022011-01-20 10:23:50 +00001294 return -1;
1295 }
1296
Andy Green3221f922011-02-12 13:14:11 +00001297 this->protocols[p].broadcast_socket_user_fd = fd;
Andy Greened11a022011-01-20 10:23:50 +00001298 }
1299
Andy Greene92cd172011-01-19 13:11:55 +00001300 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00001301 }
1302
1303 /* we want a SIGHUP when our parent goes down */
1304 prctl(PR_SET_PDEATHSIG, SIGHUP);
1305
1306 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +00001307
Andy Greene92cd172011-01-19 13:11:55 +00001308 while (1)
1309 if (libwebsocket_service(this, 1000))
1310 return -1;
Andy Green8f037e42010-12-19 22:13:26 +00001311
Andy Green251f6fa2010-11-03 11:13:06 +00001312 return 0;
Andy Greenff95d7a2010-10-28 22:36:01 +01001313}
1314
Andy Greened11a022011-01-20 10:23:50 +00001315#endif
1316
Andy Greenb45993c2010-12-18 15:13:50 +00001317/**
1318 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +00001319 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +00001320 * @wsi: pointer to struct websocket you want to know the protocol of
1321 *
Andy Green8f037e42010-12-19 22:13:26 +00001322 *
1323 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +00001324 * the callback.
1325 */
Andy Greenab990e42010-10-31 12:42:52 +00001326
Andy Greenb45993c2010-12-18 15:13:50 +00001327const struct libwebsocket_protocols *
1328libwebsockets_get_protocol(struct libwebsocket *wsi)
1329{
1330 return wsi->protocol;
1331}
1332
1333/**
Andy Greene92cd172011-01-19 13:11:55 +00001334 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +00001335 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +00001336 * @protocol: pointer to the protocol you will broadcast to all members of
1337 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +00001338 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
1339 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
1340 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +00001341 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +00001342 *
1343 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +00001344 * the given protocol. It does not send the data directly; instead it calls
1345 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
1346 * wants to actually send the data for that connection, the callback itself
1347 * should call libwebsocket_write().
1348 *
1349 * libwebsockets_broadcast() can be called from another fork context without
1350 * having to take any care about data visibility between the processes, it'll
1351 * "just work".
1352 */
1353
1354
1355int
Andy Green8f037e42010-12-19 22:13:26 +00001356libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +00001357 unsigned char *buf, size_t len)
1358{
Andy Green8f037e42010-12-19 22:13:26 +00001359 struct libwebsocket_context *this = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +00001360 int n;
Andy Green0d338332011-02-12 11:57:43 +00001361 int m;
1362 struct libwebsocket * wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00001363
1364 if (!protocol->broadcast_socket_user_fd) {
1365 /*
Andy Greene92cd172011-01-19 13:11:55 +00001366 * We are either running unforked / flat, or we are being
1367 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +00001368 * eg, from a callback. In that case don't use sockets for
1369 * broadcast IPC (since we can't open a socket connection to
1370 * a socket listening on our own thread) but directly do the
1371 * send action.
1372 *
1373 * Locking is not needed because we are by definition being
1374 * called in the poll thread context and are serialized.
1375 */
1376
Andy Green0d338332011-02-12 11:57:43 +00001377 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Greenb45993c2010-12-18 15:13:50 +00001378
Andy Green0d338332011-02-12 11:57:43 +00001379 for (m = 0; m < this->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00001380
Andy Green0d338332011-02-12 11:57:43 +00001381 wsi = this->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00001382
Andy Green0d338332011-02-12 11:57:43 +00001383 if (wsi->mode != LWS_CONNMODE_WS_SERVING)
1384 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00001385
Andy Green0d338332011-02-12 11:57:43 +00001386 /*
1387 * never broadcast to
1388 * non-established connections
1389 */
1390 if (wsi->state != WSI_STATE_ESTABLISHED)
1391 continue;
1392
1393 /* only broadcast to guys using
1394 * requested protocol
1395 */
1396 if (wsi->protocol != protocol)
1397 continue;
1398
Andy Green62c54d22011-02-14 09:14:25 +00001399 wsi->protocol->callback(this, wsi,
Andy Green8f037e42010-12-19 22:13:26 +00001400 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00001401 wsi->user_space,
Andy Greenb45993c2010-12-18 15:13:50 +00001402 buf, len);
Andy Green0d338332011-02-12 11:57:43 +00001403 }
Andy Greenb45993c2010-12-18 15:13:50 +00001404 }
1405
1406 return 0;
1407 }
1408
Andy Green0ca6a172010-12-19 20:50:01 +00001409 /*
1410 * We're being called from a different process context than the server
1411 * loop. Instead of broadcasting directly, we send our
1412 * payload on a socket to do the IPC; the server process will serialize
1413 * the broadcast action in its main poll() loop.
1414 *
1415 * There's one broadcast socket listening for each protocol supported
1416 * set up when the websocket server initializes
1417 */
1418
Andy Green6964bb52011-01-23 16:50:33 +00001419 n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
Andy Greenb45993c2010-12-18 15:13:50 +00001420
1421 return n;
1422}