blob: f8522b5bb4086e123b5ec003e7c2349909c164f9 [file] [log] [blame]
Andy Green58eaa742011-03-07 17:54:06 +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
Peter Hinz56885f32011-03-02 22:03:47 +000024#ifdef WIN32
25
26#else
27#include <ifaddrs.h>
Andy Green7627af52011-03-09 15:13:52 +000028#include <sys/un.h>
Peter Hinz56885f32011-03-02 22:03:47 +000029#endif
Andy Green2e24da02011-03-05 16:12:04 +000030
31#ifdef LWS_OPENSSL_SUPPORT
32int openssl_websocket_private_data_index;
33#endif
34
Andy Greenbe93fef2011-02-14 20:25:43 +000035/*
36 * In-place str to lower case
37 */
38
39static void
40strtolower(char *s)
41{
42 while (*s) {
43 *s = tolower(*s);
44 s++;
45 }
46}
47
Andy Green0d338332011-02-12 11:57:43 +000048/* file descriptor hash management */
49
50struct libwebsocket *
Peter Hinz56885f32011-03-02 22:03:47 +000051wsi_from_fd(struct libwebsocket_context *context, int fd)
Andy Green0d338332011-02-12 11:57:43 +000052{
53 int h = LWS_FD_HASH(fd);
54 int n = 0;
55
Peter Hinz56885f32011-03-02 22:03:47 +000056 for (n = 0; n < context->fd_hashtable[h].length; n++)
57 if (context->fd_hashtable[h].wsi[n]->sock == fd)
58 return context->fd_hashtable[h].wsi[n];
Andy Green0d338332011-02-12 11:57:43 +000059
60 return NULL;
61}
62
63int
Peter Hinz56885f32011-03-02 22:03:47 +000064insert_wsi(struct libwebsocket_context *context, struct libwebsocket *wsi)
Andy Green0d338332011-02-12 11:57:43 +000065{
66 int h = LWS_FD_HASH(wsi->sock);
67
Peter Hinz56885f32011-03-02 22:03:47 +000068 if (context->fd_hashtable[h].length == MAX_CLIENTS - 1) {
Andy Green0d338332011-02-12 11:57:43 +000069 fprintf(stderr, "hash table overflow\n");
70 return 1;
71 }
72
Peter Hinz56885f32011-03-02 22:03:47 +000073 context->fd_hashtable[h].wsi[context->fd_hashtable[h].length++] = wsi;
Andy Green0d338332011-02-12 11:57:43 +000074
75 return 0;
76}
77
78int
Peter Hinz56885f32011-03-02 22:03:47 +000079delete_from_fd(struct libwebsocket_context *context, int fd)
Andy Green0d338332011-02-12 11:57:43 +000080{
81 int h = LWS_FD_HASH(fd);
82 int n = 0;
83
Peter Hinz56885f32011-03-02 22:03:47 +000084 for (n = 0; n < context->fd_hashtable[h].length; n++)
85 if (context->fd_hashtable[h].wsi[n]->sock == fd) {
86 while (n < context->fd_hashtable[h].length) {
87 context->fd_hashtable[h].wsi[n] =
88 context->fd_hashtable[h].wsi[n + 1];
Andy Green0d338332011-02-12 11:57:43 +000089 n++;
90 }
Peter Hinz56885f32011-03-02 22:03:47 +000091 context->fd_hashtable[h].length--;
Andy Green0d338332011-02-12 11:57:43 +000092
93 return 0;
94 }
95
96 fprintf(stderr, "Failed to find fd %d requested for "
97 "delete in hashtable\n", fd);
98 return 1;
99}
100
Andy Green1f9bf522011-02-14 21:14:37 +0000101#ifdef LWS_OPENSSL_SUPPORT
102static void
103libwebsockets_decode_ssl_error(void)
104{
105 char buf[256];
106 u_long err;
107
108 while ((err = ERR_get_error()) != 0) {
109 ERR_error_string_n(err, buf, sizeof(buf));
110 fprintf(stderr, "*** %s\n", buf);
111 }
112}
113#endif
Andy Green0d338332011-02-12 11:57:43 +0000114
Andy Green32375b72011-02-19 08:32:53 +0000115
116static int
117interface_to_sa(const char* ifname, struct sockaddr_in *addr, size_t addrlen)
118{
119 int rc = -1;
Peter Hinz56885f32011-03-02 22:03:47 +0000120#ifdef WIN32
121 // TODO
122#else
Andy Green32375b72011-02-19 08:32:53 +0000123 struct ifaddrs *ifr;
124 struct ifaddrs *ifc;
125 struct sockaddr_in *sin;
126
127 getifaddrs(&ifr);
128 for (ifc = ifr; ifc != NULL; ifc = ifc->ifa_next) {
129 if (strcmp(ifc->ifa_name, ifname))
130 continue;
131 if (ifc->ifa_addr == NULL)
132 continue;
133 sin = (struct sockaddr_in *)ifc->ifa_addr;
134 if (sin->sin_family != AF_INET)
135 continue;
136 memcpy(addr, sin, addrlen);
137 rc = 0;
138 }
139
140 freeifaddrs(ifr);
Peter Hinz56885f32011-03-02 22:03:47 +0000141#endif
Andy Green32375b72011-02-19 08:32:53 +0000142 return rc;
143}
144
Andy Green8f037e42010-12-19 22:13:26 +0000145void
Peter Hinz56885f32011-03-02 22:03:47 +0000146libwebsocket_close_and_free_session(struct libwebsocket_context *context,
Andy Green687b0182011-02-26 11:04:01 +0000147 struct libwebsocket *wsi, enum lws_close_status reason)
Andy Green251f6fa2010-11-03 11:13:06 +0000148{
Andy Greenb45993c2010-12-18 15:13:50 +0000149 int n;
Andy Green62c54d22011-02-14 09:14:25 +0000150 int old_state;
Andy Green5e1fa172011-02-10 09:07:05 +0000151 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
152 LWS_SEND_BUFFER_POST_PADDING];
Andy Greenc44159f2011-03-07 07:08:18 +0000153 int ret;
154 int m;
155 struct lws_tokens eff_buf;
Andy Greena41314f2011-05-23 10:00:03 +0100156 struct libwebsocket_extension *ext;
Andy Greenb45993c2010-12-18 15:13:50 +0000157
Andy Green4b6fbe12011-02-14 08:03:48 +0000158 if (!wsi)
Andy Greenb45993c2010-12-18 15:13:50 +0000159 return;
160
Andy Green62c54d22011-02-14 09:14:25 +0000161 old_state = wsi->state;
Andy Green251f6fa2010-11-03 11:13:06 +0000162
Andy Green62c54d22011-02-14 09:14:25 +0000163 if (old_state == WSI_STATE_DEAD_SOCKET)
Andy Green5e1fa172011-02-10 09:07:05 +0000164 return;
165
Andy Greenda527df2011-03-07 07:08:12 +0000166 wsi->close_reason = reason;
167
168 /*
Andy Green68b45042011-05-25 21:41:57 +0100169 * are his extensions okay with him closing? Eg he might be a mux
170 * parent and just his ch1 aspect is closing?
171 */
172
173
174 for (n = 0; n < wsi->count_active_extensions; n++) {
175 if (!wsi->active_extensions[n]->callback)
176 continue;
177
178 m = wsi->active_extensions[n]->callback(context,
179 wsi->active_extensions[n], wsi,
180 LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
181 wsi->active_extensions_user[n], NULL, 0);
182
183 /*
184 * if somebody vetoed actually closing him at this time....
185 * up to the extension to track the attempted close, let's
186 * just bail
187 */
188
189 if (m) {
Andy Greencc012472011-11-07 19:53:23 +0800190 debug("extension vetoed close\n");
Andy Green68b45042011-05-25 21:41:57 +0100191 return;
192 }
193 }
194
195
196
197 /*
Andy Greenc44159f2011-03-07 07:08:18 +0000198 * flush any tx pending from extensions, since we may send close packet
199 * if there are problems with send, just nuke the connection
200 */
201
202 ret = 1;
203 while (ret == 1) {
204
205 /* default to nobody has more to spill */
206
207 ret = 0;
208 eff_buf.token = NULL;
209 eff_buf.token_len = 0;
210
211 /* show every extension the new incoming data */
212
213 for (n = 0; n < wsi->count_active_extensions; n++) {
214 m = wsi->active_extensions[n]->callback(
Andy Green46c2ea02011-03-22 09:04:01 +0000215 wsi->protocol->owning_server,
216 wsi->active_extensions[n], wsi,
Andy Greenc44159f2011-03-07 07:08:18 +0000217 LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
218 wsi->active_extensions_user[n], &eff_buf, 0);
219 if (m < 0) {
220 fprintf(stderr, "Extension reports "
221 "fatal error\n");
222 goto just_kill_connection;
223 }
224 if (m)
225 /*
226 * at least one extension told us he has more
227 * to spill, so we will go around again after
228 */
229 ret = 1;
230 }
231
232 /* assuming they left us something to send, send it */
233
234 if (eff_buf.token_len)
235 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
236 eff_buf.token_len))
237 goto just_kill_connection;
238 }
239
240 /*
Andy Greenda527df2011-03-07 07:08:12 +0000241 * signal we are closing, libsocket_write will
242 * add any necessary version-specific stuff. If the write fails,
243 * no worries we are closing anyway. If we didn't initiate this
244 * close, then our state has been changed to
245 * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
246 *
247 * Likewise if it's a second call to close this connection after we
248 * sent the close indication to the peer already, we are in state
249 * WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
250 */
251
252 if (old_state == WSI_STATE_ESTABLISHED &&
253 reason != LWS_CLOSE_STATUS_NOSTATUS) {
Andy Green66a16f32011-05-24 22:07:45 +0100254
Andy Greencc012472011-11-07 19:53:23 +0800255 debug("sending close indication...\n");
Andy Green66a16f32011-05-24 22:07:45 +0100256
Andy Greenda527df2011-03-07 07:08:12 +0000257 n = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING],
258 0, LWS_WRITE_CLOSE);
259 if (!n) {
260 /*
261 * we have sent a nice protocol level indication we
262 * now wish to close, we should not send anything more
263 */
264
265 wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
266
267 /* and we should wait for a reply for a bit */
268
269 libwebsocket_set_timeout(wsi,
270 PENDING_TIMEOUT_CLOSE_ACK, 5);
271
Andy Greencc012472011-11-07 19:53:23 +0800272 debug("sent close indication, awaiting ack\n");
Andy Greenda527df2011-03-07 07:08:12 +0000273
274 return;
275 }
276
277 /* else, the send failed and we should just hang up */
278 }
279
Andy Greenc44159f2011-03-07 07:08:18 +0000280just_kill_connection:
Andy Green66a16f32011-05-24 22:07:45 +0100281
Andy Greencc012472011-11-07 19:53:23 +0800282 debug("libwebsocket_close_and_free_session: just_kill_connection\n");
Andy Green66a16f32011-05-24 22:07:45 +0100283
Andy Greenda527df2011-03-07 07:08:12 +0000284 /*
285 * we won't be servicing or receiving anything further from this guy
286 * remove this fd from wsi mapping hashtable
287 */
Andy Green4b6fbe12011-02-14 08:03:48 +0000288
Andy Greena41314f2011-05-23 10:00:03 +0100289 if (wsi->sock)
290 delete_from_fd(context, wsi->sock);
Andy Green4b6fbe12011-02-14 08:03:48 +0000291
292 /* delete it from the internal poll list if still present */
293
Peter Hinz56885f32011-03-02 22:03:47 +0000294 for (n = 0; n < context->fds_count; n++) {
295 if (context->fds[n].fd != wsi->sock)
Andy Green4b6fbe12011-02-14 08:03:48 +0000296 continue;
Peter Hinz56885f32011-03-02 22:03:47 +0000297 while (n < context->fds_count - 1) {
298 context->fds[n] = context->fds[n + 1];
Andy Green4b6fbe12011-02-14 08:03:48 +0000299 n++;
300 }
Peter Hinz56885f32011-03-02 22:03:47 +0000301 context->fds_count--;
Andy Green4b6fbe12011-02-14 08:03:48 +0000302 /* we only have to deal with one */
Peter Hinz56885f32011-03-02 22:03:47 +0000303 n = context->fds_count;
Andy Green4b6fbe12011-02-14 08:03:48 +0000304 }
305
306 /* remove also from external POLL support via protocol 0 */
Andy Greena41314f2011-05-23 10:00:03 +0100307 if (wsi->sock)
308 context->protocols[0].callback(context, wsi,
Andy Green4b6fbe12011-02-14 08:03:48 +0000309 LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
310
Andy Green251f6fa2010-11-03 11:13:06 +0000311 wsi->state = WSI_STATE_DEAD_SOCKET;
312
Andy Green4b6fbe12011-02-14 08:03:48 +0000313 /* tell the user it's all over for this guy */
314
Andy Greend4302732011-02-28 07:45:29 +0000315 if (wsi->protocol && wsi->protocol->callback &&
Andy Green66a16f32011-05-24 22:07:45 +0100316 ((old_state == WSI_STATE_ESTABLISHED) ||
317 (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
318 (old_state == WSI_STATE_AWAITING_CLOSE_ACK))) {
Andy Greencc012472011-11-07 19:53:23 +0800319 debug("calling back CLOSED\n");
Peter Hinz56885f32011-03-02 22:03:47 +0000320 wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
Andy Greene77ddd82010-11-13 10:03:47 +0000321 wsi->user_space, NULL, 0);
Andy Greencc012472011-11-07 19:53:23 +0800322 } else
323 debug("not calling back closed due to old_state=%d\n",
324 old_state);
325
Andy Green251f6fa2010-11-03 11:13:06 +0000326
Andy Greenef660a92011-03-06 10:29:38 +0000327 /* deallocate any active extension contexts */
328
329 for (n = 0; n < wsi->count_active_extensions; n++) {
330 if (!wsi->active_extensions[n]->callback)
331 continue;
332
Andy Green46c2ea02011-03-22 09:04:01 +0000333 wsi->active_extensions[n]->callback(context,
334 wsi->active_extensions[n], wsi,
335 LWS_EXT_CALLBACK_DESTROY,
336 wsi->active_extensions_user[n], NULL, 0);
Andy Greenef660a92011-03-06 10:29:38 +0000337
338 free(wsi->active_extensions_user[n]);
339 }
340
Andy Greena41314f2011-05-23 10:00:03 +0100341 /*
342 * inform all extensions in case they tracked this guy out of band
343 * even though not active on him specifically
344 */
345
346 ext = context->extensions;
347 while (ext && ext->callback) {
348 ext->callback(context, ext, wsi,
349 LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
350 NULL, NULL, 0);
351 ext++;
352 }
353
Andy Greenef660a92011-03-06 10:29:38 +0000354 /* free up his parsing allocations */
Andy Green4b6fbe12011-02-14 08:03:48 +0000355
Andy Green251f6fa2010-11-03 11:13:06 +0000356 for (n = 0; n < WSI_TOKEN_COUNT; n++)
357 if (wsi->utf8_token[n].token)
358 free(wsi->utf8_token[n].token);
359
Andy Greena41314f2011-05-23 10:00:03 +0100360 if (wsi->c_address)
361 free(wsi->c_address);
362
Andy Green0ca6a172010-12-19 20:50:01 +0000363/* fprintf(stderr, "closing fd=%d\n", wsi->sock); */
Andy Green251f6fa2010-11-03 11:13:06 +0000364
Andy Green3faa9c72010-11-08 17:03:03 +0000365#ifdef LWS_OPENSSL_SUPPORT
Andy Green90c7cbc2011-01-27 06:26:52 +0000366 if (wsi->ssl) {
Andy Green3faa9c72010-11-08 17:03:03 +0000367 n = SSL_get_fd(wsi->ssl);
368 SSL_shutdown(wsi->ssl);
Peter Hinz56885f32011-03-02 22:03:47 +0000369#ifdef WIN32
370 closesocket(n);
371#else
Andy Green3faa9c72010-11-08 17:03:03 +0000372 close(n);
Peter Hinz56885f32011-03-02 22:03:47 +0000373#endif
Andy Green3faa9c72010-11-08 17:03:03 +0000374 SSL_free(wsi->ssl);
375 } else {
376#endif
377 shutdown(wsi->sock, SHUT_RDWR);
Peter Hinz56885f32011-03-02 22:03:47 +0000378#ifdef WIN32
Andy Green66a16f32011-05-24 22:07:45 +0100379 if (wsi->sock)
380 closesocket(wsi->sock);
Peter Hinz56885f32011-03-02 22:03:47 +0000381#else
Andy Green66a16f32011-05-24 22:07:45 +0100382 if (wsi->sock)
383 close(wsi->sock);
Peter Hinz56885f32011-03-02 22:03:47 +0000384#endif
Andy Green3faa9c72010-11-08 17:03:03 +0000385#ifdef LWS_OPENSSL_SUPPORT
386 }
387#endif
Andy Green4f3943a2010-11-12 10:44:16 +0000388 if (wsi->user_space)
389 free(wsi->user_space);
390
Andy Green251f6fa2010-11-03 11:13:06 +0000391 free(wsi);
392}
393
Andy Green07034092011-02-13 08:37:12 +0000394/**
Andy Greenf7ee5492011-02-13 09:04:21 +0000395 * libwebsockets_hangup_on_client() - Server calls to terminate client
396 * connection
Peter Hinz56885f32011-03-02 22:03:47 +0000397 * @context: libwebsockets context
Andy Greenf7ee5492011-02-13 09:04:21 +0000398 * @fd: Connection socket descriptor
399 */
400
401void
Peter Hinz56885f32011-03-02 22:03:47 +0000402libwebsockets_hangup_on_client(struct libwebsocket_context *context, int fd)
Andy Greenf7ee5492011-02-13 09:04:21 +0000403{
Peter Hinz56885f32011-03-02 22:03:47 +0000404 struct libwebsocket *wsi = wsi_from_fd(context, fd);
Andy Greenf7ee5492011-02-13 09:04:21 +0000405
406 if (wsi == NULL)
407 return;
408
Peter Hinz56885f32011-03-02 22:03:47 +0000409 libwebsocket_close_and_free_session(context, wsi,
Andy Green6da560c2011-02-26 11:06:27 +0000410 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenf7ee5492011-02-13 09:04:21 +0000411}
412
413
414/**
Andy Green07034092011-02-13 08:37:12 +0000415 * libwebsockets_get_peer_addresses() - Get client address information
416 * @fd: Connection socket descriptor
417 * @name: Buffer to take client address name
418 * @name_len: Length of client address name buffer
419 * @rip: Buffer to take client address IP qotted quad
420 * @rip_len: Length of client address IP buffer
421 *
422 * This function fills in @name and @rip with the name and IP of
423 * the client connected with socket descriptor @fd. Names may be
424 * truncated if there is not enough room. If either cannot be
425 * determined, they will be returned as valid zero-length strings.
426 */
427
428void
429libwebsockets_get_peer_addresses(int fd, char *name, int name_len,
430 char *rip, int rip_len)
431{
432 unsigned int len;
433 struct sockaddr_in sin;
434 struct hostent *host;
435 struct hostent *host1;
436 char ip[128];
Andy Greenf92def72011-03-09 15:02:20 +0000437 unsigned char *p;
Andy Green07034092011-02-13 08:37:12 +0000438 int n;
Andy Green7627af52011-03-09 15:13:52 +0000439 struct sockaddr_un *un;
Andy Green07034092011-02-13 08:37:12 +0000440
441 rip[0] = '\0';
442 name[0] = '\0';
443
444 len = sizeof sin;
445 if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
446 perror("getpeername");
447 return;
448 }
449
450 host = gethostbyaddr((char *) &sin.sin_addr, sizeof sin.sin_addr,
451 AF_INET);
452 if (host == NULL) {
453 perror("gethostbyaddr");
454 return;
455 }
456
457 strncpy(name, host->h_name, name_len);
458 name[name_len - 1] = '\0';
459
460 host1 = gethostbyname(host->h_name);
461 if (host1 == NULL)
462 return;
Andy Greenf92def72011-03-09 15:02:20 +0000463 p = (unsigned char *)host1;
Andy Green07034092011-02-13 08:37:12 +0000464 n = 0;
465 while (p != NULL) {
Andy Greenf92def72011-03-09 15:02:20 +0000466 p = (unsigned char *)host1->h_addr_list[n++];
Andy Green07034092011-02-13 08:37:12 +0000467 if (p == NULL)
468 continue;
Peter Hinzbb45a902011-03-10 18:14:01 +0000469 if ((host1->h_addrtype != AF_INET)
470#ifdef AF_LOCAL
471 && (host1->h_addrtype != AF_LOCAL)
472#endif
473 )
Andy Green07034092011-02-13 08:37:12 +0000474 continue;
475
Andy Green7627af52011-03-09 15:13:52 +0000476 if (host1->h_addrtype == AF_INET)
477 sprintf(ip, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
Peter Hinzbb45a902011-03-10 18:14:01 +0000478#ifdef AF_LOCAL
Andy Green7627af52011-03-09 15:13:52 +0000479 else {
480 un = (struct sockaddr_un *)p;
481 strncpy(ip, un->sun_path, sizeof(ip) -1);
482 ip[sizeof(ip) - 1] = '\0';
483 }
Peter Hinzbb45a902011-03-10 18:14:01 +0000484#endif
Andy Green07034092011-02-13 08:37:12 +0000485 p = NULL;
486 strncpy(rip, ip, rip_len);
487 rip[rip_len - 1] = '\0';
488 }
489}
Andy Green9f990342011-02-12 11:57:45 +0000490
Peter Hinz56885f32011-03-02 22:03:47 +0000491int libwebsockets_get_random(struct libwebsocket_context *context,
492 void *buf, int len)
493{
494 int n;
495 char *p = buf;
496
497#ifdef WIN32
498 for (n = 0; n < len; n++)
499 p[n] = (unsigned char)rand();
500#else
501 n = read(context->fd_random, p, len);
502#endif
503
504 return n;
505}
506
Andy Green2836c642011-03-07 20:47:41 +0000507unsigned char *
508libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md)
509{
510 return SHA1(d, n, md);
511}
512
Andy Greeneeaacb32011-03-01 20:44:24 +0000513void libwebsockets_00_spaceout(char *key, int spaces, int seed)
514{
515 char *p;
Peter Hinz56885f32011-03-02 22:03:47 +0000516
Andy Greeneeaacb32011-03-01 20:44:24 +0000517 key++;
518 while (spaces--) {
519 if (*key && (seed & 1))
520 key++;
521 seed >>= 1;
Peter Hinz56885f32011-03-02 22:03:47 +0000522
Andy Greeneeaacb32011-03-01 20:44:24 +0000523 p = key + strlen(key);
524 while (p >= key) {
525 p[1] = p[0];
526 p--;
527 }
528 *key++ = ' ';
529 }
530}
531
532void libwebsockets_00_spam(char *key, int count, int seed)
533{
534 char *p;
535
536 key++;
537 while (count--) {
538
539 if (*key && (seed & 1))
540 key++;
541 seed >>= 1;
542
543 p = key + strlen(key);
544 while (p >= key) {
545 p[1] = p[0];
546 p--;
547 }
548 *key++ = 0x21 + ((seed & 0xffff) % 15);
549 /* 4 would use it up too fast.. not like it matters */
550 seed >>= 1;
551 }
552}
553
Andy Green95a7b5d2011-03-06 10:29:39 +0000554int lws_send_pipe_choked(struct libwebsocket *wsi)
555{
556 struct pollfd fds;
557
558 fds.fd = wsi->sock;
559 fds.events = POLLOUT;
560 fds.revents = 0;
561
562 if (poll(&fds, 1, 0) != 1)
563 return 1;
564
565 if ((fds.revents & POLLOUT) == 0)
566 return 1;
567
568 /* okay to send another packet without blocking */
569
570 return 0;
571}
572
Andy Greena41314f2011-05-23 10:00:03 +0100573int
Andy Green3b84c002011-03-06 13:14:42 +0000574lws_handle_POLLOUT_event(struct libwebsocket_context *context,
575 struct libwebsocket *wsi, struct pollfd *pollfd)
576{
577 struct lws_tokens eff_buf;
578 int n;
579 int ret;
580 int m;
Andy Greena41314f2011-05-23 10:00:03 +0100581 int handled = 0;
Andy Green3b84c002011-03-06 13:14:42 +0000582
Andy Greena41314f2011-05-23 10:00:03 +0100583 for (n = 0; n < wsi->count_active_extensions; n++) {
584 if (!wsi->active_extensions[n]->callback)
585 continue;
586
587 m = wsi->active_extensions[n]->callback(context,
588 wsi->active_extensions[n], wsi,
589 LWS_EXT_CALLBACK_IS_WRITEABLE,
590 wsi->active_extensions_user[n], NULL, 0);
591 if (m > handled)
592 handled = m;
593 }
594
595 if (handled == 1)
596 goto notify_action;
597
598 if (!wsi->extension_data_pending || handled == 2)
Andy Green3b84c002011-03-06 13:14:42 +0000599 goto user_service;
600
601 /*
602 * check in on the active extensions, see if they
603 * had pending stuff to spill... they need to get the
604 * first look-in otherwise sequence will be disordered
605 *
606 * NULL, zero-length eff_buf means just spill pending
607 */
608
609 ret = 1;
610 while (ret == 1) {
611
612 /* default to nobody has more to spill */
613
614 ret = 0;
615 eff_buf.token = NULL;
616 eff_buf.token_len = 0;
617
618 /* give every extension a chance to spill */
619
620 for (n = 0; n < wsi->count_active_extensions; n++) {
621 m = wsi->active_extensions[n]->callback(
Andy Green46c2ea02011-03-22 09:04:01 +0000622 wsi->protocol->owning_server,
623 wsi->active_extensions[n], wsi,
Andy Green3b84c002011-03-06 13:14:42 +0000624 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
625 wsi->active_extensions_user[n], &eff_buf, 0);
626 if (m < 0) {
627 fprintf(stderr, "extension reports fatal error\n");
628 return -1;
629 }
630 if (m)
631 /*
632 * at least one extension told us he has more
633 * to spill, so we will go around again after
634 */
635 ret = 1;
636 }
637
638 /* assuming they gave us something to send, send it */
639
640 if (eff_buf.token_len) {
641 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
642 eff_buf.token_len))
643 return -1;
644 } else
645 continue;
646
647 /* no extension has more to spill */
648
649 if (!ret)
650 continue;
651
652 /*
653 * There's more to spill from an extension, but we just sent
654 * something... did that leave the pipe choked?
655 */
656
657 if (!lws_send_pipe_choked(wsi))
658 /* no we could add more */
659 continue;
660
Andy Greencc012472011-11-07 19:53:23 +0800661 debug("choked in POLLOUT service\n");
Andy Green3b84c002011-03-06 13:14:42 +0000662
663 /*
664 * Yes, he's choked. Leave the POLLOUT masked on so we will
665 * come back here when he is unchoked. Don't call the user
666 * callback to enforce ordering of spilling, he'll get called
667 * when we come back here and there's nothing more to spill.
668 */
669
670 return 0;
671 }
672
673 wsi->extension_data_pending = 0;
674
675user_service:
676 /* one shot */
677
Andy Greena41314f2011-05-23 10:00:03 +0100678 if (pollfd) {
679 pollfd->events &= ~POLLOUT;
Andy Green3b84c002011-03-06 13:14:42 +0000680
Andy Greena41314f2011-05-23 10:00:03 +0100681 /* external POLL support via protocol 0 */
682 context->protocols[0].callback(context, wsi,
683 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
684 (void *)(long)wsi->sock, NULL, POLLOUT);
685 }
686
687notify_action:
Andy Green3b84c002011-03-06 13:14:42 +0000688
Andy Green9e4c2b62011-03-07 20:47:39 +0000689 if (wsi->mode == LWS_CONNMODE_WS_CLIENT)
690 n = LWS_CALLBACK_CLIENT_WRITEABLE;
691 else
692 n = LWS_CALLBACK_SERVER_WRITEABLE;
693
694 wsi->protocol->callback(context, wsi, n, wsi->user_space, NULL, 0);
Andy Green3b84c002011-03-06 13:14:42 +0000695
696 return 0;
697}
698
699
700
Andy Greena41314f2011-05-23 10:00:03 +0100701void
702libwebsocket_service_timeout_check(struct libwebsocket_context *context,
703 struct libwebsocket *wsi, unsigned int sec)
704{
705 int n;
706
707 /*
708 * if extensions want in on it (eg, we are a mux parent)
709 * give them a chance to service child timeouts
710 */
711
712 for (n = 0; n < wsi->count_active_extensions; n++)
713 wsi->active_extensions[n]->callback(
714 context, wsi->active_extensions[n],
715 wsi, LWS_EXT_CALLBACK_1HZ,
716 wsi->active_extensions_user[n], NULL, sec);
717
718 if (!wsi->pending_timeout)
719 return;
720
721 /*
722 * if we went beyond the allowed time, kill the
723 * connection
724 */
725
726 if (sec > wsi->pending_timeout_limit) {
Andy Greencc012472011-11-07 19:53:23 +0800727 debug("TIMEDOUT WAITING\n");
Andy Greena41314f2011-05-23 10:00:03 +0100728 libwebsocket_close_and_free_session(context,
729 wsi, LWS_CLOSE_STATUS_NOSTATUS);
730 }
731}
732
733struct libwebsocket *
734libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
735{
736 struct libwebsocket *new_wsi;
737 int n;
738
739 new_wsi = malloc(sizeof(struct libwebsocket));
740 if (new_wsi == NULL) {
741 fprintf(stderr, "Out of memory for new connection\n");
742 return NULL;
743 }
744
745 memset(new_wsi, 0, sizeof (struct libwebsocket));
746 new_wsi->count_active_extensions = 0;
747 new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
748
749 /* intialize the instance struct */
750
751 new_wsi->state = WSI_STATE_HTTP;
752 new_wsi->name_buffer_pos = 0;
753 new_wsi->mode = LWS_CONNMODE_WS_SERVING;
754
755 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
756 new_wsi->utf8_token[n].token = NULL;
757 new_wsi->utf8_token[n].token_len = 0;
758 }
759
760 /*
761 * these can only be set once the protocol is known
762 * we set an unestablished connection's protocol pointer
763 * to the start of the supported list, so it can look
764 * for matching ones during the handshake
765 */
766 new_wsi->protocol = context->protocols;
767 new_wsi->user_space = NULL;
768
769 /*
770 * Default protocol is 76 / 00
771 * After 76, there's a header specified to inform which
772 * draft the client wants, when that's seen we modify
773 * the individual connection's spec revision accordingly
774 */
775 new_wsi->ietf_spec_revision = 0;
776
777 return new_wsi;
778}
779
780char *
781libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
782 struct libwebsocket *wsi, char *pkt)
783{
784 char hash[20];
785 char *p = pkt;
786 int n;
787 struct libwebsocket_extension *ext;
Andy Green09226502011-05-28 10:19:19 +0100788 struct libwebsocket_extension *ext1;
Andy Greena41314f2011-05-23 10:00:03 +0100789 int ext_count = 0;
790 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 + MAX_BROADCAST_PAYLOAD +
791 LWS_SEND_BUFFER_POST_PADDING];
792 static const char magic_websocket_guid[] =
793 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
794
795 /*
796 * create the random key
797 */
798
799 n = libwebsockets_get_random(context, hash, 16);
800 if (n != 16) {
801 fprintf(stderr, "Unable to read from random dev %s\n",
802 SYSTEM_RANDOM_FILEPATH);
803 free(wsi->c_path);
804 free(wsi->c_host);
805 if (wsi->c_origin)
806 free(wsi->c_origin);
807 if (wsi->c_protocol)
808 free(wsi->c_protocol);
809 libwebsocket_close_and_free_session(context, wsi,
810 LWS_CLOSE_STATUS_NOSTATUS);
811 return NULL;
812 }
813
814 lws_b64_encode_string(hash, 16, wsi->key_b64,
815 sizeof wsi->key_b64);
816
817 /*
818 * 00 example client handshake
819 *
820 * GET /socket.io/websocket HTTP/1.1
821 * Upgrade: WebSocket
822 * Connection: Upgrade
823 * Host: 127.0.0.1:9999
824 * Origin: http://127.0.0.1
825 * Sec-WebSocket-Key1: 1 0 2#0W 9 89 7 92 ^
826 * Sec-WebSocket-Key2: 7 7Y 4328 B2v[8(z1
827 * Cookie: socketio=websocket
828 *
829 * (Á®Ä0¶†≥
830 *
831 * 04 example client handshake
832 *
833 * GET /chat HTTP/1.1
834 * Host: server.example.com
835 * Upgrade: websocket
836 * Connection: Upgrade
837 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
838 * Sec-WebSocket-Origin: http://example.com
839 * Sec-WebSocket-Protocol: chat, superchat
840 * Sec-WebSocket-Version: 4
841 */
842
843 p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a", wsi->c_path);
844
845 if (wsi->ietf_spec_revision == 0) {
846 unsigned char spaces_1, spaces_2;
847 unsigned int max_1, max_2;
848 unsigned int num_1, num_2;
849 unsigned long product_1, product_2;
850 char key_1[40];
851 char key_2[40];
852 unsigned int seed;
853 unsigned int count;
854 char challenge[16];
855
856 libwebsockets_get_random(context, &spaces_1,
857 sizeof(char));
858 libwebsockets_get_random(context, &spaces_2,
859 sizeof(char));
860
861 spaces_1 = (spaces_1 % 12) + 1;
862 spaces_2 = (spaces_2 % 12) + 1;
863
864 max_1 = 4294967295 / spaces_1;
865 max_2 = 4294967295 / spaces_2;
866
867 libwebsockets_get_random(context, &num_1, sizeof(int));
868 libwebsockets_get_random(context, &num_2, sizeof(int));
869
870 num_1 = (num_1 % max_1);
871 num_2 = (num_2 % max_2);
872
873 challenge[0] = num_1 >> 24;
874 challenge[1] = num_1 >> 16;
875 challenge[2] = num_1 >> 8;
876 challenge[3] = num_1;
877 challenge[4] = num_2 >> 24;
878 challenge[5] = num_2 >> 16;
879 challenge[6] = num_2 >> 8;
880 challenge[7] = num_2;
881
882 product_1 = num_1 * spaces_1;
883 product_2 = num_2 * spaces_2;
884
885 sprintf(key_1, "%lu", product_1);
886 sprintf(key_2, "%lu", product_2);
887
888 libwebsockets_get_random(context, &seed, sizeof(int));
889 libwebsockets_get_random(context, &count, sizeof(int));
890
891 libwebsockets_00_spam(key_1, (count % 12) + 1, seed);
892
893 libwebsockets_get_random(context, &seed, sizeof(int));
894 libwebsockets_get_random(context, &count, sizeof(int));
895
896 libwebsockets_00_spam(key_2, (count % 12) + 1, seed);
897
898 libwebsockets_get_random(context, &seed, sizeof(int));
899
900 libwebsockets_00_spaceout(key_1, spaces_1, seed);
901 libwebsockets_00_spaceout(key_2, spaces_2, seed >> 16);
902
903 p += sprintf(p, "Upgrade: WebSocket\x0d\x0a"
904 "Connection: Upgrade\x0d\x0aHost: %s\x0d\x0a",
905 wsi->c_host);
906 if (wsi->c_origin)
907 p += sprintf(p, "Origin: %s\x0d\x0a",
908 wsi->c_origin);
909
910 if (wsi->c_protocol)
911 p += sprintf(p, "Sec-WebSocket-Protocol: %s"
912 "\x0d\x0a", wsi->c_protocol);
913
914 p += sprintf(p, "Sec-WebSocket-Key1: %s\x0d\x0a",
915 key_1);
916 p += sprintf(p, "Sec-WebSocket-Key2: %s\x0d\x0a",
917 key_2);
918
919 /* give userland a chance to append, eg, cookies */
920
921 context->protocols[0].callback(context, wsi,
922 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
923 NULL, &p, (pkt + sizeof(pkt)) - p - 12);
924
925 p += sprintf(p, "\x0d\x0a");
926
927 if (libwebsockets_get_random(context, p, 8) != 8)
928 return NULL;
929 memcpy(&challenge[8], p, 8);
930 p += 8;
931
932 /* precompute what we want to see from the server */
933
934 MD5((unsigned char *)challenge, 16,
935 (unsigned char *)wsi->initial_handshake_hash_base64);
936
937 goto issue_hdr;
938 }
939
940 p += sprintf(p, "Host: %s\x0d\x0a", wsi->c_host);
941 p += sprintf(p, "Upgrade: websocket\x0d\x0a");
942 p += sprintf(p, "Connection: Upgrade\x0d\x0a"
943 "Sec-WebSocket-Key: ");
944 strcpy(p, wsi->key_b64);
945 p += strlen(wsi->key_b64);
946 p += sprintf(p, "\x0d\x0a");
947 if (wsi->c_origin)
948 p += sprintf(p, "Sec-WebSocket-Origin: %s\x0d\x0a",
949 wsi->c_origin);
950 if (wsi->c_protocol)
951 p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
952 wsi->c_protocol);
953
954 /* tell the server what extensions we could support */
955
956 p += sprintf(p, "Sec-WebSocket-Extensions: ");
957
958 ext =context->extensions;
959 while (ext && ext->callback) {
960
961 n = 0;
Andy Green09226502011-05-28 10:19:19 +0100962 ext1 = context->extensions;
963 while (ext1 && ext1->callback) {
964
965 n |= ext1->callback(context, ext1, wsi,
966 LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
967 NULL, (char *)ext->name, 0);
968
969 ext1++;
970 }
971
972 if (n) {
973
974 /* an extension vetos us */
Andy Greencc012472011-11-07 19:53:23 +0800975 debug("ext %s vetoed\n", (char *)ext->name);
Andy Green09226502011-05-28 10:19:19 +0100976 ext++;
977 continue;
978 }
979
Andy Greena41314f2011-05-23 10:00:03 +0100980 n = context->protocols[0].callback(context, wsi,
981 LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
982 wsi->user_space, (char *)ext->name, 0);
983
984 /*
985 * zero return from callback means
986 * go ahead and allow the extension,
987 * it's what we get if the callback is
988 * unhandled
989 */
990
991 if (n) {
992 ext++;
993 continue;
994 }
995
996 /* apply it */
997
998 if (ext_count)
999 *p++ = ',';
1000 p += sprintf(p, "%s", ext->name);
1001 ext_count++;
1002
1003 ext++;
1004 }
1005
1006 p += sprintf(p, "\x0d\x0a");
1007
1008 if (wsi->ietf_spec_revision)
1009 p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
1010 wsi->ietf_spec_revision);
1011
1012 /* give userland a chance to append, eg, cookies */
1013
1014 context->protocols[0].callback(context, wsi,
1015 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
1016 NULL, &p, (pkt + sizeof(pkt)) - p - 12);
1017
1018 p += sprintf(p, "\x0d\x0a");
1019
1020 /* prepare the expected server accept response */
1021
1022 strcpy((char *)buf, wsi->key_b64);
1023 strcpy((char *)&buf[strlen((char *)buf)], magic_websocket_guid);
1024
1025 SHA1(buf, strlen((char *)buf), (unsigned char *)hash);
1026
1027 lws_b64_encode_string(hash, 20,
1028 wsi->initial_handshake_hash_base64,
1029 sizeof wsi->initial_handshake_hash_base64);
1030
1031issue_hdr:
1032
Andy Greencc012472011-11-07 19:53:23 +08001033// puts(pkt);
Andy Green09226502011-05-28 10:19:19 +01001034
Andy Greena41314f2011-05-23 10:00:03 +01001035 /* done with these now */
1036
1037 free(wsi->c_path);
1038 free(wsi->c_host);
1039 if (wsi->c_origin)
1040 free(wsi->c_origin);
1041
1042 return p;
1043}
1044
1045int
1046lws_client_interpret_server_handshake(struct libwebsocket_context *context,
1047 struct libwebsocket *wsi)
1048{
1049 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 + MAX_BROADCAST_PAYLOAD +
1050 LWS_SEND_BUFFER_POST_PADDING];
1051 char pkt[1024];
1052 char *p = &pkt[0];
1053 const char *pc;
1054 const char *c;
1055 int more = 1;
1056 int okay = 0;
1057 char ext_name[128];
1058 struct libwebsocket_extension *ext;
1059 void *v;
Andy Greenc15cb382011-06-26 10:27:28 +01001060 int len = 0;
Andy Greena41314f2011-05-23 10:00:03 +01001061 int n;
1062 static const char magic_websocket_04_masking_guid[] =
1063 "61AC5F19-FBBA-4540-B96F-6561F1AB40A8";
1064
1065 /*
1066 * 00 / 76 -->
1067 *
1068 * HTTP/1.1 101 WebSocket Protocol Handshake
1069 * Upgrade: WebSocket
1070 * Connection: Upgrade
1071 * Sec-WebSocket-Origin: http://127.0.0.1
1072 * Sec-WebSocket-Location: ws://127.0.0.1:9999/socket.io/websocket
1073 *
1074 * xxxxxxxxxxxxxxxx
1075 */
1076
1077 if (wsi->ietf_spec_revision == 0) {
1078 if (!wsi->utf8_token[WSI_TOKEN_HTTP].token_len ||
1079 !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
1080 !wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len ||
1081 !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len ||
1082 (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len &&
1083 wsi->c_protocol != NULL)) {
Andy Greencc012472011-11-07 19:53:23 +08001084 debug("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001085 "missing required header(s)\n");
1086 pkt[len] = '\0';
Andy Greencc012472011-11-07 19:53:23 +08001087 debug("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001088 goto bail3;
1089 }
1090
1091 strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token);
1092 if (strcmp(wsi->utf8_token[WSI_TOKEN_HTTP].token,
1093 "101 websocket protocol handshake")) {
1094 fprintf(stderr, "libwebsocket_client_handshake "
1095 "server sent bad HTTP response '%s'\n",
1096 wsi->utf8_token[WSI_TOKEN_HTTP].token);
1097 goto bail3;
1098 }
1099
1100 if (wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len <
1101 16) {
1102 fprintf(stderr, "libwebsocket_client_handshake "
1103 "challenge reply too short %d\n",
1104 wsi->utf8_token[
1105 WSI_TOKEN_CHALLENGE].token_len);
1106 pkt[len] = '\0';
Andy Greencc012472011-11-07 19:53:23 +08001107 debug("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001108 goto bail3;
1109
1110 }
1111
1112 goto select_protocol;
1113 }
1114
1115 /*
1116 * well, what the server sent looked reasonable for syntax.
1117 * Now let's confirm it sent all the necessary headers
1118 */
1119#if 0
1120 fprintf(stderr, "WSI_TOKEN_HTTP: %d\n", wsi->utf8_token[WSI_TOKEN_HTTP].token_len);
1121 fprintf(stderr, "WSI_TOKEN_UPGRADE: %d\n", wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len);
1122 fprintf(stderr, "WSI_TOKEN_CONNECTION: %d\n", wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len);
1123 fprintf(stderr, "WSI_TOKEN_ACCEPT: %d\n", wsi->utf8_token[WSI_TOKEN_ACCEPT].token_len);
1124 fprintf(stderr, "WSI_TOKEN_NONCE: %d\n", wsi->utf8_token[WSI_TOKEN_NONCE].token_len);
1125 fprintf(stderr, "WSI_TOKEN_PROTOCOL: %d\n", wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len);
1126#endif
1127 if (!wsi->utf8_token[WSI_TOKEN_HTTP].token_len ||
1128 !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
1129 !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len ||
1130 !wsi->utf8_token[WSI_TOKEN_ACCEPT].token_len ||
1131 (!wsi->utf8_token[WSI_TOKEN_NONCE].token_len &&
1132 wsi->ietf_spec_revision == 4) ||
1133 (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len &&
1134 wsi->c_protocol != NULL)) {
Andy Greencc012472011-11-07 19:53:23 +08001135 debug("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001136 "missing required header(s)\n");
1137 pkt[len] = '\0';
Andy Greencc012472011-11-07 19:53:23 +08001138 debug("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001139 goto bail3;
1140 }
1141
1142 /*
1143 * Everything seems to be there, now take a closer look at what
1144 * is in each header
1145 */
1146
1147 strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token);
1148 if (strcmp(wsi->utf8_token[WSI_TOKEN_HTTP].token,
1149 "101 switching protocols")) {
1150 fprintf(stderr, "libwebsocket_client_handshake "
1151 "server sent bad HTTP response '%s'\n",
1152 wsi->utf8_token[WSI_TOKEN_HTTP].token);
1153 goto bail3;
1154 }
1155
1156 strtolower(wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
1157 if (strcmp(wsi->utf8_token[WSI_TOKEN_UPGRADE].token,
1158 "websocket")) {
1159 fprintf(stderr, "libwebsocket_client_handshake server "
1160 "sent bad Upgrade header '%s'\n",
1161 wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
1162 goto bail3;
1163 }
1164
1165 strtolower(wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
1166 if (strcmp(wsi->utf8_token[WSI_TOKEN_CONNECTION].token,
1167 "upgrade")) {
1168 fprintf(stderr, "libwebsocket_client_handshake server "
1169 "sent bad Connection hdr '%s'\n",
1170 wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
1171 goto bail3;
1172 }
1173
1174select_protocol:
1175 pc = wsi->c_protocol;
1176 if (pc == NULL)
1177 fprintf(stderr, "lws_client_interpret_server_handshake: NULL c_protocol\n");
1178 else
Andy Greencc012472011-11-07 19:53:23 +08001179 debug("lws_client_interpret_server_handshake: cPprotocol='%s'\n", pc);
Andy Greena41314f2011-05-23 10:00:03 +01001180
1181 /*
1182 * confirm the protocol the server wants to talk was in the list
1183 * of protocols we offered
1184 */
1185
1186 if (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len) {
1187
1188 fprintf(stderr, "lws_client_interpret_server_handshake WSI_TOKEN_PROTOCOL is null\n");
1189 /*
1190 * no protocol name to work from,
1191 * default to first protocol
1192 */
1193 wsi->protocol = &context->protocols[0];
1194
1195 free(wsi->c_protocol);
1196
1197 goto check_accept;
1198 }
1199
1200 while (*pc && !okay) {
1201 if ((!strncmp(pc,
1202 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token,
1203 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len)) &&
1204 (pc[wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len] == ',' ||
1205 pc[wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len] == '\0')) {
1206 okay = 1;
1207 continue;
1208 }
1209 while (*pc && *pc != ',')
1210 pc++;
1211 while (*pc && *pc != ' ')
1212 pc++;
1213 }
1214
1215 /* done with him now */
1216
1217 if (wsi->c_protocol)
1218 free(wsi->c_protocol);
1219
1220
1221 if (!okay) {
1222 fprintf(stderr, "libwebsocket_client_handshake server "
1223 "sent bad protocol '%s'\n",
1224 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
1225 goto bail2;
1226 }
1227
1228 /*
1229 * identify the selected protocol struct and set it
1230 */
1231 n = 0;
1232 wsi->protocol = NULL;
1233 while (context->protocols[n].callback) {
1234 if (strcmp(wsi->utf8_token[WSI_TOKEN_PROTOCOL].token,
1235 context->protocols[n].name) == 0)
1236 wsi->protocol = &context->protocols[n];
1237 n++;
1238 }
1239
1240 if (wsi->protocol == NULL) {
1241 fprintf(stderr, "libwebsocket_client_handshake server "
1242 "requested protocol '%s', which we "
1243 "said we supported but we don't!\n",
1244 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
1245 goto bail2;
1246 }
1247
1248
1249 /* instantiate the accepted extensions */
1250
1251 if (!wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token_len) {
Andy Greencc012472011-11-07 19:53:23 +08001252 debug("no client extenstions allowed by server \n");
Andy Greena41314f2011-05-23 10:00:03 +01001253 goto check_accept;
1254 }
1255
1256 /*
1257 * break down the list of server accepted extensions
1258 * and go through matching them or identifying bogons
1259 */
1260
1261 c = wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token;
1262 n = 0;
1263 while (more) {
1264
1265 if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
1266 ext_name[n] = *c++;
1267 if (n < sizeof(ext_name) - 1)
1268 n++;
1269 continue;
1270 }
1271 ext_name[n] = '\0';
1272 if (!*c)
1273 more = 0;
1274 else {
1275 c++;
1276 if (!n)
1277 continue;
1278 }
1279
1280 /* check we actually support it */
1281
Andy Greencc012472011-11-07 19:53:23 +08001282 debug("checking client ext %s\n", ext_name);
Andy Greena41314f2011-05-23 10:00:03 +01001283
1284 n = 0;
1285 ext = wsi->protocol->owning_server->extensions;
1286 while (ext && ext->callback) {
1287
1288 if (strcmp(ext_name, ext->name)) {
1289 ext++;
1290 continue;
1291 }
1292
1293 n = 1;
1294
Andy Greencc012472011-11-07 19:53:23 +08001295 debug("instantiating client ext %s\n", ext_name);
Andy Greena41314f2011-05-23 10:00:03 +01001296
1297 /* instantiate the extension on this conn */
1298
1299 wsi->active_extensions_user[
1300 wsi->count_active_extensions] =
1301 malloc(ext->per_session_data_size);
Andy Greenf6652412011-05-25 20:46:18 +01001302 memset(wsi->active_extensions_user[
1303 wsi->count_active_extensions], 0,
1304 ext->per_session_data_size);
Andy Greena41314f2011-05-23 10:00:03 +01001305 wsi->active_extensions[
1306 wsi->count_active_extensions] = ext;
1307
1308 /* allow him to construct his context */
1309
1310 ext->callback(wsi->protocol->owning_server,
1311 ext, wsi,
1312 LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
1313 wsi->active_extensions_user[
1314 wsi->count_active_extensions],
1315 NULL, 0);
1316
1317 wsi->count_active_extensions++;
1318
1319 ext++;
1320 }
1321
1322 if (n == 0) {
1323 fprintf(stderr, "Server said we should use"
1324 "an unknown extension '%s'!\n", ext_name);
1325 goto bail2;
1326 }
1327
1328 n = 0;
1329 }
1330
1331
1332check_accept:
1333
1334 if (wsi->ietf_spec_revision == 0) {
1335
1336 if (memcmp(wsi->initial_handshake_hash_base64,
1337 wsi->utf8_token[WSI_TOKEN_CHALLENGE].token, 16)) {
1338 fprintf(stderr, "libwebsocket_client_handshake "
1339 "failed 00 challenge compare\n");
1340 pkt[len] = '\0';
1341 fprintf(stderr, "%s", pkt);
1342 goto bail2;
1343 }
1344
1345 goto accept_ok;
1346 }
1347
1348 /*
1349 * Confirm his accept token is the one we precomputed
1350 */
1351
1352 if (strcmp(wsi->utf8_token[WSI_TOKEN_ACCEPT].token,
1353 wsi->initial_handshake_hash_base64)) {
1354 fprintf(stderr, "libwebsocket_client_handshake server "
1355 "sent bad ACCEPT '%s' vs computed '%s'\n",
1356 wsi->utf8_token[WSI_TOKEN_ACCEPT].token,
1357 wsi->initial_handshake_hash_base64);
1358 goto bail2;
1359 }
1360
1361 if (wsi->ietf_spec_revision == 4) {
1362 /*
1363 * Calculate the 04 masking key to use when
1364 * sending data to server
1365 */
1366
1367 strcpy((char *)buf, wsi->key_b64);
1368 p = (char *)buf + strlen(wsi->key_b64);
1369 strcpy(p, wsi->utf8_token[WSI_TOKEN_NONCE].token);
1370 p += wsi->utf8_token[WSI_TOKEN_NONCE].token_len;
1371 strcpy(p, magic_websocket_04_masking_guid);
1372 SHA1(buf, strlen((char *)buf), wsi->masking_key_04);
1373 }
1374 accept_ok:
1375
1376 /* allocate the per-connection user memory (if any) */
Alex Bligh49146db2011-11-07 17:19:25 +08001377 if (wsi->protocol->per_session_data_size && !libwebsocket_ensure_user_space(wsi))
1378 goto bail2;
Andy Greena41314f2011-05-23 10:00:03 +01001379
1380 /* clear his proxy connection timeout */
1381
1382 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1383
1384 /* mark him as being alive */
1385
1386 wsi->state = WSI_STATE_ESTABLISHED;
1387 wsi->mode = LWS_CONNMODE_WS_CLIENT;
1388
1389 fprintf(stderr, "handshake OK for protocol %s\n",
1390 wsi->protocol->name);
1391
1392 /* call him back to inform him he is up */
1393
1394 wsi->protocol->callback(context, wsi,
1395 LWS_CALLBACK_CLIENT_ESTABLISHED,
1396 wsi->user_space,
1397 NULL, 0);
1398
1399 /*
1400 * inform all extensions, not just active ones since they
1401 * already know
1402 */
1403
1404 ext = context->extensions;
1405
1406 while (ext && ext->callback) {
1407 v = NULL;
1408 for (n = 0; n < wsi->count_active_extensions; n++)
1409 if (wsi->active_extensions[n] == ext)
1410 v = wsi->active_extensions_user[n];
1411
1412 ext->callback(context, ext, wsi,
1413 LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED, v, NULL, 0);
1414 ext++;
1415 }
1416
1417 return 0;
1418
1419bail3:
1420 if (wsi->c_protocol)
1421 free(wsi->c_protocol);
1422
1423bail2:
1424 libwebsocket_close_and_free_session(context, wsi,
1425 LWS_CLOSE_STATUS_NOSTATUS);
1426 return 1;
1427}
1428
1429
1430
Andy Green9f990342011-02-12 11:57:45 +00001431/**
1432 * libwebsocket_service_fd() - Service polled socket with something waiting
Peter Hinz56885f32011-03-02 22:03:47 +00001433 * @context: Websocket context
Andy Green9f990342011-02-12 11:57:45 +00001434 * @pollfd: The pollfd entry describing the socket fd and which events
1435 * happened.
1436 *
1437 * This function closes any active connections and then frees the
1438 * context. After calling this, any further use of the context is
1439 * undefined.
1440 */
1441
1442int
Peter Hinz56885f32011-03-02 22:03:47 +00001443libwebsocket_service_fd(struct libwebsocket_context *context,
Andy Green0d338332011-02-12 11:57:43 +00001444 struct pollfd *pollfd)
Andy Greenb45993c2010-12-18 15:13:50 +00001445{
Andy Green3b84c002011-03-06 13:14:42 +00001446 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 + MAX_BROADCAST_PAYLOAD +
Andy Greenb45993c2010-12-18 15:13:50 +00001447 LWS_SEND_BUFFER_POST_PADDING];
Andy Greena71eafc2011-02-14 17:59:43 +00001448 struct libwebsocket *wsi;
Andy Green0d338332011-02-12 11:57:43 +00001449 struct libwebsocket *new_wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00001450 int n;
Andy Green0d338332011-02-12 11:57:43 +00001451 int m;
Andy Greenb45993c2010-12-18 15:13:50 +00001452 size_t len;
Andy Green0d338332011-02-12 11:57:43 +00001453 int accept_fd;
1454 unsigned int clilen;
1455 struct sockaddr_in cli_addr;
Andy Greena71eafc2011-02-14 17:59:43 +00001456 struct timeval tv;
Andy Greenbe93fef2011-02-14 20:25:43 +00001457 char pkt[1024];
1458 char *p = &pkt[0];
Andy Green2366b1c2011-03-06 13:15:31 +00001459 int more = 1;
Andy Green98a717c2011-03-06 13:14:15 +00001460 struct lws_tokens eff_buf;
Andy Green6c939552011-03-08 08:56:57 +00001461 int opt = 1;
Andy Greenc6517fa2011-03-06 13:15:29 +00001462
Andy Greenbe93fef2011-02-14 20:25:43 +00001463#ifdef LWS_OPENSSL_SUPPORT
1464 char ssl_err_buf[512];
1465#endif
Andy Greena71eafc2011-02-14 17:59:43 +00001466 /*
1467 * you can call us with pollfd = NULL to just allow the once-per-second
1468 * global timeout checks; if less than a second since the last check
1469 * it returns immediately then.
1470 */
1471
1472 gettimeofday(&tv, NULL);
1473
Peter Hinz56885f32011-03-02 22:03:47 +00001474 if (context->last_timeout_check_s != tv.tv_sec) {
1475 context->last_timeout_check_s = tv.tv_sec;
Andy Greena71eafc2011-02-14 17:59:43 +00001476
1477 /* global timeout check once per second */
1478
Peter Hinz56885f32011-03-02 22:03:47 +00001479 for (n = 0; n < context->fds_count; n++) {
1480 wsi = wsi_from_fd(context, context->fds[n].fd);
Andy Greena71eafc2011-02-14 17:59:43 +00001481
Andy Greena41314f2011-05-23 10:00:03 +01001482 libwebsocket_service_timeout_check(context, wsi,
1483 tv.tv_sec);
Andy Greena71eafc2011-02-14 17:59:43 +00001484 }
1485 }
1486
1487 /* just here for timeout management? */
1488
1489 if (pollfd == NULL)
1490 return 0;
1491
1492 /* no, here to service a socket descriptor */
1493
Peter Hinz56885f32011-03-02 22:03:47 +00001494 wsi = wsi_from_fd(context, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001495
Andy Green0d338332011-02-12 11:57:43 +00001496 if (wsi == NULL)
1497 return 1;
Andy Green8f037e42010-12-19 22:13:26 +00001498
Andy Green0d338332011-02-12 11:57:43 +00001499 switch (wsi->mode) {
1500 case LWS_CONNMODE_SERVER_LISTENER:
1501
1502 /* pollin means a client has connected to us then */
1503
1504 if (!pollfd->revents & POLLIN)
1505 break;
1506
David Galeanof7009352011-09-26 12:09:54 +01001507 if (context->fds_count >= MAX_CLIENTS) {
1508 fprintf(stderr, "too busy to accept new client\n");
1509 break;
1510 }
1511
Andy Green0d338332011-02-12 11:57:43 +00001512 /* listen socket got an unencrypted connection... */
1513
1514 clilen = sizeof(cli_addr);
1515 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1516 &clilen);
1517 if (accept_fd < 0) {
1518 fprintf(stderr, "ERROR on accept");
1519 break;
1520 }
1521
Andy Green6c939552011-03-08 08:56:57 +00001522 /* Disable Nagle */
1523 opt = 1;
David Galeanof7009352011-09-26 12:09:54 +01001524 setsockopt(accept_fd, IPPROTO_TCP, TCP_NODELAY, (const void *)&opt,
Pavel Borzenkov71ea5002011-04-15 13:16:32 +01001525 sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00001526
Andy Green07034092011-02-13 08:37:12 +00001527 /*
1528 * look at who we connected to and give user code a chance
1529 * to reject based on client IP. There's no protocol selected
1530 * yet so we issue this to protocols[0]
1531 */
1532
Peter Hinz56885f32011-03-02 22:03:47 +00001533 if ((context->protocols[0].callback)(context, wsi,
Andy Green07034092011-02-13 08:37:12 +00001534 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
1535 (void*)(long)accept_fd, NULL, 0)) {
Andy Greencc012472011-11-07 19:53:23 +08001536 debug("Callback denied network connection\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001537#ifdef WIN32
1538 closesocket(accept_fd);
1539#else
Andy Green07034092011-02-13 08:37:12 +00001540 close(accept_fd);
Peter Hinz56885f32011-03-02 22:03:47 +00001541#endif
Andy Green07034092011-02-13 08:37:12 +00001542 break;
1543 }
1544
Andy Green0d338332011-02-12 11:57:43 +00001545 /* accepting connection to main listener */
1546
Andy Greena41314f2011-05-23 10:00:03 +01001547 new_wsi = libwebsocket_create_new_server_wsi(context);
1548 if (new_wsi == NULL)
Andy Green0d338332011-02-12 11:57:43 +00001549 break;
Andy Green0d338332011-02-12 11:57:43 +00001550
Andy Green0d338332011-02-12 11:57:43 +00001551 new_wsi->sock = accept_fd;
Andy Greena41314f2011-05-23 10:00:03 +01001552
Andy Green0d338332011-02-12 11:57:43 +00001553
1554#ifdef LWS_OPENSSL_SUPPORT
1555 new_wsi->ssl = NULL;
Andy Green0d338332011-02-12 11:57:43 +00001556
Peter Hinz56885f32011-03-02 22:03:47 +00001557 if (context->use_ssl) {
Andy Green0d338332011-02-12 11:57:43 +00001558
Peter Hinz56885f32011-03-02 22:03:47 +00001559 new_wsi->ssl = SSL_new(context->ssl_ctx);
Andy Green0d338332011-02-12 11:57:43 +00001560 if (new_wsi->ssl == NULL) {
1561 fprintf(stderr, "SSL_new failed: %s\n",
1562 ERR_error_string(SSL_get_error(
1563 new_wsi->ssl, 0), NULL));
Andy Green1f9bf522011-02-14 21:14:37 +00001564 libwebsockets_decode_ssl_error();
Andy Green0d338332011-02-12 11:57:43 +00001565 free(new_wsi);
1566 break;
1567 }
1568
1569 SSL_set_fd(new_wsi->ssl, accept_fd);
1570
1571 n = SSL_accept(new_wsi->ssl);
1572 if (n != 1) {
1573 /*
1574 * browsers seem to probe with various
1575 * ssl params which fail then retry
1576 * and succeed
1577 */
1578 debug("SSL_accept failed skt %u: %s\n",
1579 pollfd->fd,
1580 ERR_error_string(SSL_get_error(
1581 new_wsi->ssl, n), NULL));
1582 SSL_free(
1583 new_wsi->ssl);
1584 free(new_wsi);
1585 break;
1586 }
Andy Greenc6bf2c22011-02-20 11:10:47 +00001587
Andy Green0d338332011-02-12 11:57:43 +00001588 debug("accepted new SSL conn "
1589 "port %u on fd=%d SSL ver %s\n",
1590 ntohs(cli_addr.sin_port), accept_fd,
1591 SSL_get_version(new_wsi->ssl));
1592
1593 } else
1594#endif
1595 debug("accepted new conn port %u on fd=%d\n",
1596 ntohs(cli_addr.sin_port), accept_fd);
1597
Peter Hinz56885f32011-03-02 22:03:47 +00001598 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001599
Andy Green0d338332011-02-12 11:57:43 +00001600 /*
1601 * make sure NO events are seen yet on this new socket
1602 * (otherwise we inherit old fds[client].revents from
1603 * previous socket there and die mysteriously! )
1604 */
Peter Hinz56885f32011-03-02 22:03:47 +00001605 context->fds[context->fds_count].revents = 0;
Andy Green0d338332011-02-12 11:57:43 +00001606
Peter Hinz56885f32011-03-02 22:03:47 +00001607 context->fds[context->fds_count].events = POLLIN;
1608 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001609
Andy Green3221f922011-02-12 13:14:11 +00001610 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001611 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001612 LWS_CALLBACK_ADD_POLL_FD,
1613 (void *)(long)accept_fd, NULL, POLLIN);
1614
Andy Green0d338332011-02-12 11:57:43 +00001615 break;
1616
1617 case LWS_CONNMODE_BROADCAST_PROXY_LISTENER:
1618
1619 /* as we are listening, POLLIN means accept() is needed */
1620
1621 if (!pollfd->revents & POLLIN)
1622 break;
1623
1624 /* listen socket got an unencrypted connection... */
1625
1626 clilen = sizeof(cli_addr);
1627 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1628 &clilen);
1629 if (accept_fd < 0) {
1630 fprintf(stderr, "ERROR on accept");
1631 break;
1632 }
1633
Peter Hinz56885f32011-03-02 22:03:47 +00001634 if (context->fds_count >= MAX_CLIENTS) {
Andy Green3221f922011-02-12 13:14:11 +00001635 fprintf(stderr, "too busy to accept new broadcast "
1636 "proxy client\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001637#ifdef WIN32
1638 closesocket(accept_fd);
1639#else
Andy Green0d338332011-02-12 11:57:43 +00001640 close(accept_fd);
Peter Hinz56885f32011-03-02 22:03:47 +00001641#endif
Andy Green0d338332011-02-12 11:57:43 +00001642 break;
1643 }
1644
1645 /* create a dummy wsi for the connection and add it */
1646
1647 new_wsi = malloc(sizeof(struct libwebsocket));
1648 memset(new_wsi, 0, sizeof (struct libwebsocket));
1649 new_wsi->sock = accept_fd;
1650 new_wsi->mode = LWS_CONNMODE_BROADCAST_PROXY;
1651 new_wsi->state = WSI_STATE_ESTABLISHED;
Andy Greend6e09112011-03-05 16:12:15 +00001652 new_wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00001653 /* note which protocol we are proxying */
1654 new_wsi->protocol_index_for_broadcast_proxy =
1655 wsi->protocol_index_for_broadcast_proxy;
Peter Hinz56885f32011-03-02 22:03:47 +00001656 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001657
1658 /* add connected socket to internal poll array */
1659
Peter Hinz56885f32011-03-02 22:03:47 +00001660 context->fds[context->fds_count].revents = 0;
1661 context->fds[context->fds_count].events = POLLIN;
1662 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001663
Andy Green3221f922011-02-12 13:14:11 +00001664 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001665 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001666 LWS_CALLBACK_ADD_POLL_FD,
1667 (void *)(long)accept_fd, NULL, POLLIN);
1668
Andy Green0d338332011-02-12 11:57:43 +00001669 break;
1670
1671 case LWS_CONNMODE_BROADCAST_PROXY:
Andy Green8f037e42010-12-19 22:13:26 +00001672
Andy Greenb45993c2010-12-18 15:13:50 +00001673 /* handle session socket closed */
Andy Green8f037e42010-12-19 22:13:26 +00001674
Andy Green0d338332011-02-12 11:57:43 +00001675 if (pollfd->revents & (POLLERR | POLLHUP)) {
Andy Green8f037e42010-12-19 22:13:26 +00001676
Andy Green0d338332011-02-12 11:57:43 +00001677 debug("Session Socket %p (fd=%d) dead\n",
Timothy J Fontaineb86d64e2011-02-14 17:55:27 +00001678 (void *)wsi, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001679
Peter Hinz56885f32011-03-02 22:03:47 +00001680 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001681 LWS_CLOSE_STATUS_NORMAL);
Andy Green4b6fbe12011-02-14 08:03:48 +00001682 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00001683 }
Andy Green8f037e42010-12-19 22:13:26 +00001684
Andy Green3b84c002011-03-06 13:14:42 +00001685 /*
1686 * either extension code with stuff to spill, or the user code,
1687 * requested a callback when it was OK to write
1688 */
Andy Green90c7cbc2011-01-27 06:26:52 +00001689
Andy Green3b84c002011-03-06 13:14:42 +00001690 if (pollfd->revents & POLLOUT)
1691 if (lws_handle_POLLOUT_event(context, wsi, pollfd) < 0) {
1692 libwebsocket_close_and_free_session(context, wsi,
1693 LWS_CLOSE_STATUS_NORMAL);
1694 return 1;
1695 }
Andy Green90c7cbc2011-01-27 06:26:52 +00001696
Andy Greenb45993c2010-12-18 15:13:50 +00001697 /* any incoming data ready? */
1698
Andy Green0d338332011-02-12 11:57:43 +00001699 if (!(pollfd->revents & POLLIN))
1700 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001701
Andy Green0d338332011-02-12 11:57:43 +00001702 /* get the issued broadcast payload from the socket */
Andy Greenb45993c2010-12-18 15:13:50 +00001703
Andy Green0d338332011-02-12 11:57:43 +00001704 len = read(pollfd->fd, buf + LWS_SEND_BUFFER_PRE_PADDING,
1705 MAX_BROADCAST_PAYLOAD);
1706 if (len < 0) {
1707 fprintf(stderr, "Error reading broadcast payload\n");
Andy Green4b6fbe12011-02-14 08:03:48 +00001708 break;
Andy Green0d338332011-02-12 11:57:43 +00001709 }
Andy Greenb45993c2010-12-18 15:13:50 +00001710
Andy Green0d338332011-02-12 11:57:43 +00001711 /* broadcast it to all guys with this protocol index */
Andy Green8f037e42010-12-19 22:13:26 +00001712
Andy Green0d338332011-02-12 11:57:43 +00001713 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Green8f037e42010-12-19 22:13:26 +00001714
Peter Hinz56885f32011-03-02 22:03:47 +00001715 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00001716
Peter Hinz56885f32011-03-02 22:03:47 +00001717 new_wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00001718
Andy Green0d338332011-02-12 11:57:43 +00001719 /* only to clients we are serving to */
Andy Greenb45993c2010-12-18 15:13:50 +00001720
Andy Green0d338332011-02-12 11:57:43 +00001721 if (new_wsi->mode != LWS_CONNMODE_WS_SERVING)
Andy Greenb45993c2010-12-18 15:13:50 +00001722 continue;
1723
1724 /*
1725 * never broadcast to non-established
1726 * connection
1727 */
1728
Andy Green0d338332011-02-12 11:57:43 +00001729 if (new_wsi->state != WSI_STATE_ESTABLISHED)
Andy Green4739e5c2011-01-22 12:51:57 +00001730 continue;
1731
Andy Greenb45993c2010-12-18 15:13:50 +00001732 /*
1733 * only broadcast to connections using
1734 * the requested protocol
1735 */
1736
Andy Green0d338332011-02-12 11:57:43 +00001737 if (new_wsi->protocol->protocol_index !=
1738 wsi->protocol_index_for_broadcast_proxy)
Andy Greenb45993c2010-12-18 15:13:50 +00001739 continue;
1740
Andy Green8f037e42010-12-19 22:13:26 +00001741 /* broadcast it to this connection */
1742
Peter Hinz56885f32011-03-02 22:03:47 +00001743 new_wsi->protocol->callback(context, new_wsi,
Andy Green8f037e42010-12-19 22:13:26 +00001744 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00001745 new_wsi->user_space,
Andy Green0ca6a172010-12-19 20:50:01 +00001746 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
Andy Greenb45993c2010-12-18 15:13:50 +00001747 }
Andy Green0d338332011-02-12 11:57:43 +00001748 }
1749 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001750
Andy Greenbe93fef2011-02-14 20:25:43 +00001751 case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
1752
1753 /* handle proxy hung up on us */
1754
1755 if (pollfd->revents & (POLLERR | POLLHUP)) {
1756
1757 fprintf(stderr, "Proxy connection %p (fd=%d) dead\n",
1758 (void *)wsi, pollfd->fd);
1759
Peter Hinz56885f32011-03-02 22:03:47 +00001760 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001761 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001762 return 1;
1763 }
1764
Andy Green72c34322011-04-16 10:46:21 +01001765 n = recv(wsi->sock, pkt, sizeof pkt, 0);
Andy Greenbe93fef2011-02-14 20:25:43 +00001766 if (n < 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001767 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001768 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001769 fprintf(stderr, "ERROR reading from proxy socket\n");
1770 return 1;
1771 }
1772
1773 pkt[13] = '\0';
1774 if (strcmp(pkt, "HTTP/1.0 200 ") != 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001775 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001776 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001777 fprintf(stderr, "ERROR from proxy: %s\n", pkt);
1778 return 1;
1779 }
1780
1781 /* clear his proxy connection timeout */
1782
1783 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1784
1785 /* fallthru */
1786
1787 case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
1788
1789 #ifdef LWS_OPENSSL_SUPPORT
1790 if (wsi->use_ssl) {
1791
Peter Hinz56885f32011-03-02 22:03:47 +00001792 wsi->ssl = SSL_new(context->ssl_client_ctx);
1793 wsi->client_bio = BIO_new_socket(wsi->sock,
1794 BIO_NOCLOSE);
Andy Greenbe93fef2011-02-14 20:25:43 +00001795 SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
1796
Andy Green6901cb32011-02-21 08:06:47 +00001797 SSL_set_ex_data(wsi->ssl,
Andy Green2e24da02011-03-05 16:12:04 +00001798 openssl_websocket_private_data_index,
Peter Hinz56885f32011-03-02 22:03:47 +00001799 context);
Andy Green6901cb32011-02-21 08:06:47 +00001800
Andy Greenbe93fef2011-02-14 20:25:43 +00001801 if (SSL_connect(wsi->ssl) <= 0) {
1802 fprintf(stderr, "SSL connect error %s\n",
Andy Green687b0182011-02-26 11:04:01 +00001803 ERR_error_string(ERR_get_error(),
1804 ssl_err_buf));
Peter Hinz56885f32011-03-02 22:03:47 +00001805 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001806 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001807 return 1;
1808 }
1809
1810 n = SSL_get_verify_result(wsi->ssl);
Andy Green2e24da02011-03-05 16:12:04 +00001811 if ((n != X509_V_OK) && (
Andy Green687b0182011-02-26 11:04:01 +00001812 n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
1813 wsi->use_ssl != 2)) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001814
Andy Green687b0182011-02-26 11:04:01 +00001815 fprintf(stderr, "server's cert didn't "
1816 "look good %d\n", n);
Peter Hinz56885f32011-03-02 22:03:47 +00001817 libwebsocket_close_and_free_session(context,
1818 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Green687b0182011-02-26 11:04:01 +00001819 return 1;
Andy Greenbe93fef2011-02-14 20:25:43 +00001820 }
1821 } else {
1822 wsi->ssl = NULL;
1823 #endif
1824
1825
1826 #ifdef LWS_OPENSSL_SUPPORT
1827 }
1828 #endif
1829
Andy Greena41314f2011-05-23 10:00:03 +01001830 p = libwebsockets_generate_client_handshake(context, wsi, p);
1831 if (p ==NULL)
Andy Greenbe93fef2011-02-14 20:25:43 +00001832 return 1;
Andy Greeneeaacb32011-03-01 20:44:24 +00001833
Andy Greenbe93fef2011-02-14 20:25:43 +00001834 /* send our request to the server */
1835
1836 #ifdef LWS_OPENSSL_SUPPORT
1837 if (wsi->use_ssl)
1838 n = SSL_write(wsi->ssl, pkt, p - pkt);
1839 else
1840 #endif
1841 n = send(wsi->sock, pkt, p - pkt, 0);
1842
1843 if (n < 0) {
1844 fprintf(stderr, "ERROR writing to client socket\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001845 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001846 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001847 return 1;
1848 }
1849
1850 wsi->parser_state = WSI_TOKEN_NAME_PART;
1851 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
1852 libwebsocket_set_timeout(wsi,
1853 PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, 5);
1854
1855 break;
1856
1857 case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
1858
1859 /* handle server hung up on us */
1860
1861 if (pollfd->revents & (POLLERR | POLLHUP)) {
1862
1863 fprintf(stderr, "Server connection %p (fd=%d) dead\n",
1864 (void *)wsi, pollfd->fd);
1865
1866 goto bail3;
1867 }
1868
1869
1870 /* interpret the server response */
1871
1872 /*
1873 * HTTP/1.1 101 Switching Protocols
1874 * Upgrade: websocket
1875 * Connection: Upgrade
1876 * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
1877 * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
1878 * Sec-WebSocket-Protocol: chat
1879 */
1880
1881 #ifdef LWS_OPENSSL_SUPPORT
1882 if (wsi->use_ssl)
1883 len = SSL_read(wsi->ssl, pkt, sizeof pkt);
1884 else
1885 #endif
Andy Green72c34322011-04-16 10:46:21 +01001886 len = recv(wsi->sock, pkt, sizeof pkt, 0);
Andy Greenbe93fef2011-02-14 20:25:43 +00001887
1888 if (len < 0) {
1889 fprintf(stderr,
1890 "libwebsocket_client_handshake read error\n");
1891 goto bail3;
1892 }
1893
1894 p = pkt;
1895 for (n = 0; n < len; n++)
1896 libwebsocket_parse(wsi, *p++);
1897
Andy Green27a0b912011-04-16 10:54:28 +01001898 /*
1899 * may be coming in multiple packets, there is a 5-second
1900 * libwebsocket timeout still active here too, so if parsing did
1901 * not complete just wait for next packet coming in this state
1902 */
1903
1904 if (wsi->parser_state != WSI_PARSING_COMPLETE)
1905 break;
Andy Greenbe93fef2011-02-14 20:25:43 +00001906
Andy Greena41314f2011-05-23 10:00:03 +01001907 return lws_client_interpret_server_handshake(context, wsi);
Andy Greenbe93fef2011-02-14 20:25:43 +00001908
1909bail3:
1910 if (wsi->c_protocol)
1911 free(wsi->c_protocol);
Peter Hinz56885f32011-03-02 22:03:47 +00001912 libwebsocket_close_and_free_session(context, wsi,
Andy Greena41314f2011-05-23 10:00:03 +01001913 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001914 return 1;
Andy Greena41314f2011-05-23 10:00:03 +01001915
1916 case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
1917 fprintf(stderr, "LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
1918 break;
1919
1920 case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
1921 fprintf(stderr, "LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
1922 break;
1923
Andy Greenbe93fef2011-02-14 20:25:43 +00001924
Andy Green0d338332011-02-12 11:57:43 +00001925 case LWS_CONNMODE_WS_SERVING:
1926 case LWS_CONNMODE_WS_CLIENT:
1927
1928 /* handle session socket closed */
1929
1930 if (pollfd->revents & (POLLERR | POLLHUP)) {
1931
Andy Green62c54d22011-02-14 09:14:25 +00001932 fprintf(stderr, "Session Socket %p (fd=%d) dead\n",
Andy Green0d338332011-02-12 11:57:43 +00001933 (void *)wsi, pollfd->fd);
1934
Peter Hinz56885f32011-03-02 22:03:47 +00001935 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001936 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green4b6fbe12011-02-14 08:03:48 +00001937 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00001938 }
1939
Andy Green0d338332011-02-12 11:57:43 +00001940 /* the guy requested a callback when it was OK to write */
1941
Andy Greenda527df2011-03-07 07:08:12 +00001942 if ((pollfd->revents & POLLOUT) &&
1943 wsi->state == WSI_STATE_ESTABLISHED)
1944 if (lws_handle_POLLOUT_event(context, wsi,
1945 pollfd) < 0) {
1946 libwebsocket_close_and_free_session(
1947 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00001948 return 1;
1949 }
Andy Green0d338332011-02-12 11:57:43 +00001950
Andy Green0d338332011-02-12 11:57:43 +00001951
1952 /* any incoming data ready? */
1953
1954 if (!(pollfd->revents & POLLIN))
1955 break;
1956
Andy Greenb45993c2010-12-18 15:13:50 +00001957#ifdef LWS_OPENSSL_SUPPORT
Andy Green0d338332011-02-12 11:57:43 +00001958 if (wsi->ssl)
Andy Green98a717c2011-03-06 13:14:15 +00001959 eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);
Andy Greenb45993c2010-12-18 15:13:50 +00001960 else
1961#endif
Andy Green98a717c2011-03-06 13:14:15 +00001962 eff_buf.token_len =
Andy Green72c34322011-04-16 10:46:21 +01001963 recv(pollfd->fd, buf, sizeof buf, 0);
Andy Greenb45993c2010-12-18 15:13:50 +00001964
Andy Green98a717c2011-03-06 13:14:15 +00001965 if (eff_buf.token_len < 0) {
1966 fprintf(stderr, "Socket read returned %d\n",
1967 eff_buf.token_len);
Andy Green4b6fbe12011-02-14 08:03:48 +00001968 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001969 }
Andy Green98a717c2011-03-06 13:14:15 +00001970 if (!eff_buf.token_len) {
Peter Hinz56885f32011-03-02 22:03:47 +00001971 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001972 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green4b6fbe12011-02-14 08:03:48 +00001973 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00001974 }
1975
Andy Green98a717c2011-03-06 13:14:15 +00001976 /*
1977 * give any active extensions a chance to munge the buffer
1978 * before parse. We pass in a pointer to an lws_tokens struct
1979 * prepared with the default buffer and content length that's in
1980 * there. Rather than rewrite the default buffer, extensions
1981 * that expect to grow the buffer can adapt .token to
1982 * point to their own per-connection buffer in the extension
1983 * user allocation. By default with no extensions or no
1984 * extension callback handling, just the normal input buffer is
1985 * used then so it is efficient.
1986 */
Andy Greenb45993c2010-12-18 15:13:50 +00001987
Andy Green98a717c2011-03-06 13:14:15 +00001988 eff_buf.token = (char *)buf;
Andy Greenb45993c2010-12-18 15:13:50 +00001989
Andy Green98a717c2011-03-06 13:14:15 +00001990 more = 1;
1991 while (more) {
Andy Green0d338332011-02-12 11:57:43 +00001992
Andy Green98a717c2011-03-06 13:14:15 +00001993 more = 0;
1994
1995 for (n = 0; n < wsi->count_active_extensions; n++) {
Andy Green46c2ea02011-03-22 09:04:01 +00001996 m = wsi->active_extensions[n]->callback(context,
1997 wsi->active_extensions[n], wsi,
Andy Green98a717c2011-03-06 13:14:15 +00001998 LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
Andy Green46c2ea02011-03-22 09:04:01 +00001999 wsi->active_extensions_user[n],
2000 &eff_buf, 0);
Andy Green98a717c2011-03-06 13:14:15 +00002001 if (m < 0) {
2002 fprintf(stderr, "Extension reports fatal error\n");
2003 libwebsocket_close_and_free_session(context, wsi,
2004 LWS_CLOSE_STATUS_NOSTATUS);
2005 return 1;
2006 }
2007 if (m)
2008 more = 1;
2009 }
2010
2011 /* service incoming data */
2012
2013 if (eff_buf.token_len) {
2014 n = libwebsocket_read(context, wsi,
2015 (unsigned char *)eff_buf.token, eff_buf.token_len);
2016 if (n < 0)
2017 /* we closed wsi */
2018 return 1;
2019 }
2020
2021 eff_buf.token = NULL;
2022 eff_buf.token_len = 0;
2023 }
2024 break;
Andy Greenb45993c2010-12-18 15:13:50 +00002025 }
2026
2027 return 0;
2028}
2029
Andy Green0d338332011-02-12 11:57:43 +00002030
Andy Green6964bb52011-01-23 16:50:33 +00002031/**
2032 * libwebsocket_context_destroy() - Destroy the websocket context
Peter Hinz56885f32011-03-02 22:03:47 +00002033 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002034 *
2035 * This function closes any active connections and then frees the
2036 * context. After calling this, any further use of the context is
2037 * undefined.
2038 */
2039void
Peter Hinz56885f32011-03-02 22:03:47 +00002040libwebsocket_context_destroy(struct libwebsocket_context *context)
Andy Green6964bb52011-01-23 16:50:33 +00002041{
Andy Green0d338332011-02-12 11:57:43 +00002042 int n;
2043 int m;
2044 struct libwebsocket *wsi;
Andy Greena41314f2011-05-23 10:00:03 +01002045 struct libwebsocket_extension *ext;
Andy Green6964bb52011-01-23 16:50:33 +00002046
Andy Green4b6fbe12011-02-14 08:03:48 +00002047 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002048 for (m = 0; m < context->fd_hashtable[n].length; m++) {
2049 wsi = context->fd_hashtable[n].wsi[m];
2050 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002051 LWS_CLOSE_STATUS_GOINGAWAY);
Andy Greenf3d3b402011-02-09 07:16:34 +00002052 }
Andy Green6964bb52011-01-23 16:50:33 +00002053
Andy Greena41314f2011-05-23 10:00:03 +01002054 /*
2055 * give all extensions a chance to clean up any per-context
2056 * allocations they might have made
2057 */
2058
2059 ext = context->extensions;
2060 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
2061 if (context->listen_port)
2062 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
2063 while (ext->callback) {
2064 ext->callback(context, ext, NULL, m, NULL, NULL, 0);
2065 ext++;
2066 }
2067
Peter Hinz56885f32011-03-02 22:03:47 +00002068#ifdef WIN32
2069#else
2070 close(context->fd_random);
Andy Green6964bb52011-01-23 16:50:33 +00002071#endif
2072
Peter Hinz56885f32011-03-02 22:03:47 +00002073#ifdef LWS_OPENSSL_SUPPORT
2074 if (context->ssl_ctx)
2075 SSL_CTX_free(context->ssl_ctx);
2076 if (context->ssl_client_ctx)
2077 SSL_CTX_free(context->ssl_client_ctx);
2078#endif
2079
2080 free(context);
2081
2082#ifdef WIN32
2083 WSACleanup();
2084#endif
Andy Green6964bb52011-01-23 16:50:33 +00002085}
2086
2087/**
2088 * libwebsocket_service() - Service any pending websocket activity
Peter Hinz56885f32011-03-02 22:03:47 +00002089 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002090 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
2091 * service otherwise block and service immediately, returning
2092 * after the timeout if nothing needed service.
2093 *
2094 * This function deals with any pending websocket traffic, for three
2095 * kinds of event. It handles these events on both server and client
2096 * types of connection the same.
2097 *
2098 * 1) Accept new connections to our context's server
2099 *
2100 * 2) Perform pending broadcast writes initiated from other forked
2101 * processes (effectively serializing asynchronous broadcasts)
2102 *
2103 * 3) Call the receive callback for incoming frame data received by
2104 * server or client connections.
2105 *
2106 * You need to call this service function periodically to all the above
2107 * functions to happen; if your application is single-threaded you can
2108 * just call it in your main event loop.
2109 *
2110 * Alternatively you can fork a new process that asynchronously handles
2111 * calling this service in a loop. In that case you are happy if this
2112 * call blocks your thread until it needs to take care of something and
2113 * would call it with a large nonzero timeout. Your loop then takes no
2114 * CPU while there is nothing happening.
2115 *
2116 * If you are calling it in a single-threaded app, you don't want it to
2117 * wait around blocking other things in your loop from happening, so you
2118 * would call it with a timeout_ms of 0, so it returns immediately if
2119 * nothing is pending, or as soon as it services whatever was pending.
2120 */
2121
Andy Greenb45993c2010-12-18 15:13:50 +00002122
Andy Greene92cd172011-01-19 13:11:55 +00002123int
Peter Hinz56885f32011-03-02 22:03:47 +00002124libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
Andy Greene92cd172011-01-19 13:11:55 +00002125{
2126 int n;
Andy Greene92cd172011-01-19 13:11:55 +00002127
2128 /* stay dead once we are dead */
2129
Peter Hinz56885f32011-03-02 22:03:47 +00002130 if (context == NULL)
Andy Greene92cd172011-01-19 13:11:55 +00002131 return 1;
2132
Andy Green0d338332011-02-12 11:57:43 +00002133 /* wait for something to need service */
Andy Green4739e5c2011-01-22 12:51:57 +00002134
Peter Hinz56885f32011-03-02 22:03:47 +00002135 n = poll(context->fds, context->fds_count, timeout_ms);
Andy Green3221f922011-02-12 13:14:11 +00002136 if (n == 0) /* poll timeout */
2137 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002138
Andy Green62c54d22011-02-14 09:14:25 +00002139 if (n < 0) {
Andy Green5e1fa172011-02-10 09:07:05 +00002140 /*
Andy Greene92cd172011-01-19 13:11:55 +00002141 fprintf(stderr, "Listen Socket dead\n");
Andy Green5e1fa172011-02-10 09:07:05 +00002142 */
Andy Green0d338332011-02-12 11:57:43 +00002143 return 1;
Andy Greene92cd172011-01-19 13:11:55 +00002144 }
Andy Greene92cd172011-01-19 13:11:55 +00002145
2146 /* handle accept on listening socket? */
2147
Peter Hinz56885f32011-03-02 22:03:47 +00002148 for (n = 0; n < context->fds_count; n++)
2149 if (context->fds[n].revents)
2150 libwebsocket_service_fd(context, &context->fds[n]);
Andy Greene92cd172011-01-19 13:11:55 +00002151
2152 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002153}
2154
Andy Greena41314f2011-05-23 10:00:03 +01002155int
2156lws_any_extension_handled(struct libwebsocket_context *context,
2157 struct libwebsocket *wsi,
2158 enum libwebsocket_extension_callback_reasons r,
2159 void *v, size_t len)
2160{
2161 int n;
2162 int handled = 0;
2163
2164 /* maybe an extension will take care of it for us */
2165
2166 for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
2167 if (!wsi->active_extensions[n]->callback)
2168 continue;
2169
2170 handled |= wsi->active_extensions[n]->callback(context,
2171 wsi->active_extensions[n], wsi,
2172 r, wsi->active_extensions_user[n], v, len);
2173 }
2174
2175 return handled;
2176}
2177
2178
2179void *
2180lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
2181 struct libwebsocket_extension * ext)
2182{
2183 int n = 0;
2184
Andy Green68b45042011-05-25 21:41:57 +01002185 if (wsi == NULL)
2186 return NULL;
2187
Andy Greena41314f2011-05-23 10:00:03 +01002188 while (n < wsi->count_active_extensions) {
2189 if (wsi->active_extensions[n] != ext) {
2190 n++;
2191 continue;
2192 }
2193 return wsi->active_extensions_user[n];
2194 }
2195
2196 return NULL;
2197}
2198
Andy Green90c7cbc2011-01-27 06:26:52 +00002199/**
2200 * libwebsocket_callback_on_writable() - Request a callback when this socket
2201 * becomes able to be written to without
2202 * blocking
Andy Green32375b72011-02-19 08:32:53 +00002203 *
Peter Hinz56885f32011-03-02 22:03:47 +00002204 * @context: libwebsockets context
Andy Green90c7cbc2011-01-27 06:26:52 +00002205 * @wsi: Websocket connection instance to get callback for
2206 */
2207
2208int
Peter Hinz56885f32011-03-02 22:03:47 +00002209libwebsocket_callback_on_writable(struct libwebsocket_context *context,
Andy Green62c54d22011-02-14 09:14:25 +00002210 struct libwebsocket *wsi)
Andy Green90c7cbc2011-01-27 06:26:52 +00002211{
Andy Green90c7cbc2011-01-27 06:26:52 +00002212 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002213 int handled = 0;
2214
2215 /* maybe an extension will take care of it for us */
2216
2217 for (n = 0; n < wsi->count_active_extensions; n++) {
2218 if (!wsi->active_extensions[n]->callback)
2219 continue;
2220
2221 handled |= wsi->active_extensions[n]->callback(context,
2222 wsi->active_extensions[n], wsi,
2223 LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
2224 wsi->active_extensions_user[n], NULL, 0);
2225 }
2226
2227 if (handled)
2228 return 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002229
Peter Hinz56885f32011-03-02 22:03:47 +00002230 for (n = 0; n < context->fds_count; n++)
2231 if (context->fds[n].fd == wsi->sock) {
2232 context->fds[n].events |= POLLOUT;
Andy Greena41314f2011-05-23 10:00:03 +01002233 n = context->fds_count + 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002234 }
2235
Andy Greena41314f2011-05-23 10:00:03 +01002236 if (n == context->fds_count)
2237 fprintf(stderr, "libwebsocket_callback_on_writable: failed to find socket %d\n", wsi->sock);
2238
Andy Green3221f922011-02-12 13:14:11 +00002239 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002240 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002241 LWS_CALLBACK_SET_MODE_POLL_FD,
2242 (void *)(long)wsi->sock, NULL, POLLOUT);
2243
Andy Green90c7cbc2011-01-27 06:26:52 +00002244 return 1;
2245}
2246
2247/**
2248 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
2249 * all connections using the given protocol when it
2250 * becomes possible to write to each socket without
2251 * blocking in turn.
2252 *
2253 * @protocol: Protocol whose connections will get callbacks
2254 */
2255
2256int
2257libwebsocket_callback_on_writable_all_protocol(
2258 const struct libwebsocket_protocols *protocol)
2259{
Peter Hinz56885f32011-03-02 22:03:47 +00002260 struct libwebsocket_context *context = protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002261 int n;
Andy Green0d338332011-02-12 11:57:43 +00002262 int m;
2263 struct libwebsocket *wsi;
Andy Green90c7cbc2011-01-27 06:26:52 +00002264
Andy Green0d338332011-02-12 11:57:43 +00002265 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
2266
Peter Hinz56885f32011-03-02 22:03:47 +00002267 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Green0d338332011-02-12 11:57:43 +00002268
Peter Hinz56885f32011-03-02 22:03:47 +00002269 wsi = context->fd_hashtable[n].wsi[m];
Andy Green0d338332011-02-12 11:57:43 +00002270
2271 if (wsi->protocol == protocol)
Peter Hinz56885f32011-03-02 22:03:47 +00002272 libwebsocket_callback_on_writable(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002273 }
2274 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002275
2276 return 0;
2277}
2278
Andy Greenbe93fef2011-02-14 20:25:43 +00002279/**
2280 * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
2281 *
2282 * You will not need this unless you are doing something special
2283 *
2284 * @wsi: Websocket connection instance
2285 * @reason: timeout reason
2286 * @secs: how many seconds
2287 */
2288
2289void
2290libwebsocket_set_timeout(struct libwebsocket *wsi,
2291 enum pending_timeout reason, int secs)
2292{
2293 struct timeval tv;
2294
2295 gettimeofday(&tv, NULL);
2296
2297 wsi->pending_timeout_limit = tv.tv_sec + secs;
2298 wsi->pending_timeout = reason;
2299}
2300
Andy Greena6cbece2011-01-27 20:06:03 +00002301
2302/**
2303 * libwebsocket_get_socket_fd() - returns the socket file descriptor
2304 *
2305 * You will not need this unless you are doing something special
2306 *
2307 * @wsi: Websocket connection instance
2308 */
2309
2310int
2311libwebsocket_get_socket_fd(struct libwebsocket *wsi)
2312{
2313 return wsi->sock;
2314}
2315
Andy Green90c7cbc2011-01-27 06:26:52 +00002316/**
2317 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
2318 * receieved packets.
2319 *
2320 * If the output side of a server process becomes choked, this allows flow
2321 * control for the input side.
2322 *
2323 * @wsi: Websocket connection instance to get callback for
2324 * @enable: 0 = disable read servicing for this connection, 1 = enable
2325 */
2326
2327int
2328libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
2329{
Peter Hinz56885f32011-03-02 22:03:47 +00002330 struct libwebsocket_context *context = wsi->protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002331 int n;
2332
Peter Hinz56885f32011-03-02 22:03:47 +00002333 for (n = 0; n < context->fds_count; n++)
2334 if (context->fds[n].fd == wsi->sock) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002335 if (enable)
Peter Hinz56885f32011-03-02 22:03:47 +00002336 context->fds[n].events |= POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002337 else
Peter Hinz56885f32011-03-02 22:03:47 +00002338 context->fds[n].events &= ~POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002339
2340 return 0;
2341 }
2342
Andy Green3221f922011-02-12 13:14:11 +00002343 if (enable)
2344 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002345 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002346 LWS_CALLBACK_SET_MODE_POLL_FD,
2347 (void *)(long)wsi->sock, NULL, POLLIN);
2348 else
2349 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002350 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002351 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
2352 (void *)(long)wsi->sock, NULL, POLLIN);
2353
Andy Greena41314f2011-05-23 10:00:03 +01002354#if 0
2355 fprintf(stderr, "libwebsocket_rx_flow_control "
Andy Green90c7cbc2011-01-27 06:26:52 +00002356 "unable to find socket\n");
Andy Greena41314f2011-05-23 10:00:03 +01002357#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002358 return 1;
2359}
2360
Andy Green2ac5a6f2011-01-28 10:00:18 +00002361/**
2362 * libwebsocket_canonical_hostname() - returns this host's hostname
2363 *
2364 * This is typically used by client code to fill in the host parameter
2365 * when making a client connection. You can only call it after the context
2366 * has been created.
2367 *
Peter Hinz56885f32011-03-02 22:03:47 +00002368 * @context: Websocket context
Andy Green2ac5a6f2011-01-28 10:00:18 +00002369 */
2370
2371
2372extern const char *
Peter Hinz56885f32011-03-02 22:03:47 +00002373libwebsocket_canonical_hostname(struct libwebsocket_context *context)
Andy Green2ac5a6f2011-01-28 10:00:18 +00002374{
Peter Hinz56885f32011-03-02 22:03:47 +00002375 return (const char *)context->canonical_hostname;
Andy Green2ac5a6f2011-01-28 10:00:18 +00002376}
2377
2378
Andy Green90c7cbc2011-01-27 06:26:52 +00002379static void sigpipe_handler(int x)
2380{
2381}
2382
Andy Green6901cb32011-02-21 08:06:47 +00002383#ifdef LWS_OPENSSL_SUPPORT
2384static int
2385OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
2386{
2387
2388 SSL *ssl;
2389 int n;
Andy Green2e24da02011-03-05 16:12:04 +00002390 struct libwebsocket_context *context;
Andy Green6901cb32011-02-21 08:06:47 +00002391
2392 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
2393 SSL_get_ex_data_X509_STORE_CTX_idx());
2394
2395 /*
Andy Green2e24da02011-03-05 16:12:04 +00002396 * !!! nasty openssl requires the index to come as a library-scope
2397 * static
Andy Green6901cb32011-02-21 08:06:47 +00002398 */
Andy Green2e24da02011-03-05 16:12:04 +00002399 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
Andy Green6901cb32011-02-21 08:06:47 +00002400
Peter Hinz56885f32011-03-02 22:03:47 +00002401 n = context->protocols[0].callback(NULL, NULL,
Andy Green6901cb32011-02-21 08:06:47 +00002402 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
2403 x509_ctx, ssl, preverify_ok);
2404
2405 /* convert return code from 0 = OK to 1 = OK */
2406
2407 if (!n)
2408 n = 1;
2409 else
2410 n = 0;
2411
2412 return n;
2413}
2414#endif
2415
Andy Greenb45993c2010-12-18 15:13:50 +00002416
Andy Greenab990e42010-10-31 12:42:52 +00002417/**
Andy Green4739e5c2011-01-22 12:51:57 +00002418 * libwebsocket_create_context() - Create the websocket handler
2419 * @port: Port to listen on... you can use 0 to suppress listening on
Andy Green6964bb52011-01-23 16:50:33 +00002420 * any port, that's what you want if you are not running a
2421 * websocket server at all but just using it as a client
Peter Hinz56885f32011-03-02 22:03:47 +00002422 * @interf: NULL to bind the listen socket to all interfaces, or the
Andy Green32375b72011-02-19 08:32:53 +00002423 * interface name, eg, "eth2"
Andy Green4f3943a2010-11-12 10:44:16 +00002424 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +00002425 * specific callback for each one. The list is ended with an
2426 * entry that has a NULL callback pointer.
Andy Green6964bb52011-01-23 16:50:33 +00002427 * It's not const because we write the owning_server member
Andy Greenc5114822011-03-06 10:29:35 +00002428 * @extensions: NULL or array of libwebsocket_extension structs listing the
2429 * extensions this context supports
Andy Green3faa9c72010-11-08 17:03:03 +00002430 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +00002431 * to listen using SSL, set to the filepath to fetch the
2432 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +00002433 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +00002434 * else ignored
Andy Green3faa9c72010-11-08 17:03:03 +00002435 * @gid: group id to change to after setting listen socket, or -1.
2436 * @uid: user id to change to after setting listen socket, or -1.
Andy Greenbfb051f2011-02-09 08:49:14 +00002437 * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
Andy Green05464c62010-11-12 10:44:18 +00002438 *
Andy Green8f037e42010-12-19 22:13:26 +00002439 * This function creates the listening socket and takes care
2440 * of all initialization in one step.
2441 *
Andy Greene92cd172011-01-19 13:11:55 +00002442 * After initialization, it returns a struct libwebsocket_context * that
2443 * represents this server. After calling, user code needs to take care
2444 * of calling libwebsocket_service() with the context pointer to get the
2445 * server's sockets serviced. This can be done in the same process context
2446 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +00002447 *
Andy Green8f037e42010-12-19 22:13:26 +00002448 * The protocol callback functions are called for a handful of events
2449 * including http requests coming in, websocket connections becoming
2450 * established, and data arriving; it's also called periodically to allow
2451 * async transmission.
2452 *
2453 * HTTP requests are sent always to the FIRST protocol in @protocol, since
2454 * at that time websocket protocol has not been negotiated. Other
2455 * protocols after the first one never see any HTTP callack activity.
2456 *
2457 * The server created is a simple http server by default; part of the
2458 * websocket standard is upgrading this http connection to a websocket one.
2459 *
2460 * This allows the same server to provide files like scripts and favicon /
2461 * images or whatever over http and dynamic data over websockets all in
2462 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +00002463 */
Andy Green4ea60062010-10-30 12:15:07 +01002464
Andy Greene92cd172011-01-19 13:11:55 +00002465struct libwebsocket_context *
Peter Hinz56885f32011-03-02 22:03:47 +00002466libwebsocket_create_context(int port, const char *interf,
Andy Greenb45993c2010-12-18 15:13:50 +00002467 struct libwebsocket_protocols *protocols,
Andy Greend6e09112011-03-05 16:12:15 +00002468 struct libwebsocket_extension *extensions,
Andy Green8f037e42010-12-19 22:13:26 +00002469 const char *ssl_cert_filepath,
2470 const char *ssl_private_key_filepath,
Andy Green8014b292011-01-30 20:57:25 +00002471 int gid, int uid, unsigned int options)
Andy Greenff95d7a2010-10-28 22:36:01 +01002472{
2473 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002474 int m;
Andy Green4739e5c2011-01-22 12:51:57 +00002475 int sockfd = 0;
Andy Green251f6fa2010-11-03 11:13:06 +00002476 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +01002477 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +00002478 int opt = 1;
Peter Hinz56885f32011-03-02 22:03:47 +00002479 struct libwebsocket_context *context = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002480 unsigned int slen;
Andy Green9659f372011-01-27 22:01:43 +00002481 char *p;
Andy Green2ac5a6f2011-01-28 10:00:18 +00002482 char hostname[1024];
Andy Green42f69142011-01-30 08:10:02 +00002483 struct hostent *he;
Andy Green0d338332011-02-12 11:57:43 +00002484 struct libwebsocket *wsi;
Andy Greenff95d7a2010-10-28 22:36:01 +01002485
Andy Green3faa9c72010-11-08 17:03:03 +00002486#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +00002487 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +00002488 char ssl_err_buf[512];
Andy Green3faa9c72010-11-08 17:03:03 +00002489#endif
2490
Peter Hinz56885f32011-03-02 22:03:47 +00002491#ifdef _WIN32
2492 {
2493 WORD wVersionRequested;
2494 WSADATA wsaData;
2495 int err;
David Galeano7b11fec2011-10-04 19:55:18 +08002496 HMODULE wsdll;
Peter Hinz56885f32011-03-02 22:03:47 +00002497
2498 /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
2499 wVersionRequested = MAKEWORD(2, 2);
2500
2501 err = WSAStartup(wVersionRequested, &wsaData);
2502 if (err != 0) {
2503 /* Tell the user that we could not find a usable */
2504 /* Winsock DLL. */
2505 fprintf(stderr, "WSAStartup failed with error: %d\n",
2506 err);
2507 return NULL;
2508 }
David Galeano7b11fec2011-10-04 19:55:18 +08002509
2510 wsdll = GetModuleHandle("Ws2_32.dll");
2511 if (wsdll)
2512 {
2513 poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
2514 }
2515
2516 if (!poll)
2517 {
2518 poll = emulated_poll;
2519 }
Peter Hinz56885f32011-03-02 22:03:47 +00002520 }
2521#endif
2522
2523
2524 context = malloc(sizeof(struct libwebsocket_context));
2525 if (!context) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002526 fprintf(stderr, "No memory for websocket context\n");
2527 return NULL;
2528 }
Peter Hinz56885f32011-03-02 22:03:47 +00002529 context->protocols = protocols;
2530 context->listen_port = port;
2531 context->http_proxy_port = 0;
2532 context->http_proxy_address[0] = '\0';
2533 context->options = options;
2534 context->fds_count = 0;
Andy Greend6e09112011-03-05 16:12:15 +00002535 context->extensions = extensions;
Andy Green9659f372011-01-27 22:01:43 +00002536
Peter Hinz56885f32011-03-02 22:03:47 +00002537#ifdef WIN32
2538 context->fd_random = 0;
2539#else
2540 context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
2541 if (context->fd_random < 0) {
Andy Green44eee682011-02-10 09:32:24 +00002542 fprintf(stderr, "Unable to open random device %s %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002543 SYSTEM_RANDOM_FILEPATH, context->fd_random);
Andy Green44eee682011-02-10 09:32:24 +00002544 return NULL;
2545 }
Peter Hinz56885f32011-03-02 22:03:47 +00002546#endif
Andy Green44eee682011-02-10 09:32:24 +00002547
Peter Hinz56885f32011-03-02 22:03:47 +00002548#ifdef LWS_OPENSSL_SUPPORT
2549 context->use_ssl = 0;
2550 context->ssl_ctx = NULL;
2551 context->ssl_client_ctx = NULL;
Andy Green2e24da02011-03-05 16:12:04 +00002552 openssl_websocket_private_data_index = 0;
Peter Hinz56885f32011-03-02 22:03:47 +00002553#endif
Andy Green2ac5a6f2011-01-28 10:00:18 +00002554 /* find canonical hostname */
2555
2556 hostname[(sizeof hostname) - 1] = '\0';
2557 gethostname(hostname, (sizeof hostname) - 1);
2558 he = gethostbyname(hostname);
Darin Willitsc19456f2011-02-14 17:52:39 +00002559 if (he) {
Peter Hinz56885f32011-03-02 22:03:47 +00002560 strncpy(context->canonical_hostname, he->h_name,
2561 sizeof context->canonical_hostname - 1);
2562 context->canonical_hostname[
2563 sizeof context->canonical_hostname - 1] = '\0';
Darin Willitsc19456f2011-02-14 17:52:39 +00002564 } else
Peter Hinz56885f32011-03-02 22:03:47 +00002565 strncpy(context->canonical_hostname, hostname,
2566 sizeof context->canonical_hostname - 1);
Andy Green2ac5a6f2011-01-28 10:00:18 +00002567
Andy Green9659f372011-01-27 22:01:43 +00002568 /* split the proxy ads:port if given */
2569
2570 p = getenv("http_proxy");
2571 if (p) {
Peter Hinz56885f32011-03-02 22:03:47 +00002572 strncpy(context->http_proxy_address, p,
2573 sizeof context->http_proxy_address - 1);
2574 context->http_proxy_address[
2575 sizeof context->http_proxy_address - 1] = '\0';
Andy Green9659f372011-01-27 22:01:43 +00002576
Peter Hinz56885f32011-03-02 22:03:47 +00002577 p = strchr(context->http_proxy_address, ':');
Andy Green9659f372011-01-27 22:01:43 +00002578 if (p == NULL) {
2579 fprintf(stderr, "http_proxy needs to be ads:port\n");
2580 return NULL;
2581 }
2582 *p = '\0';
Peter Hinz56885f32011-03-02 22:03:47 +00002583 context->http_proxy_port = atoi(p + 1);
Andy Green9659f372011-01-27 22:01:43 +00002584
2585 fprintf(stderr, "Using proxy %s:%u\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002586 context->http_proxy_address,
2587 context->http_proxy_port);
Andy Green9659f372011-01-27 22:01:43 +00002588 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002589
2590 if (port) {
2591
Andy Green3faa9c72010-11-08 17:03:03 +00002592#ifdef LWS_OPENSSL_SUPPORT
Peter Hinz56885f32011-03-02 22:03:47 +00002593 context->use_ssl = ssl_cert_filepath != NULL &&
Andy Green90c7cbc2011-01-27 06:26:52 +00002594 ssl_private_key_filepath != NULL;
Peter Hinz56885f32011-03-02 22:03:47 +00002595 if (context->use_ssl)
Andy Green90c7cbc2011-01-27 06:26:52 +00002596 fprintf(stderr, " Compiled with SSL support, "
2597 "using it\n");
2598 else
2599 fprintf(stderr, " Compiled with SSL support, "
2600 "not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +00002601
Andy Green90c7cbc2011-01-27 06:26:52 +00002602#else
2603 if (ssl_cert_filepath != NULL &&
2604 ssl_private_key_filepath != NULL) {
2605 fprintf(stderr, " Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +00002606 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002607 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002608 fprintf(stderr, " Compiled without SSL support, "
2609 "serving unencrypted\n");
2610#endif
2611 }
2612
2613 /* ignore SIGPIPE */
Peter Hinz56885f32011-03-02 22:03:47 +00002614#ifdef WIN32
2615#else
Andy Green90c7cbc2011-01-27 06:26:52 +00002616 signal(SIGPIPE, sigpipe_handler);
Peter Hinz56885f32011-03-02 22:03:47 +00002617#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002618
2619
2620#ifdef LWS_OPENSSL_SUPPORT
2621
2622 /* basic openssl init */
2623
2624 SSL_library_init();
2625
2626 OpenSSL_add_all_algorithms();
2627 SSL_load_error_strings();
2628
Andy Green2e24da02011-03-05 16:12:04 +00002629 openssl_websocket_private_data_index =
Andy Green6901cb32011-02-21 08:06:47 +00002630 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
2631
Andy Green90c7cbc2011-01-27 06:26:52 +00002632 /*
2633 * Firefox insists on SSLv23 not SSLv3
2634 * Konq disables SSLv2 by default now, SSLv23 works
2635 */
2636
2637 method = (SSL_METHOD *)SSLv23_server_method();
2638 if (!method) {
2639 fprintf(stderr, "problem creating ssl method: %s\n",
2640 ERR_error_string(ERR_get_error(), ssl_err_buf));
2641 return NULL;
2642 }
Peter Hinz56885f32011-03-02 22:03:47 +00002643 context->ssl_ctx = SSL_CTX_new(method); /* create context */
2644 if (!context->ssl_ctx) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002645 fprintf(stderr, "problem creating ssl context: %s\n",
2646 ERR_error_string(ERR_get_error(), ssl_err_buf));
2647 return NULL;
2648 }
2649
2650 /* client context */
Peter Hinz56885f32011-03-02 22:03:47 +00002651 if (port == CONTEXT_PORT_NO_LISTEN)
2652 {
2653 method = (SSL_METHOD *)SSLv23_client_method();
2654 if (!method) {
2655 fprintf(stderr, "problem creating ssl method: %s\n",
2656 ERR_error_string(ERR_get_error(), ssl_err_buf));
2657 return NULL;
2658 }
2659 /* create context */
2660 context->ssl_client_ctx = SSL_CTX_new(method);
2661 if (!context->ssl_client_ctx) {
2662 fprintf(stderr, "problem creating ssl context: %s\n",
2663 ERR_error_string(ERR_get_error(), ssl_err_buf));
2664 return NULL;
2665 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002666
Peter Hinz56885f32011-03-02 22:03:47 +00002667 /* openssl init for cert verification (for client sockets) */
Andy Green90c7cbc2011-01-27 06:26:52 +00002668
Peter Hinz56885f32011-03-02 22:03:47 +00002669 if (!SSL_CTX_load_verify_locations(
2670 context->ssl_client_ctx, NULL,
2671 LWS_OPENSSL_CLIENT_CERTS))
2672 fprintf(stderr,
2673 "Unable to load SSL Client certs from %s "
2674 "(set by --with-client-cert-dir= in configure) -- "
2675 " client ssl isn't going to work",
Andy Green90c7cbc2011-01-27 06:26:52 +00002676 LWS_OPENSSL_CLIENT_CERTS);
Peter Hinz56885f32011-03-02 22:03:47 +00002677
2678 /*
2679 * callback allowing user code to load extra verification certs
2680 * helping the client to verify server identity
2681 */
2682
2683 context->protocols[0].callback(context, NULL,
2684 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
2685 context->ssl_client_ctx, NULL, 0);
Andy Green90c7cbc2011-01-27 06:26:52 +00002686 }
Andy Greenc6bf2c22011-02-20 11:10:47 +00002687 /* as a server, are we requiring clients to identify themselves? */
2688
2689 if (options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
2690
2691 /* absolutely require the client cert */
2692
Peter Hinz56885f32011-03-02 22:03:47 +00002693 SSL_CTX_set_verify(context->ssl_ctx,
Andy Green6901cb32011-02-21 08:06:47 +00002694 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2695 OpenSSL_verify_callback);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002696
2697 /*
2698 * give user code a chance to load certs into the server
2699 * allowing it to verify incoming client certs
2700 */
2701
Peter Hinz56885f32011-03-02 22:03:47 +00002702 context->protocols[0].callback(context, NULL,
Andy Greenc6bf2c22011-02-20 11:10:47 +00002703 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
Peter Hinz56885f32011-03-02 22:03:47 +00002704 context->ssl_ctx, NULL, 0);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002705 }
2706
Peter Hinz56885f32011-03-02 22:03:47 +00002707 if (context->use_ssl) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002708
2709 /* openssl init for server sockets */
2710
Andy Green3faa9c72010-11-08 17:03:03 +00002711 /* set the local certificate from CertFile */
Peter Hinz56885f32011-03-02 22:03:47 +00002712 n = SSL_CTX_use_certificate_file(context->ssl_ctx,
Andy Green3faa9c72010-11-08 17:03:03 +00002713 ssl_cert_filepath, SSL_FILETYPE_PEM);
2714 if (n != 1) {
2715 fprintf(stderr, "problem getting cert '%s': %s\n",
2716 ssl_cert_filepath,
2717 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002718 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002719 }
2720 /* set the private key from KeyFile */
Peter Hinz56885f32011-03-02 22:03:47 +00002721 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
2722 ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
Andy Green018d8eb2010-11-08 21:04:23 +00002723 fprintf(stderr, "ssl problem getting key '%s': %s\n",
2724 ssl_private_key_filepath,
2725 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002726 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002727 }
2728 /* verify private key */
Peter Hinz56885f32011-03-02 22:03:47 +00002729 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
Andy Green018d8eb2010-11-08 21:04:23 +00002730 fprintf(stderr, "Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +00002731 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002732 }
2733
2734 /* SSL is happy and has a cert it's content with */
2735 }
2736#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002737
Andy Greendf736162011-01-18 15:39:02 +00002738 /* selftest */
2739
2740 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +00002741 return NULL;
Andy Greendf736162011-01-18 15:39:02 +00002742
Andy Green0d338332011-02-12 11:57:43 +00002743 /* fd hashtable init */
2744
2745 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002746 context->fd_hashtable[n].length = 0;
Andy Green0d338332011-02-12 11:57:43 +00002747
Andy Greenb45993c2010-12-18 15:13:50 +00002748 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +00002749
Andy Green4739e5c2011-01-22 12:51:57 +00002750 if (port) {
Andy Green8f037e42010-12-19 22:13:26 +00002751
Andy Green4739e5c2011-01-22 12:51:57 +00002752 sockfd = socket(AF_INET, SOCK_STREAM, 0);
2753 if (sockfd < 0) {
2754 fprintf(stderr, "ERROR opening socket");
2755 return NULL;
2756 }
Andy Green775c0dd2010-10-29 14:15:22 +01002757
Andy Green4739e5c2011-01-22 12:51:57 +00002758 /* allow us to restart even if old sockets in TIME_WAIT */
David Galeanof7009352011-09-26 12:09:54 +01002759 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
Andy Greene77ddd82010-11-13 10:03:47 +00002760
Andy Green6c939552011-03-08 08:56:57 +00002761
2762 /* Disable Nagle */
2763 opt = 1;
David Galeanof7009352011-09-26 12:09:54 +01002764 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00002765
Andy Green4739e5c2011-01-22 12:51:57 +00002766 bzero((char *) &serv_addr, sizeof(serv_addr));
2767 serv_addr.sin_family = AF_INET;
Peter Hinz56885f32011-03-02 22:03:47 +00002768 if (interf == NULL)
Andy Green32375b72011-02-19 08:32:53 +00002769 serv_addr.sin_addr.s_addr = INADDR_ANY;
2770 else
Peter Hinz56885f32011-03-02 22:03:47 +00002771 interface_to_sa(interf, &serv_addr,
Andy Green32375b72011-02-19 08:32:53 +00002772 sizeof(serv_addr));
Andy Green4739e5c2011-01-22 12:51:57 +00002773 serv_addr.sin_port = htons(port);
2774
2775 n = bind(sockfd, (struct sockaddr *) &serv_addr,
2776 sizeof(serv_addr));
2777 if (n < 0) {
2778 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
Andy Green8f037e42010-12-19 22:13:26 +00002779 port, n, errno);
Andy Green4739e5c2011-01-22 12:51:57 +00002780 return NULL;
2781 }
Andy Green0d338332011-02-12 11:57:43 +00002782
2783 wsi = malloc(sizeof(struct libwebsocket));
2784 memset(wsi, 0, sizeof (struct libwebsocket));
2785 wsi->sock = sockfd;
Andy Greend6e09112011-03-05 16:12:15 +00002786 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00002787 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
Peter Hinz56885f32011-03-02 22:03:47 +00002788 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002789
2790 listen(sockfd, 5);
2791 fprintf(stderr, " Listening on port %d\n", port);
2792
2793 /* list in the internal poll array */
2794
Peter Hinz56885f32011-03-02 22:03:47 +00002795 context->fds[context->fds_count].fd = sockfd;
2796 context->fds[context->fds_count++].events = POLLIN;
Andy Green3221f922011-02-12 13:14:11 +00002797
2798 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002799 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002800 LWS_CALLBACK_ADD_POLL_FD,
2801 (void *)(long)sockfd, NULL, POLLIN);
2802
Andy Green8f037e42010-12-19 22:13:26 +00002803 }
Andy Greenb45993c2010-12-18 15:13:50 +00002804
Andy Greene77ddd82010-11-13 10:03:47 +00002805 /* drop any root privs for this process */
Peter Hinz56885f32011-03-02 22:03:47 +00002806#ifdef WIN32
2807#else
Andy Green3faa9c72010-11-08 17:03:03 +00002808 if (gid != -1)
2809 if (setgid(gid))
2810 fprintf(stderr, "setgid: %s\n", strerror(errno));
2811 if (uid != -1)
2812 if (setuid(uid))
2813 fprintf(stderr, "setuid: %s\n", strerror(errno));
Peter Hinz56885f32011-03-02 22:03:47 +00002814#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002815
2816 /* set up our internal broadcast trigger sockets per-protocol */
2817
Peter Hinz56885f32011-03-02 22:03:47 +00002818 for (context->count_protocols = 0;
2819 protocols[context->count_protocols].callback;
2820 context->count_protocols++) {
Andy Green2d1301e2011-05-24 10:14:41 +01002821
2822 fprintf(stderr, " Protocol: %s\n", protocols[context->count_protocols].name);
2823
Peter Hinz56885f32011-03-02 22:03:47 +00002824 protocols[context->count_protocols].owning_server = context;
2825 protocols[context->count_protocols].protocol_index =
2826 context->count_protocols;
Andy Greenb45993c2010-12-18 15:13:50 +00002827
2828 fd = socket(AF_INET, SOCK_STREAM, 0);
2829 if (fd < 0) {
2830 fprintf(stderr, "ERROR opening socket");
Andy Greene92cd172011-01-19 13:11:55 +00002831 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002832 }
Andy Green8f037e42010-12-19 22:13:26 +00002833
Andy Greenb45993c2010-12-18 15:13:50 +00002834 /* allow us to restart even if old sockets in TIME_WAIT */
David Galeanof7009352011-09-26 12:09:54 +01002835 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
Andy Greenb45993c2010-12-18 15:13:50 +00002836
2837 bzero((char *) &serv_addr, sizeof(serv_addr));
2838 serv_addr.sin_family = AF_INET;
2839 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
2840 serv_addr.sin_port = 0; /* pick the port for us */
2841
2842 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
2843 if (n < 0) {
Andy Green8f037e42010-12-19 22:13:26 +00002844 fprintf(stderr, "ERROR on binding to port %d (%d %d)\n",
Andy Greenb45993c2010-12-18 15:13:50 +00002845 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +00002846 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002847 }
2848
2849 slen = sizeof cli_addr;
2850 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
2851 if (n < 0) {
2852 fprintf(stderr, "getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +00002853 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002854 }
Peter Hinz56885f32011-03-02 22:03:47 +00002855 protocols[context->count_protocols].broadcast_socket_port =
Andy Greenb45993c2010-12-18 15:13:50 +00002856 ntohs(cli_addr.sin_port);
2857 listen(fd, 5);
2858
2859 debug(" Protocol %s broadcast socket %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002860 protocols[context->count_protocols].name,
Andy Greenb45993c2010-12-18 15:13:50 +00002861 ntohs(cli_addr.sin_port));
2862
Andy Green0d338332011-02-12 11:57:43 +00002863 /* dummy wsi per broadcast proxy socket */
2864
2865 wsi = malloc(sizeof(struct libwebsocket));
2866 memset(wsi, 0, sizeof (struct libwebsocket));
2867 wsi->sock = fd;
2868 wsi->mode = LWS_CONNMODE_BROADCAST_PROXY_LISTENER;
Andy Greend6e09112011-03-05 16:12:15 +00002869 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00002870 /* note which protocol we are proxying */
Peter Hinz56885f32011-03-02 22:03:47 +00002871 wsi->protocol_index_for_broadcast_proxy =
2872 context->count_protocols;
2873 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002874
2875 /* list in internal poll array */
2876
Peter Hinz56885f32011-03-02 22:03:47 +00002877 context->fds[context->fds_count].fd = fd;
2878 context->fds[context->fds_count].events = POLLIN;
2879 context->fds[context->fds_count].revents = 0;
2880 context->fds_count++;
Andy Green3221f922011-02-12 13:14:11 +00002881
2882 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002883 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002884 LWS_CALLBACK_ADD_POLL_FD,
2885 (void *)(long)fd, NULL, POLLIN);
Andy Greenb45993c2010-12-18 15:13:50 +00002886 }
2887
Andy Greena41314f2011-05-23 10:00:03 +01002888 /*
2889 * give all extensions a chance to create any per-context
2890 * allocations they need
2891 */
2892
2893 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
2894 if (port)
2895 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
2896 while (extensions->callback) {
Andy Green2d1301e2011-05-24 10:14:41 +01002897 fprintf(stderr, " Extension: %s\n", extensions->name);
Andy Greena41314f2011-05-23 10:00:03 +01002898 extensions->callback(context, extensions,
2899 NULL, m, NULL, NULL, 0);
2900 extensions++;
2901 }
2902
Peter Hinz56885f32011-03-02 22:03:47 +00002903 return context;
Andy Greene92cd172011-01-19 13:11:55 +00002904}
Andy Greenb45993c2010-12-18 15:13:50 +00002905
Andy Green4739e5c2011-01-22 12:51:57 +00002906
Andy Greened11a022011-01-20 10:23:50 +00002907#ifndef LWS_NO_FORK
2908
Andy Greene92cd172011-01-19 13:11:55 +00002909/**
2910 * libwebsockets_fork_service_loop() - Optional helper function forks off
2911 * a process for the websocket server loop.
Andy Green6964bb52011-01-23 16:50:33 +00002912 * You don't have to use this but if not, you
2913 * have to make sure you are calling
2914 * libwebsocket_service periodically to service
2915 * the websocket traffic
Peter Hinz56885f32011-03-02 22:03:47 +00002916 * @context: server context returned by creation function
Andy Greene92cd172011-01-19 13:11:55 +00002917 */
Andy Greenb45993c2010-12-18 15:13:50 +00002918
Andy Greene92cd172011-01-19 13:11:55 +00002919int
Peter Hinz56885f32011-03-02 22:03:47 +00002920libwebsockets_fork_service_loop(struct libwebsocket_context *context)
Andy Greene92cd172011-01-19 13:11:55 +00002921{
Andy Greene92cd172011-01-19 13:11:55 +00002922 int fd;
2923 struct sockaddr_in cli_addr;
2924 int n;
Andy Green3221f922011-02-12 13:14:11 +00002925 int p;
Andy Greenb45993c2010-12-18 15:13:50 +00002926
Andy Greened11a022011-01-20 10:23:50 +00002927 n = fork();
2928 if (n < 0)
2929 return n;
2930
2931 if (!n) {
2932
2933 /* main process context */
2934
Andy Green3221f922011-02-12 13:14:11 +00002935 /*
2936 * set up the proxy sockets to allow broadcast from
2937 * service process context
2938 */
2939
Peter Hinz56885f32011-03-02 22:03:47 +00002940 for (p = 0; p < context->count_protocols; p++) {
Andy Greened11a022011-01-20 10:23:50 +00002941 fd = socket(AF_INET, SOCK_STREAM, 0);
2942 if (fd < 0) {
2943 fprintf(stderr, "Unable to create socket\n");
2944 return -1;
2945 }
2946 cli_addr.sin_family = AF_INET;
2947 cli_addr.sin_port = htons(
Peter Hinz56885f32011-03-02 22:03:47 +00002948 context->protocols[p].broadcast_socket_port);
Andy Greened11a022011-01-20 10:23:50 +00002949 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
2950 n = connect(fd, (struct sockaddr *)&cli_addr,
2951 sizeof cli_addr);
2952 if (n < 0) {
2953 fprintf(stderr, "Unable to connect to "
2954 "broadcast socket %d, %s\n",
Andy Green3221f922011-02-12 13:14:11 +00002955 n, strerror(errno));
Andy Greened11a022011-01-20 10:23:50 +00002956 return -1;
2957 }
2958
Peter Hinz56885f32011-03-02 22:03:47 +00002959 context->protocols[p].broadcast_socket_user_fd = fd;
Andy Greened11a022011-01-20 10:23:50 +00002960 }
2961
Andy Greene92cd172011-01-19 13:11:55 +00002962 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00002963 }
2964
2965 /* we want a SIGHUP when our parent goes down */
2966 prctl(PR_SET_PDEATHSIG, SIGHUP);
2967
2968 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +00002969
Andy Greene92cd172011-01-19 13:11:55 +00002970 while (1)
Peter Hinz56885f32011-03-02 22:03:47 +00002971 if (libwebsocket_service(context, 1000))
Andy Greene92cd172011-01-19 13:11:55 +00002972 return -1;
Andy Green8f037e42010-12-19 22:13:26 +00002973
Andy Green251f6fa2010-11-03 11:13:06 +00002974 return 0;
Andy Greenff95d7a2010-10-28 22:36:01 +01002975}
2976
Andy Greened11a022011-01-20 10:23:50 +00002977#endif
2978
Andy Greenb45993c2010-12-18 15:13:50 +00002979/**
2980 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +00002981 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +00002982 * @wsi: pointer to struct websocket you want to know the protocol of
2983 *
Andy Green8f037e42010-12-19 22:13:26 +00002984 *
2985 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +00002986 * the callback.
2987 */
Andy Greenab990e42010-10-31 12:42:52 +00002988
Andy Greenb45993c2010-12-18 15:13:50 +00002989const struct libwebsocket_protocols *
2990libwebsockets_get_protocol(struct libwebsocket *wsi)
2991{
2992 return wsi->protocol;
2993}
2994
2995/**
Andy Greene92cd172011-01-19 13:11:55 +00002996 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +00002997 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +00002998 * @protocol: pointer to the protocol you will broadcast to all members of
2999 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +00003000 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
3001 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
3002 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +00003003 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +00003004 *
3005 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +00003006 * the given protocol. It does not send the data directly; instead it calls
3007 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
3008 * wants to actually send the data for that connection, the callback itself
3009 * should call libwebsocket_write().
3010 *
3011 * libwebsockets_broadcast() can be called from another fork context without
3012 * having to take any care about data visibility between the processes, it'll
3013 * "just work".
3014 */
3015
3016
3017int
Andy Green8f037e42010-12-19 22:13:26 +00003018libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +00003019 unsigned char *buf, size_t len)
3020{
Peter Hinz56885f32011-03-02 22:03:47 +00003021 struct libwebsocket_context *context = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +00003022 int n;
Andy Green0d338332011-02-12 11:57:43 +00003023 int m;
3024 struct libwebsocket * wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00003025
3026 if (!protocol->broadcast_socket_user_fd) {
3027 /*
Andy Greene92cd172011-01-19 13:11:55 +00003028 * We are either running unforked / flat, or we are being
3029 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +00003030 * eg, from a callback. In that case don't use sockets for
3031 * broadcast IPC (since we can't open a socket connection to
3032 * a socket listening on our own thread) but directly do the
3033 * send action.
3034 *
3035 * Locking is not needed because we are by definition being
3036 * called in the poll thread context and are serialized.
3037 */
3038
Andy Green0d338332011-02-12 11:57:43 +00003039 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003040
Peter Hinz56885f32011-03-02 22:03:47 +00003041 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003042
Peter Hinz56885f32011-03-02 22:03:47 +00003043 wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00003044
Andy Green0d338332011-02-12 11:57:43 +00003045 if (wsi->mode != LWS_CONNMODE_WS_SERVING)
3046 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00003047
Andy Green0d338332011-02-12 11:57:43 +00003048 /*
3049 * never broadcast to
3050 * non-established connections
3051 */
3052 if (wsi->state != WSI_STATE_ESTABLISHED)
3053 continue;
3054
3055 /* only broadcast to guys using
3056 * requested protocol
3057 */
3058 if (wsi->protocol != protocol)
3059 continue;
3060
Peter Hinz56885f32011-03-02 22:03:47 +00003061 wsi->protocol->callback(context, wsi,
Andy Green8f037e42010-12-19 22:13:26 +00003062 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00003063 wsi->user_space,
Andy Greenb45993c2010-12-18 15:13:50 +00003064 buf, len);
Andy Green0d338332011-02-12 11:57:43 +00003065 }
Andy Greenb45993c2010-12-18 15:13:50 +00003066 }
3067
3068 return 0;
3069 }
3070
Andy Green0ca6a172010-12-19 20:50:01 +00003071 /*
3072 * We're being called from a different process context than the server
3073 * loop. Instead of broadcasting directly, we send our
3074 * payload on a socket to do the IPC; the server process will serialize
3075 * the broadcast action in its main poll() loop.
3076 *
3077 * There's one broadcast socket listening for each protocol supported
3078 * set up when the websocket server initializes
3079 */
3080
Andy Green6964bb52011-01-23 16:50:33 +00003081 n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
Andy Greenb45993c2010-12-18 15:13:50 +00003082
3083 return n;
3084}
Andy Green82c3d542011-03-07 21:16:31 +00003085
3086int
3087libwebsocket_is_final_fragment(struct libwebsocket *wsi)
3088{
3089 return wsi->final;
3090}
Alex Bligh49146db2011-11-07 17:19:25 +08003091
3092void *
3093libwebsocket_ensure_user_space(struct libwebsocket *wsi)
3094{
3095 /* allocate the per-connection user memory (if any) */
3096
3097 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
3098 wsi->user_space = malloc(
3099 wsi->protocol->per_session_data_size);
3100 if (wsi->user_space == NULL) {
3101 fprintf(stderr, "Out of memory for "
3102 "conn user space\n");
3103 return NULL;
3104 }
3105 memset(wsi->user_space, 0, wsi->protocol->per_session_data_size);
3106 }
3107 return wsi->user_space;
3108}