blob: 59c954a89215d2f64fed1a076b31a66e228a9c66 [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 Green251f6fa2010-11-03 11:13:06 +000079libwebsocket_close_and_free_session(struct libwebsocket *wsi)
80{
Andy Greenb45993c2010-12-18 15:13:50 +000081 int n;
Andy Green5e1fa172011-02-10 09:07:05 +000082 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
83 LWS_SEND_BUFFER_POST_PADDING];
Andy Greenb45993c2010-12-18 15:13:50 +000084
85 if ((unsigned long)wsi < LWS_MAX_PROTOCOLS)
86 return;
87
88 n = wsi->state;
Andy Green251f6fa2010-11-03 11:13:06 +000089
Andy Green5e1fa172011-02-10 09:07:05 +000090 if (n == WSI_STATE_DEAD_SOCKET)
91 return;
92
93 /*
94 * signal we are closing, libsocket_write will
95 * add any necessary version-specific stuff. If the write fails,
96 * no worries we are closing anyway. If we didn't initiate this
97 * close, then our state has been changed to
98 * WSI_STATE_RETURNED_CLOSE_ALREADY and we can skip this
99 */
100
101 if (n == WSI_STATE_ESTABLISHED)
102 libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 0,
103 LWS_WRITE_CLOSE);
104
Andy Green251f6fa2010-11-03 11:13:06 +0000105 wsi->state = WSI_STATE_DEAD_SOCKET;
106
Andy Green4f3943a2010-11-12 10:44:16 +0000107 if (wsi->protocol->callback && n == WSI_STATE_ESTABLISHED)
Andy Greene77ddd82010-11-13 10:03:47 +0000108 wsi->protocol->callback(wsi, LWS_CALLBACK_CLOSED,
109 wsi->user_space, NULL, 0);
Andy Green251f6fa2010-11-03 11:13:06 +0000110
111 for (n = 0; n < WSI_TOKEN_COUNT; n++)
112 if (wsi->utf8_token[n].token)
113 free(wsi->utf8_token[n].token);
114
Andy Green0ca6a172010-12-19 20:50:01 +0000115/* fprintf(stderr, "closing fd=%d\n", wsi->sock); */
Andy Green251f6fa2010-11-03 11:13:06 +0000116
Andy Green3faa9c72010-11-08 17:03:03 +0000117#ifdef LWS_OPENSSL_SUPPORT
Andy Green90c7cbc2011-01-27 06:26:52 +0000118 if (wsi->ssl) {
Andy Green3faa9c72010-11-08 17:03:03 +0000119 n = SSL_get_fd(wsi->ssl);
120 SSL_shutdown(wsi->ssl);
121 close(n);
122 SSL_free(wsi->ssl);
123 } else {
124#endif
125 shutdown(wsi->sock, SHUT_RDWR);
126 close(wsi->sock);
127#ifdef LWS_OPENSSL_SUPPORT
128 }
129#endif
Andy Green4f3943a2010-11-12 10:44:16 +0000130 if (wsi->user_space)
131 free(wsi->user_space);
132
Andy Green251f6fa2010-11-03 11:13:06 +0000133 free(wsi);
134}
135
Andy Green07034092011-02-13 08:37:12 +0000136/**
137 * libwebsockets_get_peer_addresses() - Get client address information
138 * @fd: Connection socket descriptor
139 * @name: Buffer to take client address name
140 * @name_len: Length of client address name buffer
141 * @rip: Buffer to take client address IP qotted quad
142 * @rip_len: Length of client address IP buffer
143 *
144 * This function fills in @name and @rip with the name and IP of
145 * the client connected with socket descriptor @fd. Names may be
146 * truncated if there is not enough room. If either cannot be
147 * determined, they will be returned as valid zero-length strings.
148 */
149
150void
151libwebsockets_get_peer_addresses(int fd, char *name, int name_len,
152 char *rip, int rip_len)
153{
154 unsigned int len;
155 struct sockaddr_in sin;
156 struct hostent *host;
157 struct hostent *host1;
158 char ip[128];
159 char *p;
160 int n;
161
162 rip[0] = '\0';
163 name[0] = '\0';
164
165 len = sizeof sin;
166 if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
167 perror("getpeername");
168 return;
169 }
170
171 host = gethostbyaddr((char *) &sin.sin_addr, sizeof sin.sin_addr,
172 AF_INET);
173 if (host == NULL) {
174 perror("gethostbyaddr");
175 return;
176 }
177
178 strncpy(name, host->h_name, name_len);
179 name[name_len - 1] = '\0';
180
181 host1 = gethostbyname(host->h_name);
182 if (host1 == NULL)
183 return;
184 p = (char *)host1;
185 n = 0;
186 while (p != NULL) {
187 p = host1->h_addr_list[n++];
188 if (p == NULL)
189 continue;
190 if (host1->h_addrtype != AF_INET)
191 continue;
192
193 sprintf(ip, "%d.%d.%d.%d",
194 p[0], p[1], p[2], p[3]);
195 p = NULL;
196 strncpy(rip, ip, rip_len);
197 rip[rip_len - 1] = '\0';
198 }
199}
Andy Green9f990342011-02-12 11:57:45 +0000200
201/**
202 * libwebsocket_service_fd() - Service polled socket with something waiting
203 * @this: Websocket context
204 * @pollfd: The pollfd entry describing the socket fd and which events
205 * happened.
206 *
207 * This function closes any active connections and then frees the
208 * context. After calling this, any further use of the context is
209 * undefined.
210 */
211
212int
Andy Green0d338332011-02-12 11:57:43 +0000213libwebsocket_service_fd(struct libwebsocket_context *this,
214 struct pollfd *pollfd)
Andy Greenb45993c2010-12-18 15:13:50 +0000215{
216 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_BROADCAST_PAYLOAD +
217 LWS_SEND_BUFFER_POST_PADDING];
Andy Green0d338332011-02-12 11:57:43 +0000218 struct libwebsocket *wsi = wsi_from_fd(this, pollfd->fd);
219 struct libwebsocket *new_wsi;
Andy Greenb45993c2010-12-18 15:13:50 +0000220 int n;
Andy Green0d338332011-02-12 11:57:43 +0000221 int m;
Andy Greenb45993c2010-12-18 15:13:50 +0000222 size_t len;
Andy Green0d338332011-02-12 11:57:43 +0000223 int accept_fd;
224 unsigned int clilen;
225 struct sockaddr_in cli_addr;
Andy Greenb45993c2010-12-18 15:13:50 +0000226
Andy Green0d338332011-02-12 11:57:43 +0000227 if (wsi == NULL)
228 return 1;
Andy Green8f037e42010-12-19 22:13:26 +0000229
Andy Green0d338332011-02-12 11:57:43 +0000230 switch (wsi->mode) {
231 case LWS_CONNMODE_SERVER_LISTENER:
232
233 /* pollin means a client has connected to us then */
234
235 if (!pollfd->revents & POLLIN)
236 break;
237
238 /* listen socket got an unencrypted connection... */
239
240 clilen = sizeof(cli_addr);
241 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
242 &clilen);
243 if (accept_fd < 0) {
244 fprintf(stderr, "ERROR on accept");
245 break;
246 }
247
248 if (this->fds_count >= MAX_CLIENTS) {
Andy Green3221f922011-02-12 13:14:11 +0000249 fprintf(stderr, "too busy to accept new client\n");
Andy Green0d338332011-02-12 11:57:43 +0000250 close(accept_fd);
251 break;
252 }
253
Andy Green07034092011-02-13 08:37:12 +0000254 /*
255 * look at who we connected to and give user code a chance
256 * to reject based on client IP. There's no protocol selected
257 * yet so we issue this to protocols[0]
258 */
259
260 if ((this->protocols[0].callback)(wsi,
261 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
262 (void*)(long)accept_fd, NULL, 0)) {
263 fprintf(stderr, "Callback denied network connection\n");
264 close(accept_fd);
265 break;
266 }
267
Andy Green0d338332011-02-12 11:57:43 +0000268 /* accepting connection to main listener */
269
270 new_wsi = malloc(sizeof(struct libwebsocket));
271 if (new_wsi == NULL) {
272 fprintf(stderr, "Out of memory for new connection\n");
273 break;
274 }
275
276 memset(new_wsi, 0, sizeof (struct libwebsocket));
277 new_wsi->sock = accept_fd;
278
279#ifdef LWS_OPENSSL_SUPPORT
280 new_wsi->ssl = NULL;
281 this->ssl_ctx = NULL;
282
283 if (this->use_ssl) {
284
285 new_wsi->ssl = SSL_new(this->ssl_ctx);
286 if (new_wsi->ssl == NULL) {
287 fprintf(stderr, "SSL_new failed: %s\n",
288 ERR_error_string(SSL_get_error(
289 new_wsi->ssl, 0), NULL));
290 free(new_wsi);
291 break;
292 }
293
294 SSL_set_fd(new_wsi->ssl, accept_fd);
295
296 n = SSL_accept(new_wsi->ssl);
297 if (n != 1) {
298 /*
299 * browsers seem to probe with various
300 * ssl params which fail then retry
301 * and succeed
302 */
303 debug("SSL_accept failed skt %u: %s\n",
304 pollfd->fd,
305 ERR_error_string(SSL_get_error(
306 new_wsi->ssl, n), NULL));
307 SSL_free(
308 new_wsi->ssl);
309 free(new_wsi);
310 break;
311 }
312 debug("accepted new SSL conn "
313 "port %u on fd=%d SSL ver %s\n",
314 ntohs(cli_addr.sin_port), accept_fd,
315 SSL_get_version(new_wsi->ssl));
316
317 } else
318#endif
319 debug("accepted new conn port %u on fd=%d\n",
320 ntohs(cli_addr.sin_port), accept_fd);
321
322 /* intialize the instance struct */
323
324 new_wsi->state = WSI_STATE_HTTP;
325 new_wsi->name_buffer_pos = 0;
326 new_wsi->mode = LWS_CONNMODE_WS_SERVING;
327
328 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
329 new_wsi->utf8_token[n].token = NULL;
330 new_wsi->utf8_token[n].token_len = 0;
331 }
332
333 /*
334 * these can only be set once the protocol is known
335 * we set an unestablished connection's protocol pointer
336 * to the start of the supported list, so it can look
337 * for matching ones during the handshake
338 */
339 new_wsi->protocol = this->protocols;
340 new_wsi->user_space = NULL;
341
342 /*
343 * Default protocol is 76 / 00
344 * After 76, there's a header specified to inform which
345 * draft the client wants, when that's seen we modify
346 * the individual connection's spec revision accordingly
347 */
348 new_wsi->ietf_spec_revision = 0;
349
350 insert_wsi(this, new_wsi);
351
Andy Green0d338332011-02-12 11:57:43 +0000352 /*
353 * make sure NO events are seen yet on this new socket
354 * (otherwise we inherit old fds[client].revents from
355 * previous socket there and die mysteriously! )
356 */
357 this->fds[this->fds_count].revents = 0;
358
359 this->fds[this->fds_count].events = POLLIN;
360 this->fds[this->fds_count++].fd = accept_fd;
361
Andy Green3221f922011-02-12 13:14:11 +0000362 /* external POLL support via protocol 0 */
363 this->protocols[0].callback(new_wsi,
364 LWS_CALLBACK_ADD_POLL_FD,
365 (void *)(long)accept_fd, NULL, POLLIN);
366
Andy Green0d338332011-02-12 11:57:43 +0000367 break;
368
369 case LWS_CONNMODE_BROADCAST_PROXY_LISTENER:
370
371 /* as we are listening, POLLIN means accept() is needed */
372
373 if (!pollfd->revents & POLLIN)
374 break;
375
376 /* listen socket got an unencrypted connection... */
377
378 clilen = sizeof(cli_addr);
379 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
380 &clilen);
381 if (accept_fd < 0) {
382 fprintf(stderr, "ERROR on accept");
383 break;
384 }
385
386 if (this->fds_count >= MAX_CLIENTS) {
Andy Green3221f922011-02-12 13:14:11 +0000387 fprintf(stderr, "too busy to accept new broadcast "
388 "proxy client\n");
Andy Green0d338332011-02-12 11:57:43 +0000389 close(accept_fd);
390 break;
391 }
392
393 /* create a dummy wsi for the connection and add it */
394
395 new_wsi = malloc(sizeof(struct libwebsocket));
396 memset(new_wsi, 0, sizeof (struct libwebsocket));
397 new_wsi->sock = accept_fd;
398 new_wsi->mode = LWS_CONNMODE_BROADCAST_PROXY;
399 new_wsi->state = WSI_STATE_ESTABLISHED;
400 /* note which protocol we are proxying */
401 new_wsi->protocol_index_for_broadcast_proxy =
402 wsi->protocol_index_for_broadcast_proxy;
403 insert_wsi(this, new_wsi);
404
405 /* add connected socket to internal poll array */
406
407 this->fds[this->fds_count].revents = 0;
408 this->fds[this->fds_count].events = POLLIN;
409 this->fds[this->fds_count++].fd = accept_fd;
410
Andy Green3221f922011-02-12 13:14:11 +0000411 /* external POLL support via protocol 0 */
412 this->protocols[0].callback(new_wsi,
413 LWS_CALLBACK_ADD_POLL_FD,
414 (void *)(long)accept_fd, NULL, POLLIN);
415
Andy Green0d338332011-02-12 11:57:43 +0000416 break;
417
418 case LWS_CONNMODE_BROADCAST_PROXY:
Andy Green8f037e42010-12-19 22:13:26 +0000419
Andy Greenb45993c2010-12-18 15:13:50 +0000420 /* handle session socket closed */
Andy Green8f037e42010-12-19 22:13:26 +0000421
Andy Green0d338332011-02-12 11:57:43 +0000422 if (pollfd->revents & (POLLERR | POLLHUP)) {
Andy Green8f037e42010-12-19 22:13:26 +0000423
Andy Green0d338332011-02-12 11:57:43 +0000424 debug("Session Socket %p (fd=%d) dead\n",
425 (void *)wsi, accept_fd);
Andy Greenb45993c2010-12-18 15:13:50 +0000426
Andy Green0d338332011-02-12 11:57:43 +0000427 libwebsocket_close_and_free_session(wsi);
Andy Greenb45993c2010-12-18 15:13:50 +0000428 goto nuke_this;
429 }
Andy Green8f037e42010-12-19 22:13:26 +0000430
Andy Green90c7cbc2011-01-27 06:26:52 +0000431 /* the guy requested a callback when it was OK to write */
432
Andy Green0d338332011-02-12 11:57:43 +0000433 if (pollfd->revents & POLLOUT) {
Andy Green90c7cbc2011-01-27 06:26:52 +0000434
Andy Green0d338332011-02-12 11:57:43 +0000435 /* one shot */
Andy Green90c7cbc2011-01-27 06:26:52 +0000436
Andy Green0d338332011-02-12 11:57:43 +0000437 pollfd->events &= ~POLLOUT;
438
Andy Green3221f922011-02-12 13:14:11 +0000439 /* external POLL support via protocol 0 */
440 this->protocols[0].callback(wsi,
441 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
442 (void *)(long)wsi->sock, NULL, POLLOUT);
443
Andy Green0d338332011-02-12 11:57:43 +0000444 wsi->protocol->callback(wsi,
Andy Green90c7cbc2011-01-27 06:26:52 +0000445 LWS_CALLBACK_CLIENT_WRITEABLE,
Andy Green0d338332011-02-12 11:57:43 +0000446 wsi->user_space,
Andy Green90c7cbc2011-01-27 06:26:52 +0000447 NULL, 0);
448 }
449
Andy Greenb45993c2010-12-18 15:13:50 +0000450 /* any incoming data ready? */
451
Andy Green0d338332011-02-12 11:57:43 +0000452 if (!(pollfd->revents & POLLIN))
453 break;
Andy Greenb45993c2010-12-18 15:13:50 +0000454
Andy Green0d338332011-02-12 11:57:43 +0000455 /* get the issued broadcast payload from the socket */
Andy Greenb45993c2010-12-18 15:13:50 +0000456
Andy Green0d338332011-02-12 11:57:43 +0000457 len = read(pollfd->fd, buf + LWS_SEND_BUFFER_PRE_PADDING,
458 MAX_BROADCAST_PAYLOAD);
459 if (len < 0) {
460 fprintf(stderr, "Error reading broadcast payload\n");
461 break;;
462 }
Andy Greenb45993c2010-12-18 15:13:50 +0000463
Andy Green0d338332011-02-12 11:57:43 +0000464 /* broadcast it to all guys with this protocol index */
Andy Green8f037e42010-12-19 22:13:26 +0000465
Andy Green0d338332011-02-12 11:57:43 +0000466 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Green8f037e42010-12-19 22:13:26 +0000467
Andy Green0d338332011-02-12 11:57:43 +0000468 for (m = 0; m < this->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +0000469
Andy Green0d338332011-02-12 11:57:43 +0000470 new_wsi = this->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +0000471
Andy Green0d338332011-02-12 11:57:43 +0000472 /* only to clients we are serving to */
Andy Greenb45993c2010-12-18 15:13:50 +0000473
Andy Green0d338332011-02-12 11:57:43 +0000474 if (new_wsi->mode != LWS_CONNMODE_WS_SERVING)
Andy Greenb45993c2010-12-18 15:13:50 +0000475 continue;
476
477 /*
478 * never broadcast to non-established
479 * connection
480 */
481
Andy Green0d338332011-02-12 11:57:43 +0000482 if (new_wsi->state != WSI_STATE_ESTABLISHED)
Andy Green4739e5c2011-01-22 12:51:57 +0000483 continue;
484
Andy Greenb45993c2010-12-18 15:13:50 +0000485 /*
486 * only broadcast to connections using
487 * the requested protocol
488 */
489
Andy Green0d338332011-02-12 11:57:43 +0000490 if (new_wsi->protocol->protocol_index !=
491 wsi->protocol_index_for_broadcast_proxy)
Andy Greenb45993c2010-12-18 15:13:50 +0000492 continue;
493
Andy Green8f037e42010-12-19 22:13:26 +0000494 /* broadcast it to this connection */
495
Andy Green0d338332011-02-12 11:57:43 +0000496 new_wsi->protocol->callback(new_wsi,
Andy Green8f037e42010-12-19 22:13:26 +0000497 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +0000498 new_wsi->user_space,
Andy Green0ca6a172010-12-19 20:50:01 +0000499 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
Andy Greenb45993c2010-12-18 15:13:50 +0000500 }
Andy Green0d338332011-02-12 11:57:43 +0000501 }
502 break;
Andy Greenb45993c2010-12-18 15:13:50 +0000503
Andy Green0d338332011-02-12 11:57:43 +0000504 case LWS_CONNMODE_WS_SERVING:
505 case LWS_CONNMODE_WS_CLIENT:
506
507 /* handle session socket closed */
508
509 if (pollfd->revents & (POLLERR | POLLHUP)) {
510
511 debug("Session Socket %p (fd=%d) dead\n",
512 (void *)wsi, pollfd->fd);
513
514 libwebsocket_close_and_free_session(wsi);
515 goto nuke_this;
Andy Greenb45993c2010-12-18 15:13:50 +0000516 }
517
Andy Green0d338332011-02-12 11:57:43 +0000518 /* the guy requested a callback when it was OK to write */
519
520 if (pollfd->revents & POLLOUT) {
521
522 pollfd->events &= ~POLLOUT;
523
Andy Green3221f922011-02-12 13:14:11 +0000524 /* external POLL support via protocol 0 */
525 this->protocols[0].callback(wsi,
526 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
527 (void *)(long)wsi->sock, NULL, POLLOUT);
528
Andy Green0d338332011-02-12 11:57:43 +0000529 wsi->protocol->callback(wsi,
530 LWS_CALLBACK_CLIENT_WRITEABLE,
531 wsi->user_space,
532 NULL, 0);
533 }
534
535 /* any incoming data ready? */
536
537 if (!(pollfd->revents & POLLIN))
538 break;
539
Andy Greenb45993c2010-12-18 15:13:50 +0000540#ifdef LWS_OPENSSL_SUPPORT
Andy Green0d338332011-02-12 11:57:43 +0000541 if (wsi->ssl)
542 n = SSL_read(wsi->ssl, buf, sizeof buf);
Andy Greenb45993c2010-12-18 15:13:50 +0000543 else
544#endif
Andy Green0d338332011-02-12 11:57:43 +0000545 n = recv(pollfd->fd, buf, sizeof buf, 0);
Andy Greenb45993c2010-12-18 15:13:50 +0000546
547 if (n < 0) {
548 fprintf(stderr, "Socket read returned %d\n", n);
Andy Green0d338332011-02-12 11:57:43 +0000549 break;;
Andy Greenb45993c2010-12-18 15:13:50 +0000550 }
551 if (!n) {
Andy Green0d338332011-02-12 11:57:43 +0000552 libwebsocket_close_and_free_session(wsi);
Andy Greenb45993c2010-12-18 15:13:50 +0000553 goto nuke_this;
554 }
555
Andy Greenb45993c2010-12-18 15:13:50 +0000556 /* service incoming data */
557
Andy Green0d338332011-02-12 11:57:43 +0000558 n = libwebsocket_read(wsi, buf, n);
Andy Green6964bb52011-01-23 16:50:33 +0000559 if (n >= 0)
Andy Green0d338332011-02-12 11:57:43 +0000560 break;;
Andy Greenb45993c2010-12-18 15:13:50 +0000561 /*
562 * it closed and nuked wsi[client], so remove the
563 * socket handle and wsi from our service list
564 */
565nuke_this:
566
567 debug("nuking wsi %p, fsd_count = %d\n",
Andy Green0d338332011-02-12 11:57:43 +0000568 (void *)wsi, this->fds_count - 1);
569
570 delete_from_fd(this, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +0000571
572 this->fds_count--;
Andy Green0d338332011-02-12 11:57:43 +0000573 for (n = 0; n < this->fds_count; n++)
574 if (this->fds[n].fd == pollfd->fd) {
575 while (n < this->fds_count) {
576 this->fds[n] = this->fds[n + 1];
577 n++;
578 }
579 n = this->fds_count;
580 }
Andy Green6964bb52011-01-23 16:50:33 +0000581
Andy Green3221f922011-02-12 13:14:11 +0000582 /* external POLL support via protocol 0 */
583 this->protocols[0].callback(wsi,
584 LWS_CALLBACK_DEL_POLL_FD,
585 (void *)(long)pollfd->fd, NULL, 0);
586
587
Andy Green0d338332011-02-12 11:57:43 +0000588 break;
Andy Greenb45993c2010-12-18 15:13:50 +0000589 }
590
591 return 0;
592}
593
Andy Green0d338332011-02-12 11:57:43 +0000594
Andy Green6964bb52011-01-23 16:50:33 +0000595/**
596 * libwebsocket_context_destroy() - Destroy the websocket context
597 * @this: Websocket context
598 *
599 * This function closes any active connections and then frees the
600 * context. After calling this, any further use of the context is
601 * undefined.
602 */
603void
604libwebsocket_context_destroy(struct libwebsocket_context *this)
605{
Andy Green0d338332011-02-12 11:57:43 +0000606 int n;
607 int m;
608 struct libwebsocket *wsi;
Andy Green6964bb52011-01-23 16:50:33 +0000609
Andy Green0d338332011-02-12 11:57:43 +0000610 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
611
612 for (m = 0; m < this->fd_hashtable[n].length; m++) {
613
614 wsi = this->fd_hashtable[n].wsi[m];
615
616 switch (wsi->mode) {
617 case LWS_CONNMODE_WS_SERVING:
618 libwebsocket_close_and_free_session(wsi);
619 break;
620 case LWS_CONNMODE_WS_CLIENT:
621 libwebsocket_client_close(wsi);
622 break;
623 default:
624 break;
625 }
Andy Greenf3d3b402011-02-09 07:16:34 +0000626 }
Andy Green0d338332011-02-12 11:57:43 +0000627 }
Andy Green6964bb52011-01-23 16:50:33 +0000628
Andy Green44eee682011-02-10 09:32:24 +0000629 close(this->fd_random);
630
Andy Green6964bb52011-01-23 16:50:33 +0000631#ifdef LWS_OPENSSL_SUPPORT
Andy Green44eee682011-02-10 09:32:24 +0000632 if (this->ssl_ctx)
Andy Green90c7cbc2011-01-27 06:26:52 +0000633 SSL_CTX_free(this->ssl_ctx);
Andy Green44eee682011-02-10 09:32:24 +0000634 if (this->ssl_client_ctx)
Andy Green5e1fa172011-02-10 09:07:05 +0000635 SSL_CTX_free(this->ssl_client_ctx);
Andy Green6964bb52011-01-23 16:50:33 +0000636#endif
637
Andy Green44eee682011-02-10 09:32:24 +0000638 free(this);
Andy Green6964bb52011-01-23 16:50:33 +0000639}
640
641/**
642 * libwebsocket_service() - Service any pending websocket activity
643 * @this: Websocket context
644 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
645 * service otherwise block and service immediately, returning
646 * after the timeout if nothing needed service.
647 *
648 * This function deals with any pending websocket traffic, for three
649 * kinds of event. It handles these events on both server and client
650 * types of connection the same.
651 *
652 * 1) Accept new connections to our context's server
653 *
654 * 2) Perform pending broadcast writes initiated from other forked
655 * processes (effectively serializing asynchronous broadcasts)
656 *
657 * 3) Call the receive callback for incoming frame data received by
658 * server or client connections.
659 *
660 * You need to call this service function periodically to all the above
661 * functions to happen; if your application is single-threaded you can
662 * just call it in your main event loop.
663 *
664 * Alternatively you can fork a new process that asynchronously handles
665 * calling this service in a loop. In that case you are happy if this
666 * call blocks your thread until it needs to take care of something and
667 * would call it with a large nonzero timeout. Your loop then takes no
668 * CPU while there is nothing happening.
669 *
670 * If you are calling it in a single-threaded app, you don't want it to
671 * wait around blocking other things in your loop from happening, so you
672 * would call it with a timeout_ms of 0, so it returns immediately if
673 * nothing is pending, or as soon as it services whatever was pending.
674 */
675
Andy Greenb45993c2010-12-18 15:13:50 +0000676
Andy Greene92cd172011-01-19 13:11:55 +0000677int
678libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
679{
680 int n;
Andy Greene92cd172011-01-19 13:11:55 +0000681
682 /* stay dead once we are dead */
683
684 if (this == NULL)
685 return 1;
686
Andy Green0d338332011-02-12 11:57:43 +0000687 /* wait for something to need service */
Andy Green4739e5c2011-01-22 12:51:57 +0000688
Andy Green0d338332011-02-12 11:57:43 +0000689 n = poll(this->fds, this->fds_count, timeout_ms);
Andy Green3221f922011-02-12 13:14:11 +0000690 if (n == 0) /* poll timeout */
691 return 0;
Andy Greene92cd172011-01-19 13:11:55 +0000692
693 if (n < 0 || this->fds[0].revents & (POLLERR | POLLHUP)) {
Andy Green5e1fa172011-02-10 09:07:05 +0000694 /*
Andy Greene92cd172011-01-19 13:11:55 +0000695 fprintf(stderr, "Listen Socket dead\n");
Andy Green5e1fa172011-02-10 09:07:05 +0000696 */
Andy Green0d338332011-02-12 11:57:43 +0000697 return 1;
Andy Greene92cd172011-01-19 13:11:55 +0000698 }
Andy Greene92cd172011-01-19 13:11:55 +0000699
700 /* handle accept on listening socket? */
701
Andy Green0d338332011-02-12 11:57:43 +0000702 for (n = 0; n < this->fds_count; n++)
703 if (this->fds[n].revents)
704 libwebsocket_service_fd(this, &this->fds[n]);
Andy Greene92cd172011-01-19 13:11:55 +0000705
706 return 0;
Andy Greene92cd172011-01-19 13:11:55 +0000707}
708
Andy Green90c7cbc2011-01-27 06:26:52 +0000709/**
710 * libwebsocket_callback_on_writable() - Request a callback when this socket
711 * becomes able to be written to without
712 * blocking
Andy Green3221f922011-02-12 13:14:11 +0000713 * *
Andy Green90c7cbc2011-01-27 06:26:52 +0000714 * @wsi: Websocket connection instance to get callback for
715 */
716
717int
718libwebsocket_callback_on_writable(struct libwebsocket *wsi)
719{
720 struct libwebsocket_context *this = wsi->protocol->owning_server;
721 int n;
722
Andy Green0d338332011-02-12 11:57:43 +0000723 for (n = 0; n < this->fds_count; n++)
724 if (this->fds[n].fd == wsi->sock) {
Andy Green90c7cbc2011-01-27 06:26:52 +0000725 this->fds[n].events |= POLLOUT;
Andy Green3221f922011-02-12 13:14:11 +0000726 n = this->fds_count;
Andy Green90c7cbc2011-01-27 06:26:52 +0000727 }
728
Andy Green3221f922011-02-12 13:14:11 +0000729 /* external POLL support via protocol 0 */
730 this->protocols[0].callback(wsi,
731 LWS_CALLBACK_SET_MODE_POLL_FD,
732 (void *)(long)wsi->sock, NULL, POLLOUT);
733
Andy Green90c7cbc2011-01-27 06:26:52 +0000734 return 1;
735}
736
737/**
738 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
739 * all connections using the given protocol when it
740 * becomes possible to write to each socket without
741 * blocking in turn.
742 *
743 * @protocol: Protocol whose connections will get callbacks
744 */
745
746int
747libwebsocket_callback_on_writable_all_protocol(
748 const struct libwebsocket_protocols *protocol)
749{
750 struct libwebsocket_context *this = protocol->owning_server;
751 int n;
Andy Green0d338332011-02-12 11:57:43 +0000752 int m;
753 struct libwebsocket *wsi;
Andy Green90c7cbc2011-01-27 06:26:52 +0000754
Andy Green0d338332011-02-12 11:57:43 +0000755 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
756
757 for (m = 0; m < this->fd_hashtable[n].length; m++) {
758
759 wsi = this->fd_hashtable[n].wsi[m];
760
761 if (wsi->protocol == protocol)
762 libwebsocket_callback_on_writable(wsi);
763 }
764 }
Andy Green90c7cbc2011-01-27 06:26:52 +0000765
766 return 0;
767}
768
Andy Greena6cbece2011-01-27 20:06:03 +0000769
770/**
771 * libwebsocket_get_socket_fd() - returns the socket file descriptor
772 *
773 * You will not need this unless you are doing something special
774 *
775 * @wsi: Websocket connection instance
776 */
777
778int
779libwebsocket_get_socket_fd(struct libwebsocket *wsi)
780{
781 return wsi->sock;
782}
783
Andy Green90c7cbc2011-01-27 06:26:52 +0000784/**
785 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
786 * receieved packets.
787 *
788 * If the output side of a server process becomes choked, this allows flow
789 * control for the input side.
790 *
791 * @wsi: Websocket connection instance to get callback for
792 * @enable: 0 = disable read servicing for this connection, 1 = enable
793 */
794
795int
796libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
797{
798 struct libwebsocket_context *this = wsi->protocol->owning_server;
799 int n;
800
Andy Green0d338332011-02-12 11:57:43 +0000801 for (n = 0; n < this->fds_count; n++)
802 if (this->fds[n].fd == wsi->sock) {
Andy Green90c7cbc2011-01-27 06:26:52 +0000803 if (enable)
804 this->fds[n].events |= POLLIN;
805 else
806 this->fds[n].events &= ~POLLIN;
807
808 return 0;
809 }
810
Andy Green3221f922011-02-12 13:14:11 +0000811 if (enable)
812 /* external POLL support via protocol 0 */
813 this->protocols[0].callback(wsi,
814 LWS_CALLBACK_SET_MODE_POLL_FD,
815 (void *)(long)wsi->sock, NULL, POLLIN);
816 else
817 /* external POLL support via protocol 0 */
818 this->protocols[0].callback(wsi,
819 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
820 (void *)(long)wsi->sock, NULL, POLLIN);
821
822
Andy Green90c7cbc2011-01-27 06:26:52 +0000823 fprintf(stderr, "libwebsocket_callback_on_writable "
824 "unable to find socket\n");
825 return 1;
826}
827
Andy Green2ac5a6f2011-01-28 10:00:18 +0000828/**
829 * libwebsocket_canonical_hostname() - returns this host's hostname
830 *
831 * This is typically used by client code to fill in the host parameter
832 * when making a client connection. You can only call it after the context
833 * has been created.
834 *
835 * @this: Websocket context
836 */
837
838
839extern const char *
840libwebsocket_canonical_hostname(struct libwebsocket_context *this)
841{
842 return (const char *)this->canonical_hostname;
843}
844
845
Andy Green90c7cbc2011-01-27 06:26:52 +0000846static void sigpipe_handler(int x)
847{
848}
849
Andy Greenb45993c2010-12-18 15:13:50 +0000850
Andy Green0d338332011-02-12 11:57:43 +0000851
Andy Greenab990e42010-10-31 12:42:52 +0000852/**
Andy Green4739e5c2011-01-22 12:51:57 +0000853 * libwebsocket_create_context() - Create the websocket handler
854 * @port: Port to listen on... you can use 0 to suppress listening on
Andy Green6964bb52011-01-23 16:50:33 +0000855 * any port, that's what you want if you are not running a
856 * websocket server at all but just using it as a client
Andy Green4f3943a2010-11-12 10:44:16 +0000857 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +0000858 * specific callback for each one. The list is ended with an
859 * entry that has a NULL callback pointer.
Andy Green6964bb52011-01-23 16:50:33 +0000860 * It's not const because we write the owning_server member
Andy Green3faa9c72010-11-08 17:03:03 +0000861 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +0000862 * to listen using SSL, set to the filepath to fetch the
863 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +0000864 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +0000865 * else ignored
Andy Green3faa9c72010-11-08 17:03:03 +0000866 * @gid: group id to change to after setting listen socket, or -1.
867 * @uid: user id to change to after setting listen socket, or -1.
Andy Greenbfb051f2011-02-09 08:49:14 +0000868 * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
Andy Green05464c62010-11-12 10:44:18 +0000869 *
Andy Green8f037e42010-12-19 22:13:26 +0000870 * This function creates the listening socket and takes care
871 * of all initialization in one step.
872 *
Andy Greene92cd172011-01-19 13:11:55 +0000873 * After initialization, it returns a struct libwebsocket_context * that
874 * represents this server. After calling, user code needs to take care
875 * of calling libwebsocket_service() with the context pointer to get the
876 * server's sockets serviced. This can be done in the same process context
877 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +0000878 *
Andy Green8f037e42010-12-19 22:13:26 +0000879 * The protocol callback functions are called for a handful of events
880 * including http requests coming in, websocket connections becoming
881 * established, and data arriving; it's also called periodically to allow
882 * async transmission.
883 *
884 * HTTP requests are sent always to the FIRST protocol in @protocol, since
885 * at that time websocket protocol has not been negotiated. Other
886 * protocols after the first one never see any HTTP callack activity.
887 *
888 * The server created is a simple http server by default; part of the
889 * websocket standard is upgrading this http connection to a websocket one.
890 *
891 * This allows the same server to provide files like scripts and favicon /
892 * images or whatever over http and dynamic data over websockets all in
893 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +0000894 */
Andy Green4ea60062010-10-30 12:15:07 +0100895
Andy Greene92cd172011-01-19 13:11:55 +0000896struct libwebsocket_context *
Andy Green4739e5c2011-01-22 12:51:57 +0000897libwebsocket_create_context(int port,
Andy Greenb45993c2010-12-18 15:13:50 +0000898 struct libwebsocket_protocols *protocols,
Andy Green8f037e42010-12-19 22:13:26 +0000899 const char *ssl_cert_filepath,
900 const char *ssl_private_key_filepath,
Andy Green8014b292011-01-30 20:57:25 +0000901 int gid, int uid, unsigned int options)
Andy Greenff95d7a2010-10-28 22:36:01 +0100902{
903 int n;
Andy Green4739e5c2011-01-22 12:51:57 +0000904 int sockfd = 0;
Andy Green251f6fa2010-11-03 11:13:06 +0000905 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +0100906 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +0000907 int opt = 1;
Andy Green8f037e42010-12-19 22:13:26 +0000908 struct libwebsocket_context *this = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +0000909 unsigned int slen;
Andy Green9659f372011-01-27 22:01:43 +0000910 char *p;
Andy Green2ac5a6f2011-01-28 10:00:18 +0000911 char hostname[1024];
Andy Green42f69142011-01-30 08:10:02 +0000912 struct hostent *he;
Andy Green0d338332011-02-12 11:57:43 +0000913 struct libwebsocket *wsi;
Andy Greenff95d7a2010-10-28 22:36:01 +0100914
Andy Green3faa9c72010-11-08 17:03:03 +0000915#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +0000916 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +0000917 char ssl_err_buf[512];
Andy Green3faa9c72010-11-08 17:03:03 +0000918#endif
919
Andy Green90c7cbc2011-01-27 06:26:52 +0000920 this = malloc(sizeof(struct libwebsocket_context));
921 if (!this) {
922 fprintf(stderr, "No memory for websocket context\n");
923 return NULL;
924 }
925 this->protocols = protocols;
926 this->listen_port = port;
Andy Green9659f372011-01-27 22:01:43 +0000927 this->http_proxy_port = 0;
928 this->http_proxy_address[0] = '\0';
Andy Green8014b292011-01-30 20:57:25 +0000929 this->options = options;
Andy Green0d338332011-02-12 11:57:43 +0000930 this->fds_count = 0;
Andy Green9659f372011-01-27 22:01:43 +0000931
Andy Green44eee682011-02-10 09:32:24 +0000932 this->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
933 if (this->fd_random < 0) {
934 fprintf(stderr, "Unable to open random device %s %d\n",
935 SYSTEM_RANDOM_FILEPATH, this->fd_random);
936 return NULL;
937 }
938
Andy Green2ac5a6f2011-01-28 10:00:18 +0000939 /* find canonical hostname */
940
941 hostname[(sizeof hostname) - 1] = '\0';
942 gethostname(hostname, (sizeof hostname) - 1);
943 he = gethostbyname(hostname);
944 strncpy(this->canonical_hostname, he->h_name,
945 sizeof this->canonical_hostname - 1);
946 this->canonical_hostname[sizeof this->canonical_hostname - 1] = '\0';
Andy Green1efb63c2011-02-06 17:42:06 +0000947 fprintf(stderr, " canonical hostname = '%s'\n",
948 this->canonical_hostname);
Andy Green2ac5a6f2011-01-28 10:00:18 +0000949
Andy Green9659f372011-01-27 22:01:43 +0000950 /* split the proxy ads:port if given */
951
952 p = getenv("http_proxy");
953 if (p) {
954 strncpy(this->http_proxy_address, p,
955 sizeof this->http_proxy_address - 1);
956 this->http_proxy_address[
957 sizeof this->http_proxy_address - 1] = '\0';
958
959 p = strchr(this->http_proxy_address, ':');
960 if (p == NULL) {
961 fprintf(stderr, "http_proxy needs to be ads:port\n");
962 return NULL;
963 }
964 *p = '\0';
965 this->http_proxy_port = atoi(p + 1);
966
967 fprintf(stderr, "Using proxy %s:%u\n",
968 this->http_proxy_address,
969 this->http_proxy_port);
970 }
Andy Green90c7cbc2011-01-27 06:26:52 +0000971
972 if (port) {
973
Andy Green3faa9c72010-11-08 17:03:03 +0000974#ifdef LWS_OPENSSL_SUPPORT
Andy Green90c7cbc2011-01-27 06:26:52 +0000975 this->use_ssl = ssl_cert_filepath != NULL &&
976 ssl_private_key_filepath != NULL;
977 if (this->use_ssl)
978 fprintf(stderr, " Compiled with SSL support, "
979 "using it\n");
980 else
981 fprintf(stderr, " Compiled with SSL support, "
982 "not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +0000983
Andy Green90c7cbc2011-01-27 06:26:52 +0000984#else
985 if (ssl_cert_filepath != NULL &&
986 ssl_private_key_filepath != NULL) {
987 fprintf(stderr, " Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +0000988 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +0000989 }
Andy Green90c7cbc2011-01-27 06:26:52 +0000990 fprintf(stderr, " Compiled without SSL support, "
991 "serving unencrypted\n");
992#endif
993 }
994
995 /* ignore SIGPIPE */
996
997 signal(SIGPIPE, sigpipe_handler);
998
999
1000#ifdef LWS_OPENSSL_SUPPORT
1001
1002 /* basic openssl init */
1003
1004 SSL_library_init();
1005
1006 OpenSSL_add_all_algorithms();
1007 SSL_load_error_strings();
1008
1009 /*
1010 * Firefox insists on SSLv23 not SSLv3
1011 * Konq disables SSLv2 by default now, SSLv23 works
1012 */
1013
1014 method = (SSL_METHOD *)SSLv23_server_method();
1015 if (!method) {
1016 fprintf(stderr, "problem creating ssl method: %s\n",
1017 ERR_error_string(ERR_get_error(), ssl_err_buf));
1018 return NULL;
1019 }
1020 this->ssl_ctx = SSL_CTX_new(method); /* create context */
1021 if (!this->ssl_ctx) {
1022 fprintf(stderr, "problem creating ssl context: %s\n",
1023 ERR_error_string(ERR_get_error(), ssl_err_buf));
1024 return NULL;
1025 }
1026
1027 /* client context */
1028
1029 method = (SSL_METHOD *)SSLv23_client_method();
1030 if (!method) {
1031 fprintf(stderr, "problem creating ssl method: %s\n",
1032 ERR_error_string(ERR_get_error(), ssl_err_buf));
1033 return NULL;
1034 }
1035 this->ssl_client_ctx = SSL_CTX_new(method); /* create context */
1036 if (!this->ssl_client_ctx) {
1037 fprintf(stderr, "problem creating ssl context: %s\n",
1038 ERR_error_string(ERR_get_error(), ssl_err_buf));
1039 return NULL;
1040 }
1041
1042
1043 /* openssl init for cert verification (used with client sockets) */
1044
1045 if (!SSL_CTX_load_verify_locations(this->ssl_client_ctx, NULL,
1046 LWS_OPENSSL_CLIENT_CERTS)) {
1047 fprintf(stderr, "Unable to load SSL Client certs from %s "
1048 "(set by --with-client-cert-dir= in configure) -- "
1049 " client ssl isn't going to work",
1050 LWS_OPENSSL_CLIENT_CERTS);
1051 }
1052
1053 if (this->use_ssl) {
1054
1055 /* openssl init for server sockets */
1056
Andy Green3faa9c72010-11-08 17:03:03 +00001057 /* set the local certificate from CertFile */
Andy Green90c7cbc2011-01-27 06:26:52 +00001058 n = SSL_CTX_use_certificate_file(this->ssl_ctx,
Andy Green3faa9c72010-11-08 17:03:03 +00001059 ssl_cert_filepath, SSL_FILETYPE_PEM);
1060 if (n != 1) {
1061 fprintf(stderr, "problem getting cert '%s': %s\n",
1062 ssl_cert_filepath,
1063 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00001064 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00001065 }
1066 /* set the private key from KeyFile */
Andy Green90c7cbc2011-01-27 06:26:52 +00001067 if (SSL_CTX_use_PrivateKey_file(this->ssl_ctx,
Andy Green018d8eb2010-11-08 21:04:23 +00001068 ssl_private_key_filepath,
Andy Green4739e5c2011-01-22 12:51:57 +00001069 SSL_FILETYPE_PEM) != 1) {
Andy Green018d8eb2010-11-08 21:04:23 +00001070 fprintf(stderr, "ssl problem getting key '%s': %s\n",
1071 ssl_private_key_filepath,
1072 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00001073 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00001074 }
1075 /* verify private key */
Andy Green90c7cbc2011-01-27 06:26:52 +00001076 if (!SSL_CTX_check_private_key(this->ssl_ctx)) {
Andy Green018d8eb2010-11-08 21:04:23 +00001077 fprintf(stderr, "Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +00001078 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00001079 }
1080
1081 /* SSL is happy and has a cert it's content with */
1082 }
1083#endif
Andy Greenb45993c2010-12-18 15:13:50 +00001084
Andy Greendf736162011-01-18 15:39:02 +00001085 /* selftest */
1086
1087 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +00001088 return NULL;
Andy Greendf736162011-01-18 15:39:02 +00001089
Andy Green0d338332011-02-12 11:57:43 +00001090 /* fd hashtable init */
1091
1092 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
1093 this->fd_hashtable[n].length = 0;
1094
Andy Greenb45993c2010-12-18 15:13:50 +00001095 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +00001096
Andy Green4739e5c2011-01-22 12:51:57 +00001097 if (port) {
Andy Green8f037e42010-12-19 22:13:26 +00001098
Andy Green4739e5c2011-01-22 12:51:57 +00001099 sockfd = socket(AF_INET, SOCK_STREAM, 0);
1100 if (sockfd < 0) {
1101 fprintf(stderr, "ERROR opening socket");
1102 return NULL;
1103 }
Andy Green775c0dd2010-10-29 14:15:22 +01001104
Andy Green4739e5c2011-01-22 12:51:57 +00001105 /* allow us to restart even if old sockets in TIME_WAIT */
1106 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
Andy Greene77ddd82010-11-13 10:03:47 +00001107
Andy Green4739e5c2011-01-22 12:51:57 +00001108 bzero((char *) &serv_addr, sizeof(serv_addr));
1109 serv_addr.sin_family = AF_INET;
1110 serv_addr.sin_addr.s_addr = INADDR_ANY;
1111 serv_addr.sin_port = htons(port);
1112
1113 n = bind(sockfd, (struct sockaddr *) &serv_addr,
1114 sizeof(serv_addr));
1115 if (n < 0) {
1116 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
Andy Green8f037e42010-12-19 22:13:26 +00001117 port, n, errno);
Andy Green4739e5c2011-01-22 12:51:57 +00001118 return NULL;
1119 }
Andy Green0d338332011-02-12 11:57:43 +00001120
1121 wsi = malloc(sizeof(struct libwebsocket));
1122 memset(wsi, 0, sizeof (struct libwebsocket));
1123 wsi->sock = sockfd;
1124 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
1125 insert_wsi(this, wsi);
1126
1127 listen(sockfd, 5);
1128 fprintf(stderr, " Listening on port %d\n", port);
1129
1130 /* list in the internal poll array */
1131
1132 this->fds[this->fds_count].fd = sockfd;
1133 this->fds[this->fds_count++].events = POLLIN;
Andy Green3221f922011-02-12 13:14:11 +00001134
1135 /* external POLL support via protocol 0 */
1136 this->protocols[0].callback(wsi,
1137 LWS_CALLBACK_ADD_POLL_FD,
1138 (void *)(long)sockfd, NULL, POLLIN);
1139
Andy Green8f037e42010-12-19 22:13:26 +00001140 }
Andy Greenb45993c2010-12-18 15:13:50 +00001141
Andy Greene77ddd82010-11-13 10:03:47 +00001142 /* drop any root privs for this process */
Andy Green3faa9c72010-11-08 17:03:03 +00001143
1144 if (gid != -1)
1145 if (setgid(gid))
1146 fprintf(stderr, "setgid: %s\n", strerror(errno));
1147 if (uid != -1)
1148 if (setuid(uid))
1149 fprintf(stderr, "setuid: %s\n", strerror(errno));
1150
Andy Greenb45993c2010-12-18 15:13:50 +00001151
1152 /* set up our internal broadcast trigger sockets per-protocol */
1153
Andy Green0d338332011-02-12 11:57:43 +00001154 for (this->count_protocols = 0;
1155 protocols[this->count_protocols].callback;
Andy Greenb45993c2010-12-18 15:13:50 +00001156 this->count_protocols++) {
1157 protocols[this->count_protocols].owning_server = this;
1158 protocols[this->count_protocols].protocol_index =
1159 this->count_protocols;
1160
1161 fd = socket(AF_INET, SOCK_STREAM, 0);
1162 if (fd < 0) {
1163 fprintf(stderr, "ERROR opening socket");
Andy Greene92cd172011-01-19 13:11:55 +00001164 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00001165 }
Andy Green8f037e42010-12-19 22:13:26 +00001166
Andy Greenb45993c2010-12-18 15:13:50 +00001167 /* allow us to restart even if old sockets in TIME_WAIT */
1168 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1169
1170 bzero((char *) &serv_addr, sizeof(serv_addr));
1171 serv_addr.sin_family = AF_INET;
1172 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
1173 serv_addr.sin_port = 0; /* pick the port for us */
1174
1175 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
1176 if (n < 0) {
Andy Green8f037e42010-12-19 22:13:26 +00001177 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
Andy Greenb45993c2010-12-18 15:13:50 +00001178 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +00001179 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00001180 }
1181
1182 slen = sizeof cli_addr;
1183 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
1184 if (n < 0) {
1185 fprintf(stderr, "getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +00001186 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00001187 }
1188 protocols[this->count_protocols].broadcast_socket_port =
1189 ntohs(cli_addr.sin_port);
1190 listen(fd, 5);
1191
1192 debug(" Protocol %s broadcast socket %d\n",
1193 protocols[this->count_protocols].name,
1194 ntohs(cli_addr.sin_port));
1195
Andy Green0d338332011-02-12 11:57:43 +00001196 /* dummy wsi per broadcast proxy socket */
1197
1198 wsi = malloc(sizeof(struct libwebsocket));
1199 memset(wsi, 0, sizeof (struct libwebsocket));
1200 wsi->sock = fd;
1201 wsi->mode = LWS_CONNMODE_BROADCAST_PROXY_LISTENER;
1202 /* note which protocol we are proxying */
1203 wsi->protocol_index_for_broadcast_proxy = this->count_protocols;
1204 insert_wsi(this, wsi);
1205
1206 /* list in internal poll array */
1207
Andy Greenb45993c2010-12-18 15:13:50 +00001208 this->fds[this->fds_count].fd = fd;
1209 this->fds[this->fds_count].events = POLLIN;
Andy Green3221f922011-02-12 13:14:11 +00001210 this->fds[this->fds_count].revents = 0;
Andy Greenb45993c2010-12-18 15:13:50 +00001211 this->fds_count++;
Andy Green3221f922011-02-12 13:14:11 +00001212
1213 /* external POLL support via protocol 0 */
1214 this->protocols[0].callback(wsi,
1215 LWS_CALLBACK_ADD_POLL_FD,
1216 (void *)(long)fd, NULL, POLLIN);
Andy Greenb45993c2010-12-18 15:13:50 +00001217 }
1218
Andy Greene92cd172011-01-19 13:11:55 +00001219 return this;
1220}
Andy Greenb45993c2010-12-18 15:13:50 +00001221
Andy Green4739e5c2011-01-22 12:51:57 +00001222
Andy Greened11a022011-01-20 10:23:50 +00001223#ifndef LWS_NO_FORK
1224
Andy Greene92cd172011-01-19 13:11:55 +00001225/**
1226 * libwebsockets_fork_service_loop() - Optional helper function forks off
1227 * a process for the websocket server loop.
Andy Green6964bb52011-01-23 16:50:33 +00001228 * You don't have to use this but if not, you
1229 * have to make sure you are calling
1230 * libwebsocket_service periodically to service
1231 * the websocket traffic
Andy Greene92cd172011-01-19 13:11:55 +00001232 * @this: server context returned by creation function
1233 */
Andy Greenb45993c2010-12-18 15:13:50 +00001234
Andy Greene92cd172011-01-19 13:11:55 +00001235int
1236libwebsockets_fork_service_loop(struct libwebsocket_context *this)
1237{
Andy Greene92cd172011-01-19 13:11:55 +00001238 int fd;
1239 struct sockaddr_in cli_addr;
1240 int n;
Andy Green3221f922011-02-12 13:14:11 +00001241 int p;
Andy Greenb45993c2010-12-18 15:13:50 +00001242
Andy Greened11a022011-01-20 10:23:50 +00001243 n = fork();
1244 if (n < 0)
1245 return n;
1246
1247 if (!n) {
1248
1249 /* main process context */
1250
Andy Green3221f922011-02-12 13:14:11 +00001251 /*
1252 * set up the proxy sockets to allow broadcast from
1253 * service process context
1254 */
1255
1256 for (p = 0; p < this->count_protocols; p++) {
Andy Greened11a022011-01-20 10:23:50 +00001257 fd = socket(AF_INET, SOCK_STREAM, 0);
1258 if (fd < 0) {
1259 fprintf(stderr, "Unable to create socket\n");
1260 return -1;
1261 }
1262 cli_addr.sin_family = AF_INET;
1263 cli_addr.sin_port = htons(
Andy Green3221f922011-02-12 13:14:11 +00001264 this->protocols[p].broadcast_socket_port);
Andy Greened11a022011-01-20 10:23:50 +00001265 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
1266 n = connect(fd, (struct sockaddr *)&cli_addr,
1267 sizeof cli_addr);
1268 if (n < 0) {
1269 fprintf(stderr, "Unable to connect to "
1270 "broadcast socket %d, %s\n",
Andy Green3221f922011-02-12 13:14:11 +00001271 n, strerror(errno));
Andy Greened11a022011-01-20 10:23:50 +00001272 return -1;
1273 }
1274
Andy Green3221f922011-02-12 13:14:11 +00001275 this->protocols[p].broadcast_socket_user_fd = fd;
Andy Greened11a022011-01-20 10:23:50 +00001276 }
1277
Andy Greene92cd172011-01-19 13:11:55 +00001278 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00001279 }
1280
1281 /* we want a SIGHUP when our parent goes down */
1282 prctl(PR_SET_PDEATHSIG, SIGHUP);
1283
1284 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +00001285
Andy Greene92cd172011-01-19 13:11:55 +00001286 while (1)
1287 if (libwebsocket_service(this, 1000))
1288 return -1;
Andy Green8f037e42010-12-19 22:13:26 +00001289
Andy Green251f6fa2010-11-03 11:13:06 +00001290 return 0;
Andy Greenff95d7a2010-10-28 22:36:01 +01001291}
1292
Andy Greened11a022011-01-20 10:23:50 +00001293#endif
1294
Andy Greenb45993c2010-12-18 15:13:50 +00001295/**
1296 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +00001297 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +00001298 * @wsi: pointer to struct websocket you want to know the protocol of
1299 *
Andy Green8f037e42010-12-19 22:13:26 +00001300 *
1301 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +00001302 * the callback.
1303 */
Andy Greenab990e42010-10-31 12:42:52 +00001304
Andy Greenb45993c2010-12-18 15:13:50 +00001305const struct libwebsocket_protocols *
1306libwebsockets_get_protocol(struct libwebsocket *wsi)
1307{
1308 return wsi->protocol;
1309}
1310
1311/**
Andy Greene92cd172011-01-19 13:11:55 +00001312 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +00001313 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +00001314 * @protocol: pointer to the protocol you will broadcast to all members of
1315 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +00001316 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
1317 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
1318 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +00001319 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +00001320 *
1321 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +00001322 * the given protocol. It does not send the data directly; instead it calls
1323 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
1324 * wants to actually send the data for that connection, the callback itself
1325 * should call libwebsocket_write().
1326 *
1327 * libwebsockets_broadcast() can be called from another fork context without
1328 * having to take any care about data visibility between the processes, it'll
1329 * "just work".
1330 */
1331
1332
1333int
Andy Green8f037e42010-12-19 22:13:26 +00001334libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +00001335 unsigned char *buf, size_t len)
1336{
Andy Green8f037e42010-12-19 22:13:26 +00001337 struct libwebsocket_context *this = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +00001338 int n;
Andy Green0d338332011-02-12 11:57:43 +00001339 int m;
1340 struct libwebsocket * wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00001341
1342 if (!protocol->broadcast_socket_user_fd) {
1343 /*
Andy Greene92cd172011-01-19 13:11:55 +00001344 * We are either running unforked / flat, or we are being
1345 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +00001346 * eg, from a callback. In that case don't use sockets for
1347 * broadcast IPC (since we can't open a socket connection to
1348 * a socket listening on our own thread) but directly do the
1349 * send action.
1350 *
1351 * Locking is not needed because we are by definition being
1352 * called in the poll thread context and are serialized.
1353 */
1354
Andy Green0d338332011-02-12 11:57:43 +00001355 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Greenb45993c2010-12-18 15:13:50 +00001356
Andy Green0d338332011-02-12 11:57:43 +00001357 for (m = 0; m < this->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00001358
Andy Green0d338332011-02-12 11:57:43 +00001359 wsi = this->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00001360
Andy Green0d338332011-02-12 11:57:43 +00001361 if (wsi->mode != LWS_CONNMODE_WS_SERVING)
1362 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00001363
Andy Green0d338332011-02-12 11:57:43 +00001364 /*
1365 * never broadcast to
1366 * non-established connections
1367 */
1368 if (wsi->state != WSI_STATE_ESTABLISHED)
1369 continue;
1370
1371 /* only broadcast to guys using
1372 * requested protocol
1373 */
1374 if (wsi->protocol != protocol)
1375 continue;
1376
1377 wsi->protocol->callback(wsi,
Andy Green8f037e42010-12-19 22:13:26 +00001378 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00001379 wsi->user_space,
Andy Greenb45993c2010-12-18 15:13:50 +00001380 buf, len);
Andy Green0d338332011-02-12 11:57:43 +00001381 }
Andy Greenb45993c2010-12-18 15:13:50 +00001382 }
1383
1384 return 0;
1385 }
1386
Andy Green0ca6a172010-12-19 20:50:01 +00001387 /*
1388 * We're being called from a different process context than the server
1389 * loop. Instead of broadcasting directly, we send our
1390 * payload on a socket to do the IPC; the server process will serialize
1391 * the broadcast action in its main poll() loop.
1392 *
1393 * There's one broadcast socket listening for each protocol supported
1394 * set up when the websocket server initializes
1395 */
1396
Andy Green6964bb52011-01-23 16:50:33 +00001397 n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
Andy Greenb45993c2010-12-18 15:13:50 +00001398
1399 return n;
1400}