blob: 4cc70b46424f84af3f3a6c6e3f883f9090652e2a [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
David Galeanocb193682013-01-09 15:29:00 +080025#include <tchar.h>
26#include <io.h>
Peter Hinz56885f32011-03-02 22:03:47 +000027#else
Davidc4ef7b12013-01-12 20:39:47 +080028#ifdef LWS_BUILTIN_GETIFADDRS
29#include <getifaddrs.h>
30#else
Peter Hinz56885f32011-03-02 22:03:47 +000031#include <ifaddrs.h>
Davidc4ef7b12013-01-12 20:39:47 +080032#endif
Andy Green7627af52011-03-09 15:13:52 +000033#include <sys/un.h>
Andy Greena69f0512012-05-03 12:32:38 +080034#include <sys/socket.h>
35#include <netdb.h>
Peter Hinz56885f32011-03-02 22:03:47 +000036#endif
Andy Green2e24da02011-03-05 16:12:04 +000037
38#ifdef LWS_OPENSSL_SUPPORT
39int openssl_websocket_private_data_index;
40#endif
41
Andy Greenaa6fc442012-04-12 13:26:49 +080042#ifdef __MINGW32__
43#include "../win32port/win32helpers/websock-w32.c"
44#else
45#ifdef __MINGW64__
46#include "../win32port/win32helpers/websock-w32.c"
47#endif
48#endif
49
Andy Green43db0452013-01-10 19:50:35 +080050static int log_level = LLL_ERR | LLL_WARN;
Andy Greende8f27a2013-01-12 09:17:42 +080051static void lwsl_emit_stderr(const char *line);
52static void (*lwsl_emit)(const char *line) = lwsl_emit_stderr;
Andy Green43db0452013-01-10 19:50:35 +080053static const char *log_level_names[] = {
54 "ERR",
55 "WARN",
56 "INFO",
57 "DEBUG",
58 "PARSER",
59 "HEADER",
60 "EXTENSION",
61 "CLIENT",
62};
63
Andy Greenbe93fef2011-02-14 20:25:43 +000064/*
65 * In-place str to lower case
66 */
67
68static void
69strtolower(char *s)
70{
71 while (*s) {
72 *s = tolower(*s);
73 s++;
74 }
75}
76
Andy Green0d338332011-02-12 11:57:43 +000077/* file descriptor hash management */
78
79struct libwebsocket *
Peter Hinz56885f32011-03-02 22:03:47 +000080wsi_from_fd(struct libwebsocket_context *context, int fd)
Andy Green0d338332011-02-12 11:57:43 +000081{
82 int h = LWS_FD_HASH(fd);
83 int n = 0;
84
Peter Hinz56885f32011-03-02 22:03:47 +000085 for (n = 0; n < context->fd_hashtable[h].length; n++)
86 if (context->fd_hashtable[h].wsi[n]->sock == fd)
87 return context->fd_hashtable[h].wsi[n];
Andy Green0d338332011-02-12 11:57:43 +000088
89 return NULL;
90}
91
92int
Peter Hinz56885f32011-03-02 22:03:47 +000093insert_wsi(struct libwebsocket_context *context, struct libwebsocket *wsi)
Andy Green0d338332011-02-12 11:57:43 +000094{
95 int h = LWS_FD_HASH(wsi->sock);
96
Peter Hinz56885f32011-03-02 22:03:47 +000097 if (context->fd_hashtable[h].length == MAX_CLIENTS - 1) {
Andy Green43db0452013-01-10 19:50:35 +080098 lwsl_err("hash table overflow\n");
Andy Green0d338332011-02-12 11:57:43 +000099 return 1;
100 }
101
Peter Hinz56885f32011-03-02 22:03:47 +0000102 context->fd_hashtable[h].wsi[context->fd_hashtable[h].length++] = wsi;
Andy Green0d338332011-02-12 11:57:43 +0000103
104 return 0;
105}
106
107int
Peter Hinz56885f32011-03-02 22:03:47 +0000108delete_from_fd(struct libwebsocket_context *context, int fd)
Andy Green0d338332011-02-12 11:57:43 +0000109{
110 int h = LWS_FD_HASH(fd);
111 int n = 0;
112
Peter Hinz56885f32011-03-02 22:03:47 +0000113 for (n = 0; n < context->fd_hashtable[h].length; n++)
114 if (context->fd_hashtable[h].wsi[n]->sock == fd) {
115 while (n < context->fd_hashtable[h].length) {
116 context->fd_hashtable[h].wsi[n] =
117 context->fd_hashtable[h].wsi[n + 1];
Andy Green0d338332011-02-12 11:57:43 +0000118 n++;
119 }
Peter Hinz56885f32011-03-02 22:03:47 +0000120 context->fd_hashtable[h].length--;
Andy Green0d338332011-02-12 11:57:43 +0000121
122 return 0;
123 }
124
Andy Green43db0452013-01-10 19:50:35 +0800125 lwsl_err("Failed to find fd %d requested for "
Andy Green0d338332011-02-12 11:57:43 +0000126 "delete in hashtable\n", fd);
127 return 1;
128}
129
Andy Green1f9bf522011-02-14 21:14:37 +0000130#ifdef LWS_OPENSSL_SUPPORT
131static void
132libwebsockets_decode_ssl_error(void)
133{
134 char buf[256];
135 u_long err;
136
137 while ((err = ERR_get_error()) != 0) {
138 ERR_error_string_n(err, buf, sizeof(buf));
Andy Green43db0452013-01-10 19:50:35 +0800139 lwsl_err("*** %s\n", buf);
Andy Green1f9bf522011-02-14 21:14:37 +0000140 }
141}
142#endif
Andy Green0d338332011-02-12 11:57:43 +0000143
Andy Green32375b72011-02-19 08:32:53 +0000144
145static int
Andy Green6ee372f2012-04-09 15:09:01 +0800146interface_to_sa(const char *ifname, struct sockaddr_in *addr, size_t addrlen)
Andy Green32375b72011-02-19 08:32:53 +0000147{
148 int rc = -1;
Peter Hinz56885f32011-03-02 22:03:47 +0000149#ifdef WIN32
Andy Green6ee372f2012-04-09 15:09:01 +0800150 /* TODO */
Peter Hinz56885f32011-03-02 22:03:47 +0000151#else
Andy Green32375b72011-02-19 08:32:53 +0000152 struct ifaddrs *ifr;
153 struct ifaddrs *ifc;
154 struct sockaddr_in *sin;
155
156 getifaddrs(&ifr);
157 for (ifc = ifr; ifc != NULL; ifc = ifc->ifa_next) {
158 if (strcmp(ifc->ifa_name, ifname))
159 continue;
160 if (ifc->ifa_addr == NULL)
161 continue;
162 sin = (struct sockaddr_in *)ifc->ifa_addr;
163 if (sin->sin_family != AF_INET)
164 continue;
165 memcpy(addr, sin, addrlen);
Andy Green6ee372f2012-04-09 15:09:01 +0800166 rc = 0;
Andy Green32375b72011-02-19 08:32:53 +0000167 }
168
169 freeifaddrs(ifr);
Peter Hinz56885f32011-03-02 22:03:47 +0000170#endif
Andy Green32375b72011-02-19 08:32:53 +0000171 return rc;
172}
173
Andy Green8f037e42010-12-19 22:13:26 +0000174void
Peter Hinz56885f32011-03-02 22:03:47 +0000175libwebsocket_close_and_free_session(struct libwebsocket_context *context,
Andy Green687b0182011-02-26 11:04:01 +0000176 struct libwebsocket *wsi, enum lws_close_status reason)
Andy Green251f6fa2010-11-03 11:13:06 +0000177{
Andy Greenb45993c2010-12-18 15:13:50 +0000178 int n;
Andy Green62c54d22011-02-14 09:14:25 +0000179 int old_state;
Andy Green5e1fa172011-02-10 09:07:05 +0000180 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
181 LWS_SEND_BUFFER_POST_PADDING];
Andy Greenc44159f2011-03-07 07:08:18 +0000182 int ret;
183 int m;
184 struct lws_tokens eff_buf;
Andy Greena41314f2011-05-23 10:00:03 +0100185 struct libwebsocket_extension *ext;
Andy Greenb45993c2010-12-18 15:13:50 +0000186
Andy Green4b6fbe12011-02-14 08:03:48 +0000187 if (!wsi)
Andy Greenb45993c2010-12-18 15:13:50 +0000188 return;
189
Andy Green62c54d22011-02-14 09:14:25 +0000190 old_state = wsi->state;
Andy Green251f6fa2010-11-03 11:13:06 +0000191
Andy Green62c54d22011-02-14 09:14:25 +0000192 if (old_state == WSI_STATE_DEAD_SOCKET)
Andy Green5e1fa172011-02-10 09:07:05 +0000193 return;
194
Andy Greenda527df2011-03-07 07:08:12 +0000195 wsi->close_reason = reason;
196
197 /*
Andy Green68b45042011-05-25 21:41:57 +0100198 * are his extensions okay with him closing? Eg he might be a mux
199 * parent and just his ch1 aspect is closing?
200 */
201
202
203 for (n = 0; n < wsi->count_active_extensions; n++) {
204 if (!wsi->active_extensions[n]->callback)
205 continue;
206
207 m = wsi->active_extensions[n]->callback(context,
208 wsi->active_extensions[n], wsi,
209 LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
210 wsi->active_extensions_user[n], NULL, 0);
211
212 /*
213 * if somebody vetoed actually closing him at this time....
214 * up to the extension to track the attempted close, let's
215 * just bail
216 */
217
218 if (m) {
Andy Green43db0452013-01-10 19:50:35 +0800219 lwsl_ext("extension vetoed close\n");
Andy Green68b45042011-05-25 21:41:57 +0100220 return;
221 }
222 }
223
224
225
226 /*
Andy Greenc44159f2011-03-07 07:08:18 +0000227 * flush any tx pending from extensions, since we may send close packet
228 * if there are problems with send, just nuke the connection
229 */
230
231 ret = 1;
232 while (ret == 1) {
233
234 /* default to nobody has more to spill */
235
236 ret = 0;
237 eff_buf.token = NULL;
238 eff_buf.token_len = 0;
239
240 /* show every extension the new incoming data */
241
242 for (n = 0; n < wsi->count_active_extensions; n++) {
243 m = wsi->active_extensions[n]->callback(
Andy Green46c2ea02011-03-22 09:04:01 +0000244 wsi->protocol->owning_server,
245 wsi->active_extensions[n], wsi,
Andy Greenc44159f2011-03-07 07:08:18 +0000246 LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
247 wsi->active_extensions_user[n], &eff_buf, 0);
248 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +0800249 lwsl_ext("Extension reports fatal error\n");
Andy Greenc44159f2011-03-07 07:08:18 +0000250 goto just_kill_connection;
251 }
252 if (m)
253 /*
254 * at least one extension told us he has more
255 * to spill, so we will go around again after
256 */
257 ret = 1;
258 }
259
260 /* assuming they left us something to send, send it */
261
262 if (eff_buf.token_len)
263 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
264 eff_buf.token_len))
265 goto just_kill_connection;
266 }
267
268 /*
Andy Greenda527df2011-03-07 07:08:12 +0000269 * signal we are closing, libsocket_write will
270 * add any necessary version-specific stuff. If the write fails,
271 * no worries we are closing anyway. If we didn't initiate this
272 * close, then our state has been changed to
273 * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
274 *
275 * Likewise if it's a second call to close this connection after we
276 * sent the close indication to the peer already, we are in state
277 * WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
278 */
279
280 if (old_state == WSI_STATE_ESTABLISHED &&
281 reason != LWS_CLOSE_STATUS_NOSTATUS) {
Andy Green66a16f32011-05-24 22:07:45 +0100282
Andy Green43db0452013-01-10 19:50:35 +0800283 lwsl_debug("sending close indication...\n");
Andy Green66a16f32011-05-24 22:07:45 +0100284
Andy Greenda527df2011-03-07 07:08:12 +0000285 n = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING],
286 0, LWS_WRITE_CLOSE);
287 if (!n) {
288 /*
289 * we have sent a nice protocol level indication we
290 * now wish to close, we should not send anything more
291 */
292
293 wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
294
295 /* and we should wait for a reply for a bit */
296
297 libwebsocket_set_timeout(wsi,
David Galeanoc9f1ff82013-01-09 18:01:23 +0800298 PENDING_TIMEOUT_CLOSE_ACK, AWAITING_TIMEOUT);
Andy Greenda527df2011-03-07 07:08:12 +0000299
Andy Green43db0452013-01-10 19:50:35 +0800300 lwsl_debug("sent close indication, awaiting ack\n");
Andy Greenda527df2011-03-07 07:08:12 +0000301
302 return;
303 }
304
305 /* else, the send failed and we should just hang up */
306 }
307
Andy Greenc44159f2011-03-07 07:08:18 +0000308just_kill_connection:
Andy Green66a16f32011-05-24 22:07:45 +0100309
Andy Green43db0452013-01-10 19:50:35 +0800310 lwsl_debug("libwebsocket_close_and_free_session: just_kill_connection\n");
Andy Green66a16f32011-05-24 22:07:45 +0100311
Andy Greenda527df2011-03-07 07:08:12 +0000312 /*
313 * we won't be servicing or receiving anything further from this guy
314 * remove this fd from wsi mapping hashtable
315 */
Andy Green4b6fbe12011-02-14 08:03:48 +0000316
Andy Greena41314f2011-05-23 10:00:03 +0100317 if (wsi->sock)
318 delete_from_fd(context, wsi->sock);
Andy Green4b6fbe12011-02-14 08:03:48 +0000319
320 /* delete it from the internal poll list if still present */
321
Peter Hinz56885f32011-03-02 22:03:47 +0000322 for (n = 0; n < context->fds_count; n++) {
323 if (context->fds[n].fd != wsi->sock)
Andy Green4b6fbe12011-02-14 08:03:48 +0000324 continue;
Peter Hinz56885f32011-03-02 22:03:47 +0000325 while (n < context->fds_count - 1) {
326 context->fds[n] = context->fds[n + 1];
Andy Green4b6fbe12011-02-14 08:03:48 +0000327 n++;
328 }
Peter Hinz56885f32011-03-02 22:03:47 +0000329 context->fds_count--;
Andy Green4b6fbe12011-02-14 08:03:48 +0000330 /* we only have to deal with one */
Peter Hinz56885f32011-03-02 22:03:47 +0000331 n = context->fds_count;
Andy Green4b6fbe12011-02-14 08:03:48 +0000332 }
333
334 /* remove also from external POLL support via protocol 0 */
Andy Greena41314f2011-05-23 10:00:03 +0100335 if (wsi->sock)
336 context->protocols[0].callback(context, wsi,
Andy Green4b6fbe12011-02-14 08:03:48 +0000337 LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
338
Andy Green251f6fa2010-11-03 11:13:06 +0000339 wsi->state = WSI_STATE_DEAD_SOCKET;
340
Andy Green4b6fbe12011-02-14 08:03:48 +0000341 /* tell the user it's all over for this guy */
342
Andy Greend4302732011-02-28 07:45:29 +0000343 if (wsi->protocol && wsi->protocol->callback &&
Andy Green6ee372f2012-04-09 15:09:01 +0800344 ((old_state == WSI_STATE_ESTABLISHED) ||
345 (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
346 (old_state == WSI_STATE_AWAITING_CLOSE_ACK))) {
Andy Green43db0452013-01-10 19:50:35 +0800347 lwsl_debug("calling back CLOSED\n");
Peter Hinz56885f32011-03-02 22:03:47 +0000348 wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
Andy Greene77ddd82010-11-13 10:03:47 +0000349 wsi->user_space, NULL, 0);
Andy Greencc012472011-11-07 19:53:23 +0800350 } else
Andy Green43db0452013-01-10 19:50:35 +0800351 lwsl_debug("not calling back closed, old_state=%d\n", old_state);
Andy Green251f6fa2010-11-03 11:13:06 +0000352
Andy Greenef660a92011-03-06 10:29:38 +0000353 /* deallocate any active extension contexts */
354
355 for (n = 0; n < wsi->count_active_extensions; n++) {
356 if (!wsi->active_extensions[n]->callback)
357 continue;
358
Andy Green46c2ea02011-03-22 09:04:01 +0000359 wsi->active_extensions[n]->callback(context,
360 wsi->active_extensions[n], wsi,
361 LWS_EXT_CALLBACK_DESTROY,
362 wsi->active_extensions_user[n], NULL, 0);
Andy Greenef660a92011-03-06 10:29:38 +0000363
364 free(wsi->active_extensions_user[n]);
365 }
366
Andy Greena41314f2011-05-23 10:00:03 +0100367 /*
368 * inform all extensions in case they tracked this guy out of band
369 * even though not active on him specifically
370 */
371
372 ext = context->extensions;
373 while (ext && ext->callback) {
374 ext->callback(context, ext, wsi,
375 LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
376 NULL, NULL, 0);
377 ext++;
378 }
379
Andy Greenef660a92011-03-06 10:29:38 +0000380 /* free up his parsing allocations */
Andy Green4b6fbe12011-02-14 08:03:48 +0000381
Andy Green251f6fa2010-11-03 11:13:06 +0000382 for (n = 0; n < WSI_TOKEN_COUNT; n++)
383 if (wsi->utf8_token[n].token)
384 free(wsi->utf8_token[n].token);
385
Andy Greena41314f2011-05-23 10:00:03 +0100386 if (wsi->c_address)
387 free(wsi->c_address);
388
Andy Green43db0452013-01-10 19:50:35 +0800389/* lwsl_info("closing fd=%d\n", wsi->sock); */
Andy Green251f6fa2010-11-03 11:13:06 +0000390
Andy Green3faa9c72010-11-08 17:03:03 +0000391#ifdef LWS_OPENSSL_SUPPORT
Andy Green90c7cbc2011-01-27 06:26:52 +0000392 if (wsi->ssl) {
Andy Green3faa9c72010-11-08 17:03:03 +0000393 n = SSL_get_fd(wsi->ssl);
394 SSL_shutdown(wsi->ssl);
Andy Green3fc2c652013-01-14 15:35:02 +0800395 compatible_close(n);
Andy Green3faa9c72010-11-08 17:03:03 +0000396 SSL_free(wsi->ssl);
397 } else {
398#endif
399 shutdown(wsi->sock, SHUT_RDWR);
Andy Green3fc2c652013-01-14 15:35:02 +0800400
Andy Green66a16f32011-05-24 22:07:45 +0100401 if (wsi->sock)
Andy Green3fc2c652013-01-14 15:35:02 +0800402 compatible_close(wsi->sock);
Andy Green3faa9c72010-11-08 17:03:03 +0000403#ifdef LWS_OPENSSL_SUPPORT
404 }
405#endif
David Brooks2c60d952012-04-20 12:19:01 +0800406 if (wsi->protocol && wsi->protocol->per_session_data_size && wsi->user_space) /* user code may own */
Andy Green4f3943a2010-11-12 10:44:16 +0000407 free(wsi->user_space);
408
Andy Green251f6fa2010-11-03 11:13:06 +0000409 free(wsi);
410}
411
Andy Green07034092011-02-13 08:37:12 +0000412/**
Andy Greenf7ee5492011-02-13 09:04:21 +0000413 * libwebsockets_hangup_on_client() - Server calls to terminate client
Andy Green6ee372f2012-04-09 15:09:01 +0800414 * connection
Peter Hinz56885f32011-03-02 22:03:47 +0000415 * @context: libwebsockets context
Andy Greenf7ee5492011-02-13 09:04:21 +0000416 * @fd: Connection socket descriptor
417 */
418
419void
Peter Hinz56885f32011-03-02 22:03:47 +0000420libwebsockets_hangup_on_client(struct libwebsocket_context *context, int fd)
Andy Greenf7ee5492011-02-13 09:04:21 +0000421{
Peter Hinz56885f32011-03-02 22:03:47 +0000422 struct libwebsocket *wsi = wsi_from_fd(context, fd);
Andy Greenf7ee5492011-02-13 09:04:21 +0000423
424 if (wsi == NULL)
425 return;
426
Peter Hinz56885f32011-03-02 22:03:47 +0000427 libwebsocket_close_and_free_session(context, wsi,
Andy Green6da560c2011-02-26 11:06:27 +0000428 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenf7ee5492011-02-13 09:04:21 +0000429}
430
431
432/**
Andy Green07034092011-02-13 08:37:12 +0000433 * libwebsockets_get_peer_addresses() - Get client address information
434 * @fd: Connection socket descriptor
435 * @name: Buffer to take client address name
436 * @name_len: Length of client address name buffer
437 * @rip: Buffer to take client address IP qotted quad
438 * @rip_len: Length of client address IP buffer
439 *
440 * This function fills in @name and @rip with the name and IP of
Andy Green6ee372f2012-04-09 15:09:01 +0800441 * the client connected with socket descriptor @fd. Names may be
442 * truncated if there is not enough room. If either cannot be
443 * determined, they will be returned as valid zero-length strings.
Andy Green07034092011-02-13 08:37:12 +0000444 */
445
446void
447libwebsockets_get_peer_addresses(int fd, char *name, int name_len,
448 char *rip, int rip_len)
449{
450 unsigned int len;
451 struct sockaddr_in sin;
452 struct hostent *host;
453 struct hostent *host1;
454 char ip[128];
Andy Greenf92def72011-03-09 15:02:20 +0000455 unsigned char *p;
Andy Green07034092011-02-13 08:37:12 +0000456 int n;
David Galeanocb193682013-01-09 15:29:00 +0800457#ifdef AF_LOCAL
458 struct sockaddr_un *un;
459#endif
Andy Green07034092011-02-13 08:37:12 +0000460
461 rip[0] = '\0';
462 name[0] = '\0';
463
464 len = sizeof sin;
465 if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
466 perror("getpeername");
467 return;
468 }
Andy Green6ee372f2012-04-09 15:09:01 +0800469
Andy Green07034092011-02-13 08:37:12 +0000470 host = gethostbyaddr((char *) &sin.sin_addr, sizeof sin.sin_addr,
471 AF_INET);
472 if (host == NULL) {
473 perror("gethostbyaddr");
474 return;
475 }
476
477 strncpy(name, host->h_name, name_len);
478 name[name_len - 1] = '\0';
479
480 host1 = gethostbyname(host->h_name);
481 if (host1 == NULL)
482 return;
Andy Greenf92def72011-03-09 15:02:20 +0000483 p = (unsigned char *)host1;
Andy Green07034092011-02-13 08:37:12 +0000484 n = 0;
485 while (p != NULL) {
Andy Greenf92def72011-03-09 15:02:20 +0000486 p = (unsigned char *)host1->h_addr_list[n++];
Andy Green07034092011-02-13 08:37:12 +0000487 if (p == NULL)
488 continue;
Peter Hinzbb45a902011-03-10 18:14:01 +0000489 if ((host1->h_addrtype != AF_INET)
490#ifdef AF_LOCAL
491 && (host1->h_addrtype != AF_LOCAL)
492#endif
493 )
Andy Green07034092011-02-13 08:37:12 +0000494 continue;
495
Andy Green7627af52011-03-09 15:13:52 +0000496 if (host1->h_addrtype == AF_INET)
497 sprintf(ip, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
Peter Hinzbb45a902011-03-10 18:14:01 +0000498#ifdef AF_LOCAL
Andy Green7627af52011-03-09 15:13:52 +0000499 else {
500 un = (struct sockaddr_un *)p;
Andy Green6ee372f2012-04-09 15:09:01 +0800501 strncpy(ip, un->sun_path, sizeof(ip) - 1);
Andy Green7627af52011-03-09 15:13:52 +0000502 ip[sizeof(ip) - 1] = '\0';
503 }
Peter Hinzbb45a902011-03-10 18:14:01 +0000504#endif
Andy Green07034092011-02-13 08:37:12 +0000505 p = NULL;
506 strncpy(rip, ip, rip_len);
507 rip[rip_len - 1] = '\0';
508 }
509}
Andy Green9f990342011-02-12 11:57:45 +0000510
Peter Hinz56885f32011-03-02 22:03:47 +0000511int libwebsockets_get_random(struct libwebsocket_context *context,
512 void *buf, int len)
513{
514 int n;
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800515 char *p = (char *)buf;
Peter Hinz56885f32011-03-02 22:03:47 +0000516
517#ifdef WIN32
518 for (n = 0; n < len; n++)
519 p[n] = (unsigned char)rand();
520#else
521 n = read(context->fd_random, p, len);
522#endif
523
524 return n;
525}
526
Andy Green2836c642011-03-07 20:47:41 +0000527unsigned char *
528libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md)
529{
530 return SHA1(d, n, md);
531}
532
Andy Greeneeaacb32011-03-01 20:44:24 +0000533void libwebsockets_00_spaceout(char *key, int spaces, int seed)
534{
535 char *p;
Andy Green6ee372f2012-04-09 15:09:01 +0800536
Andy Greeneeaacb32011-03-01 20:44:24 +0000537 key++;
538 while (spaces--) {
539 if (*key && (seed & 1))
540 key++;
541 seed >>= 1;
Andy Green6ee372f2012-04-09 15:09:01 +0800542
Andy Greeneeaacb32011-03-01 20:44:24 +0000543 p = key + strlen(key);
544 while (p >= key) {
545 p[1] = p[0];
546 p--;
547 }
548 *key++ = ' ';
549 }
550}
551
552void libwebsockets_00_spam(char *key, int count, int seed)
553{
554 char *p;
555
556 key++;
557 while (count--) {
Andy Green6ee372f2012-04-09 15:09:01 +0800558
Andy Greeneeaacb32011-03-01 20:44:24 +0000559 if (*key && (seed & 1))
560 key++;
561 seed >>= 1;
562
563 p = key + strlen(key);
564 while (p >= key) {
565 p[1] = p[0];
566 p--;
567 }
568 *key++ = 0x21 + ((seed & 0xffff) % 15);
569 /* 4 would use it up too fast.. not like it matters */
570 seed >>= 1;
571 }
572}
573
Andy Green95a7b5d2011-03-06 10:29:39 +0000574int lws_send_pipe_choked(struct libwebsocket *wsi)
575{
576 struct pollfd fds;
577
578 fds.fd = wsi->sock;
579 fds.events = POLLOUT;
580 fds.revents = 0;
581
582 if (poll(&fds, 1, 0) != 1)
583 return 1;
584
585 if ((fds.revents & POLLOUT) == 0)
586 return 1;
587
588 /* okay to send another packet without blocking */
589
590 return 0;
591}
592
Andy Greena41314f2011-05-23 10:00:03 +0100593int
Andy Green3b84c002011-03-06 13:14:42 +0000594lws_handle_POLLOUT_event(struct libwebsocket_context *context,
595 struct libwebsocket *wsi, struct pollfd *pollfd)
596{
597 struct lws_tokens eff_buf;
598 int n;
599 int ret;
600 int m;
Andy Greena41314f2011-05-23 10:00:03 +0100601 int handled = 0;
Andy Green3b84c002011-03-06 13:14:42 +0000602
Andy Greena41314f2011-05-23 10:00:03 +0100603 for (n = 0; n < wsi->count_active_extensions; n++) {
604 if (!wsi->active_extensions[n]->callback)
605 continue;
606
607 m = wsi->active_extensions[n]->callback(context,
608 wsi->active_extensions[n], wsi,
609 LWS_EXT_CALLBACK_IS_WRITEABLE,
610 wsi->active_extensions_user[n], NULL, 0);
611 if (m > handled)
612 handled = m;
613 }
614
615 if (handled == 1)
616 goto notify_action;
617
618 if (!wsi->extension_data_pending || handled == 2)
Andy Green3b84c002011-03-06 13:14:42 +0000619 goto user_service;
620
621 /*
622 * check in on the active extensions, see if they
623 * had pending stuff to spill... they need to get the
624 * first look-in otherwise sequence will be disordered
625 *
626 * NULL, zero-length eff_buf means just spill pending
627 */
628
629 ret = 1;
630 while (ret == 1) {
631
632 /* default to nobody has more to spill */
633
634 ret = 0;
635 eff_buf.token = NULL;
636 eff_buf.token_len = 0;
637
638 /* give every extension a chance to spill */
639
640 for (n = 0; n < wsi->count_active_extensions; n++) {
641 m = wsi->active_extensions[n]->callback(
Andy Green46c2ea02011-03-22 09:04:01 +0000642 wsi->protocol->owning_server,
643 wsi->active_extensions[n], wsi,
Andy Green3b84c002011-03-06 13:14:42 +0000644 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
645 wsi->active_extensions_user[n], &eff_buf, 0);
646 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +0800647 lwsl_err("ext reports fatal error\n");
Andy Green3b84c002011-03-06 13:14:42 +0000648 return -1;
649 }
650 if (m)
651 /*
652 * at least one extension told us he has more
653 * to spill, so we will go around again after
654 */
655 ret = 1;
656 }
657
658 /* assuming they gave us something to send, send it */
659
660 if (eff_buf.token_len) {
661 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
662 eff_buf.token_len))
663 return -1;
664 } else
665 continue;
666
667 /* no extension has more to spill */
668
669 if (!ret)
670 continue;
671
672 /*
673 * There's more to spill from an extension, but we just sent
674 * something... did that leave the pipe choked?
675 */
676
677 if (!lws_send_pipe_choked(wsi))
678 /* no we could add more */
679 continue;
680
Andy Green43db0452013-01-10 19:50:35 +0800681 lwsl_info("choked in POLLOUT service\n");
Andy Green3b84c002011-03-06 13:14:42 +0000682
683 /*
684 * Yes, he's choked. Leave the POLLOUT masked on so we will
685 * come back here when he is unchoked. Don't call the user
686 * callback to enforce ordering of spilling, he'll get called
687 * when we come back here and there's nothing more to spill.
688 */
689
690 return 0;
691 }
692
693 wsi->extension_data_pending = 0;
694
695user_service:
696 /* one shot */
697
Andy Greena41314f2011-05-23 10:00:03 +0100698 if (pollfd) {
699 pollfd->events &= ~POLLOUT;
Andy Green3b84c002011-03-06 13:14:42 +0000700
Andy Greena41314f2011-05-23 10:00:03 +0100701 /* external POLL support via protocol 0 */
702 context->protocols[0].callback(context, wsi,
703 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
704 (void *)(long)wsi->sock, NULL, POLLOUT);
705 }
706
707notify_action:
Andy Green3b84c002011-03-06 13:14:42 +0000708
Andy Green9e4c2b62011-03-07 20:47:39 +0000709 if (wsi->mode == LWS_CONNMODE_WS_CLIENT)
710 n = LWS_CALLBACK_CLIENT_WRITEABLE;
711 else
712 n = LWS_CALLBACK_SERVER_WRITEABLE;
713
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800714 wsi->protocol->callback(context, wsi, (enum libwebsocket_callback_reasons) n, wsi->user_space, NULL, 0);
Andy Green3b84c002011-03-06 13:14:42 +0000715
716 return 0;
717}
718
719
720
Andy Greena41314f2011-05-23 10:00:03 +0100721void
722libwebsocket_service_timeout_check(struct libwebsocket_context *context,
723 struct libwebsocket *wsi, unsigned int sec)
724{
725 int n;
726
727 /*
728 * if extensions want in on it (eg, we are a mux parent)
729 * give them a chance to service child timeouts
730 */
731
732 for (n = 0; n < wsi->count_active_extensions; n++)
733 wsi->active_extensions[n]->callback(
734 context, wsi->active_extensions[n],
735 wsi, LWS_EXT_CALLBACK_1HZ,
736 wsi->active_extensions_user[n], NULL, sec);
737
738 if (!wsi->pending_timeout)
739 return;
Andy Green6ee372f2012-04-09 15:09:01 +0800740
Andy Greena41314f2011-05-23 10:00:03 +0100741 /*
742 * if we went beyond the allowed time, kill the
743 * connection
744 */
745
746 if (sec > wsi->pending_timeout_limit) {
Andy Green43db0452013-01-10 19:50:35 +0800747 lwsl_info("TIMEDOUT WAITING\n");
Andy Greena41314f2011-05-23 10:00:03 +0100748 libwebsocket_close_and_free_session(context,
749 wsi, LWS_CLOSE_STATUS_NOSTATUS);
750 }
751}
752
753struct libwebsocket *
754libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
755{
756 struct libwebsocket *new_wsi;
757 int n;
758
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800759 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Greena41314f2011-05-23 10:00:03 +0100760 if (new_wsi == NULL) {
Andy Green43db0452013-01-10 19:50:35 +0800761 lwsl_err("Out of memory for new connection\n");
Andy Greena41314f2011-05-23 10:00:03 +0100762 return NULL;
763 }
764
Andy Green6ee372f2012-04-09 15:09:01 +0800765 memset(new_wsi, 0, sizeof(struct libwebsocket));
Andy Greena41314f2011-05-23 10:00:03 +0100766 new_wsi->count_active_extensions = 0;
767 new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
768
769 /* intialize the instance struct */
770
771 new_wsi->state = WSI_STATE_HTTP;
772 new_wsi->name_buffer_pos = 0;
773 new_wsi->mode = LWS_CONNMODE_WS_SERVING;
774
775 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
776 new_wsi->utf8_token[n].token = NULL;
777 new_wsi->utf8_token[n].token_len = 0;
778 }
779
780 /*
781 * these can only be set once the protocol is known
782 * we set an unestablished connection's protocol pointer
783 * to the start of the supported list, so it can look
784 * for matching ones during the handshake
785 */
786 new_wsi->protocol = context->protocols;
787 new_wsi->user_space = NULL;
788
789 /*
790 * Default protocol is 76 / 00
791 * After 76, there's a header specified to inform which
792 * draft the client wants, when that's seen we modify
793 * the individual connection's spec revision accordingly
794 */
795 new_wsi->ietf_spec_revision = 0;
796
797 return new_wsi;
798}
799
800char *
801libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
802 struct libwebsocket *wsi, char *pkt)
803{
804 char hash[20];
805 char *p = pkt;
806 int n;
807 struct libwebsocket_extension *ext;
Andy Green09226502011-05-28 10:19:19 +0100808 struct libwebsocket_extension *ext1;
Andy Greena41314f2011-05-23 10:00:03 +0100809 int ext_count = 0;
Andy Green6ee372f2012-04-09 15:09:01 +0800810 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
811 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena41314f2011-05-23 10:00:03 +0100812 static const char magic_websocket_guid[] =
813 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
814
815 /*
816 * create the random key
817 */
818
819 n = libwebsockets_get_random(context, hash, 16);
820 if (n != 16) {
Andy Green43db0452013-01-10 19:50:35 +0800821 lwsl_err("Unable to read from random dev %s\n",
Andy Greena41314f2011-05-23 10:00:03 +0100822 SYSTEM_RANDOM_FILEPATH);
823 free(wsi->c_path);
824 free(wsi->c_host);
825 if (wsi->c_origin)
826 free(wsi->c_origin);
827 if (wsi->c_protocol)
828 free(wsi->c_protocol);
829 libwebsocket_close_and_free_session(context, wsi,
830 LWS_CLOSE_STATUS_NOSTATUS);
831 return NULL;
832 }
833
834 lws_b64_encode_string(hash, 16, wsi->key_b64,
835 sizeof wsi->key_b64);
836
837 /*
838 * 00 example client handshake
839 *
840 * GET /socket.io/websocket HTTP/1.1
841 * Upgrade: WebSocket
842 * Connection: Upgrade
843 * Host: 127.0.0.1:9999
844 * Origin: http://127.0.0.1
845 * Sec-WebSocket-Key1: 1 0 2#0W 9 89 7 92 ^
846 * Sec-WebSocket-Key2: 7 7Y 4328 B2v[8(z1
847 * Cookie: socketio=websocket
848 *
849 * (Á®Ä0¶†≥
850 *
851 * 04 example client handshake
852 *
853 * GET /chat HTTP/1.1
854 * Host: server.example.com
855 * Upgrade: websocket
856 * Connection: Upgrade
857 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
858 * Sec-WebSocket-Origin: http://example.com
859 * Sec-WebSocket-Protocol: chat, superchat
860 * Sec-WebSocket-Version: 4
861 */
862
863 p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a", wsi->c_path);
864
David Galeano4fbc40c2013-01-10 10:26:05 +0800865 p += sprintf(p, "Pragma: no-cache\x0d\x0a"
866 "Cache-Control: no-cache\x0d\x0a");
867
Andy Greena41314f2011-05-23 10:00:03 +0100868 if (wsi->ietf_spec_revision == 0) {
869 unsigned char spaces_1, spaces_2;
870 unsigned int max_1, max_2;
871 unsigned int num_1, num_2;
872 unsigned long product_1, product_2;
873 char key_1[40];
874 char key_2[40];
875 unsigned int seed;
876 unsigned int count;
877 char challenge[16];
878
Andy Green6ee372f2012-04-09 15:09:01 +0800879 libwebsockets_get_random(context, &spaces_1, sizeof(char));
880 libwebsockets_get_random(context, &spaces_2, sizeof(char));
Andy Greena41314f2011-05-23 10:00:03 +0100881
882 spaces_1 = (spaces_1 % 12) + 1;
883 spaces_2 = (spaces_2 % 12) + 1;
884
885 max_1 = 4294967295 / spaces_1;
886 max_2 = 4294967295 / spaces_2;
887
888 libwebsockets_get_random(context, &num_1, sizeof(int));
889 libwebsockets_get_random(context, &num_2, sizeof(int));
890
891 num_1 = (num_1 % max_1);
892 num_2 = (num_2 % max_2);
893
894 challenge[0] = num_1 >> 24;
895 challenge[1] = num_1 >> 16;
896 challenge[2] = num_1 >> 8;
897 challenge[3] = num_1;
898 challenge[4] = num_2 >> 24;
899 challenge[5] = num_2 >> 16;
900 challenge[6] = num_2 >> 8;
901 challenge[7] = num_2;
902
903 product_1 = num_1 * spaces_1;
904 product_2 = num_2 * spaces_2;
905
906 sprintf(key_1, "%lu", product_1);
907 sprintf(key_2, "%lu", product_2);
908
909 libwebsockets_get_random(context, &seed, sizeof(int));
910 libwebsockets_get_random(context, &count, sizeof(int));
911
912 libwebsockets_00_spam(key_1, (count % 12) + 1, seed);
913
914 libwebsockets_get_random(context, &seed, sizeof(int));
915 libwebsockets_get_random(context, &count, sizeof(int));
916
917 libwebsockets_00_spam(key_2, (count % 12) + 1, seed);
918
919 libwebsockets_get_random(context, &seed, sizeof(int));
920
921 libwebsockets_00_spaceout(key_1, spaces_1, seed);
922 libwebsockets_00_spaceout(key_2, spaces_2, seed >> 16);
923
924 p += sprintf(p, "Upgrade: WebSocket\x0d\x0a"
925 "Connection: Upgrade\x0d\x0aHost: %s\x0d\x0a",
926 wsi->c_host);
927 if (wsi->c_origin)
Andy Green6ee372f2012-04-09 15:09:01 +0800928 p += sprintf(p, "Origin: %s\x0d\x0a", wsi->c_origin);
Andy Greena41314f2011-05-23 10:00:03 +0100929
930 if (wsi->c_protocol)
931 p += sprintf(p, "Sec-WebSocket-Protocol: %s"
932 "\x0d\x0a", wsi->c_protocol);
933
Andy Green6ee372f2012-04-09 15:09:01 +0800934 p += sprintf(p, "Sec-WebSocket-Key1: %s\x0d\x0a", key_1);
935 p += sprintf(p, "Sec-WebSocket-Key2: %s\x0d\x0a", key_2);
Andy Greena41314f2011-05-23 10:00:03 +0100936
937 /* give userland a chance to append, eg, cookies */
938
939 context->protocols[0].callback(context, wsi,
940 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
941 NULL, &p, (pkt + sizeof(pkt)) - p - 12);
942
943 p += sprintf(p, "\x0d\x0a");
944
945 if (libwebsockets_get_random(context, p, 8) != 8)
946 return NULL;
947 memcpy(&challenge[8], p, 8);
948 p += 8;
949
950 /* precompute what we want to see from the server */
951
952 MD5((unsigned char *)challenge, 16,
953 (unsigned char *)wsi->initial_handshake_hash_base64);
954
955 goto issue_hdr;
956 }
957
958 p += sprintf(p, "Host: %s\x0d\x0a", wsi->c_host);
David Galeano4fbc40c2013-01-10 10:26:05 +0800959 p += sprintf(p, "Upgrade: websocket\x0d\x0a"
960 "Connection: Upgrade\x0d\x0a"
961 "Sec-WebSocket-Key: ");
Andy Greena41314f2011-05-23 10:00:03 +0100962 strcpy(p, wsi->key_b64);
963 p += strlen(wsi->key_b64);
964 p += sprintf(p, "\x0d\x0a");
David Galeanoaa0bc862013-01-09 15:31:46 +0800965 if (wsi->c_origin) {
966 if (wsi->ietf_spec_revision == 13) {
967 p += sprintf(p, "Origin: %s\x0d\x0a",
968 wsi->c_origin);
969 }
970 else {
David Galeanocb193682013-01-09 15:29:00 +0800971 p += sprintf(p, "Sec-WebSocket-Origin: %s\x0d\x0a",
Andy Greena41314f2011-05-23 10:00:03 +0100972 wsi->c_origin);
David Galeanoaa0bc862013-01-09 15:31:46 +0800973 }
974 }
Andy Greena41314f2011-05-23 10:00:03 +0100975 if (wsi->c_protocol)
976 p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
977 wsi->c_protocol);
978
979 /* tell the server what extensions we could support */
980
981 p += sprintf(p, "Sec-WebSocket-Extensions: ");
982
Andy Green6ee372f2012-04-09 15:09:01 +0800983 ext = context->extensions;
Andy Greena41314f2011-05-23 10:00:03 +0100984 while (ext && ext->callback) {
985
986 n = 0;
Andy Green09226502011-05-28 10:19:19 +0100987 ext1 = context->extensions;
Andy Green09226502011-05-28 10:19:19 +0100988
Andy Green6ee372f2012-04-09 15:09:01 +0800989 while (ext1 && ext1->callback) {
Andy Green09226502011-05-28 10:19:19 +0100990 n |= ext1->callback(context, ext1, wsi,
991 LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
992 NULL, (char *)ext->name, 0);
993
994 ext1++;
995 }
996
Andy Green6ee372f2012-04-09 15:09:01 +0800997 if (n) { /* an extension vetos us */
Andy Green43db0452013-01-10 19:50:35 +0800998 lwsl_ext("ext %s vetoed\n", (char *)ext->name);
Andy Green09226502011-05-28 10:19:19 +0100999 ext++;
1000 continue;
1001 }
1002
Andy Greena41314f2011-05-23 10:00:03 +01001003 n = context->protocols[0].callback(context, wsi,
1004 LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
1005 wsi->user_space, (char *)ext->name, 0);
1006
1007 /*
1008 * zero return from callback means
1009 * go ahead and allow the extension,
1010 * it's what we get if the callback is
1011 * unhandled
1012 */
1013
1014 if (n) {
1015 ext++;
1016 continue;
1017 }
1018
1019 /* apply it */
1020
1021 if (ext_count)
1022 *p++ = ',';
1023 p += sprintf(p, "%s", ext->name);
1024 ext_count++;
1025
1026 ext++;
1027 }
1028
1029 p += sprintf(p, "\x0d\x0a");
1030
1031 if (wsi->ietf_spec_revision)
1032 p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
1033 wsi->ietf_spec_revision);
1034
1035 /* give userland a chance to append, eg, cookies */
1036
1037 context->protocols[0].callback(context, wsi,
1038 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
1039 NULL, &p, (pkt + sizeof(pkt)) - p - 12);
1040
1041 p += sprintf(p, "\x0d\x0a");
1042
1043 /* prepare the expected server accept response */
1044
1045 strcpy((char *)buf, wsi->key_b64);
1046 strcpy((char *)&buf[strlen((char *)buf)], magic_websocket_guid);
1047
1048 SHA1(buf, strlen((char *)buf), (unsigned char *)hash);
1049
1050 lws_b64_encode_string(hash, 20,
1051 wsi->initial_handshake_hash_base64,
1052 sizeof wsi->initial_handshake_hash_base64);
1053
1054issue_hdr:
1055
Andy Green6ee372f2012-04-09 15:09:01 +08001056#if 0
1057 puts(pkt);
1058#endif
Andy Green09226502011-05-28 10:19:19 +01001059
Andy Greena41314f2011-05-23 10:00:03 +01001060 /* done with these now */
1061
1062 free(wsi->c_path);
1063 free(wsi->c_host);
1064 if (wsi->c_origin)
1065 free(wsi->c_origin);
1066
1067 return p;
1068}
1069
1070int
1071lws_client_interpret_server_handshake(struct libwebsocket_context *context,
1072 struct libwebsocket *wsi)
1073{
Andy Green6ee372f2012-04-09 15:09:01 +08001074 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
1075 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena41314f2011-05-23 10:00:03 +01001076 char pkt[1024];
1077 char *p = &pkt[0];
1078 const char *pc;
1079 const char *c;
1080 int more = 1;
1081 int okay = 0;
1082 char ext_name[128];
1083 struct libwebsocket_extension *ext;
1084 void *v;
Andy Greenc15cb382011-06-26 10:27:28 +01001085 int len = 0;
Andy Greena41314f2011-05-23 10:00:03 +01001086 int n;
1087 static const char magic_websocket_04_masking_guid[] =
1088 "61AC5F19-FBBA-4540-B96F-6561F1AB40A8";
1089
1090 /*
1091 * 00 / 76 -->
1092 *
1093 * HTTP/1.1 101 WebSocket Protocol Handshake
1094 * Upgrade: WebSocket
1095 * Connection: Upgrade
1096 * Sec-WebSocket-Origin: http://127.0.0.1
1097 * Sec-WebSocket-Location: ws://127.0.0.1:9999/socket.io/websocket
1098 *
1099 * xxxxxxxxxxxxxxxx
1100 */
1101
1102 if (wsi->ietf_spec_revision == 0) {
1103 if (!wsi->utf8_token[WSI_TOKEN_HTTP].token_len ||
1104 !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
1105 !wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len ||
1106 !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len ||
1107 (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len &&
1108 wsi->c_protocol != NULL)) {
Andy Green43db0452013-01-10 19:50:35 +08001109 lwsl_parser("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001110 "missing required header(s)\n");
1111 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001112 lwsl_parser("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001113 goto bail3;
1114 }
1115
1116 strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token);
Andy Green6ee372f2012-04-09 15:09:01 +08001117 if (strncmp(wsi->utf8_token[WSI_TOKEN_HTTP].token, "101", 3)) {
Andy Green43db0452013-01-10 19:50:35 +08001118 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001119 "server sent bad HTTP response '%s'\n",
1120 wsi->utf8_token[WSI_TOKEN_HTTP].token);
1121 goto bail3;
1122 }
1123
Andy Green6ee372f2012-04-09 15:09:01 +08001124 if (wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len < 16) {
Andy Green43db0452013-01-10 19:50:35 +08001125 lwsl_parser("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001126 "challenge reply too short %d\n",
1127 wsi->utf8_token[
1128 WSI_TOKEN_CHALLENGE].token_len);
1129 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001130 lwsl_parser("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001131 goto bail3;
1132
1133 }
1134
1135 goto select_protocol;
1136 }
1137
1138 /*
1139 * well, what the server sent looked reasonable for syntax.
1140 * Now let's confirm it sent all the necessary headers
1141 */
1142#if 0
Andy Green43db0452013-01-10 19:50:35 +08001143 lwsl_parser("WSI_TOKEN_HTTP: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001144 wsi->utf8_token[WSI_TOKEN_HTTP].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001145 lwsl_parser("WSI_TOKEN_UPGRADE: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001146 wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001147 lwsl_parser("WSI_TOKEN_CONNECTION: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001148 wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001149 lwsl_parser("WSI_TOKEN_ACCEPT: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001150 wsi->utf8_token[WSI_TOKEN_ACCEPT].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001151 lwsl_parser("WSI_TOKEN_NONCE: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001152 wsi->utf8_token[WSI_TOKEN_NONCE].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001153 lwsl_parser("WSI_TOKEN_PROTOCOL: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001154 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len);
Andy Greena41314f2011-05-23 10:00:03 +01001155#endif
Andy Green6ee372f2012-04-09 15:09:01 +08001156 if (!wsi->utf8_token[WSI_TOKEN_HTTP].token_len ||
1157 !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
1158 !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len ||
1159 !wsi->utf8_token[WSI_TOKEN_ACCEPT].token_len ||
1160 (!wsi->utf8_token[WSI_TOKEN_NONCE].token_len &&
Andy Greena41314f2011-05-23 10:00:03 +01001161 wsi->ietf_spec_revision == 4) ||
Andy Green6ee372f2012-04-09 15:09:01 +08001162 (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len &&
1163 wsi->c_protocol != NULL)) {
Andy Green43db0452013-01-10 19:50:35 +08001164 lwsl_parser("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001165 "missing required header(s)\n");
1166 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001167 lwsl_parser("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001168 goto bail3;
1169 }
1170
1171 /*
1172 * Everything seems to be there, now take a closer look at what
1173 * is in each header
1174 */
1175
1176 strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token);
Artem Egorkined515ddd2011-11-23 10:46:24 +02001177 if (strncmp(wsi->utf8_token[WSI_TOKEN_HTTP].token, "101", 3)) {
Andy Green43db0452013-01-10 19:50:35 +08001178 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001179 "server sent bad HTTP response '%s'\n",
1180 wsi->utf8_token[WSI_TOKEN_HTTP].token);
1181 goto bail3;
1182 }
1183
1184 strtolower(wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
1185 if (strcmp(wsi->utf8_token[WSI_TOKEN_UPGRADE].token,
1186 "websocket")) {
Andy Green43db0452013-01-10 19:50:35 +08001187 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001188 "sent bad Upgrade header '%s'\n",
1189 wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
1190 goto bail3;
1191 }
1192
1193 strtolower(wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
1194 if (strcmp(wsi->utf8_token[WSI_TOKEN_CONNECTION].token,
1195 "upgrade")) {
Andy Green43db0452013-01-10 19:50:35 +08001196 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001197 "sent bad Connection hdr '%s'\n",
1198 wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
1199 goto bail3;
1200 }
1201
1202select_protocol:
1203 pc = wsi->c_protocol;
1204 if (pc == NULL)
Andy Green43db0452013-01-10 19:50:35 +08001205 lwsl_parser("lws_client_interpret_server_handshake: "
Andy Green6ee372f2012-04-09 15:09:01 +08001206 "NULL c_protocol\n");
Andy Greena41314f2011-05-23 10:00:03 +01001207 else
Andy Green43db0452013-01-10 19:50:35 +08001208 lwsl_parser("lws_client_interpret_server_handshake: "
Andy Green6ee372f2012-04-09 15:09:01 +08001209 "cPprotocol='%s'\n", pc);
Andy Greena41314f2011-05-23 10:00:03 +01001210
1211 /*
1212 * confirm the protocol the server wants to talk was in the list
1213 * of protocols we offered
1214 */
1215
1216 if (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len) {
1217
Andy Green43db0452013-01-10 19:50:35 +08001218 lwsl_warn("lws_client_interpret_server_handshake "
Andy Green6ee372f2012-04-09 15:09:01 +08001219 "WSI_TOKEN_PROTOCOL is null\n");
Andy Greena41314f2011-05-23 10:00:03 +01001220 /*
1221 * no protocol name to work from,
1222 * default to first protocol
1223 */
1224 wsi->protocol = &context->protocols[0];
David Brooks2c60d952012-04-20 12:19:01 +08001225 wsi->c_callback = wsi->protocol->callback;
Andy Greena41314f2011-05-23 10:00:03 +01001226 free(wsi->c_protocol);
1227
David Galeano4c38f142013-01-09 19:49:50 +08001228 goto check_extensions;
Andy Greena41314f2011-05-23 10:00:03 +01001229 }
1230
1231 while (*pc && !okay) {
Andy Green6ee372f2012-04-09 15:09:01 +08001232 if ((!strncmp(pc, wsi->utf8_token[WSI_TOKEN_PROTOCOL].token,
1233 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len)) &&
1234 (pc[wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len] == ',' ||
1235 pc[wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len] == '\0')) {
Andy Greena41314f2011-05-23 10:00:03 +01001236 okay = 1;
1237 continue;
1238 }
1239 while (*pc && *pc != ',')
1240 pc++;
1241 while (*pc && *pc != ' ')
1242 pc++;
1243 }
1244
1245 /* done with him now */
1246
1247 if (wsi->c_protocol)
1248 free(wsi->c_protocol);
1249
Andy Greena41314f2011-05-23 10:00:03 +01001250 if (!okay) {
Andy Green43db0452013-01-10 19:50:35 +08001251 lwsl_err("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001252 "sent bad protocol '%s'\n",
1253 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
1254 goto bail2;
1255 }
1256
1257 /*
1258 * identify the selected protocol struct and set it
1259 */
1260 n = 0;
1261 wsi->protocol = NULL;
David Brooks2c60d952012-04-20 12:19:01 +08001262 while (context->protocols[n].callback && !wsi->protocol) { /* Stop after finding first one?? */
Andy Greena41314f2011-05-23 10:00:03 +01001263 if (strcmp(wsi->utf8_token[WSI_TOKEN_PROTOCOL].token,
David Brooks2c60d952012-04-20 12:19:01 +08001264 context->protocols[n].name) == 0) {
Andy Greena41314f2011-05-23 10:00:03 +01001265 wsi->protocol = &context->protocols[n];
David Brooks2c60d952012-04-20 12:19:01 +08001266 wsi->c_callback = wsi->protocol->callback;
1267 }
Andy Greena41314f2011-05-23 10:00:03 +01001268 n++;
1269 }
1270
1271 if (wsi->protocol == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08001272 lwsl_err("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001273 "requested protocol '%s', which we "
1274 "said we supported but we don't!\n",
1275 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
1276 goto bail2;
1277 }
1278
1279
David Galeano4c38f142013-01-09 19:49:50 +08001280check_extensions:
1281
Andy Greena41314f2011-05-23 10:00:03 +01001282 /* instantiate the accepted extensions */
1283
1284 if (!wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token_len) {
Andy Green43db0452013-01-10 19:50:35 +08001285 lwsl_ext("no client extenstions allowed by server\n");
Andy Greena41314f2011-05-23 10:00:03 +01001286 goto check_accept;
1287 }
1288
1289 /*
1290 * break down the list of server accepted extensions
1291 * and go through matching them or identifying bogons
1292 */
1293
1294 c = wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token;
1295 n = 0;
1296 while (more) {
1297
1298 if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
1299 ext_name[n] = *c++;
1300 if (n < sizeof(ext_name) - 1)
1301 n++;
1302 continue;
1303 }
1304 ext_name[n] = '\0';
1305 if (!*c)
1306 more = 0;
1307 else {
1308 c++;
1309 if (!n)
1310 continue;
1311 }
1312
1313 /* check we actually support it */
1314
Andy Green43db0452013-01-10 19:50:35 +08001315 lwsl_ext("checking client ext %s\n", ext_name);
Andy Greena41314f2011-05-23 10:00:03 +01001316
1317 n = 0;
1318 ext = wsi->protocol->owning_server->extensions;
1319 while (ext && ext->callback) {
1320
1321 if (strcmp(ext_name, ext->name)) {
1322 ext++;
1323 continue;
1324 }
1325
1326 n = 1;
1327
Andy Green43db0452013-01-10 19:50:35 +08001328 lwsl_ext("instantiating client ext %s\n", ext_name);
Andy Greena41314f2011-05-23 10:00:03 +01001329
1330 /* instantiate the extension on this conn */
1331
1332 wsi->active_extensions_user[
1333 wsi->count_active_extensions] =
1334 malloc(ext->per_session_data_size);
Andy Green41c58032013-01-12 13:21:08 +08001335 if (wsi->active_extensions_user[
1336 wsi->count_active_extensions] == NULL) {
1337 lwsl_err("Out of mem\n");
1338 goto bail2;
1339 }
Andy Greenf6652412011-05-25 20:46:18 +01001340 memset(wsi->active_extensions_user[
1341 wsi->count_active_extensions], 0,
1342 ext->per_session_data_size);
Andy Greena41314f2011-05-23 10:00:03 +01001343 wsi->active_extensions[
1344 wsi->count_active_extensions] = ext;
1345
1346 /* allow him to construct his context */
1347
1348 ext->callback(wsi->protocol->owning_server,
1349 ext, wsi,
1350 LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
1351 wsi->active_extensions_user[
1352 wsi->count_active_extensions],
1353 NULL, 0);
1354
1355 wsi->count_active_extensions++;
1356
1357 ext++;
1358 }
1359
1360 if (n == 0) {
Andy Green43db0452013-01-10 19:50:35 +08001361 lwsl_warn("Server said we should use"
Andy Greena41314f2011-05-23 10:00:03 +01001362 "an unknown extension '%s'!\n", ext_name);
1363 goto bail2;
1364 }
1365
1366 n = 0;
1367 }
1368
1369
1370check_accept:
1371
1372 if (wsi->ietf_spec_revision == 0) {
1373
1374 if (memcmp(wsi->initial_handshake_hash_base64,
1375 wsi->utf8_token[WSI_TOKEN_CHALLENGE].token, 16)) {
Andy Green43db0452013-01-10 19:50:35 +08001376 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001377 "failed 00 challenge compare\n");
1378 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001379 lwsl_warn("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001380 goto bail2;
1381 }
1382
1383 goto accept_ok;
1384 }
1385
1386 /*
1387 * Confirm his accept token is the one we precomputed
1388 */
1389
1390 if (strcmp(wsi->utf8_token[WSI_TOKEN_ACCEPT].token,
1391 wsi->initial_handshake_hash_base64)) {
Andy Green43db0452013-01-10 19:50:35 +08001392 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001393 "sent bad ACCEPT '%s' vs computed '%s'\n",
1394 wsi->utf8_token[WSI_TOKEN_ACCEPT].token,
1395 wsi->initial_handshake_hash_base64);
1396 goto bail2;
1397 }
1398
1399 if (wsi->ietf_spec_revision == 4) {
1400 /*
1401 * Calculate the 04 masking key to use when
1402 * sending data to server
1403 */
1404
1405 strcpy((char *)buf, wsi->key_b64);
1406 p = (char *)buf + strlen(wsi->key_b64);
1407 strcpy(p, wsi->utf8_token[WSI_TOKEN_NONCE].token);
1408 p += wsi->utf8_token[WSI_TOKEN_NONCE].token_len;
1409 strcpy(p, magic_websocket_04_masking_guid);
1410 SHA1(buf, strlen((char *)buf), wsi->masking_key_04);
1411 }
Andy Green6ee372f2012-04-09 15:09:01 +08001412accept_ok:
Andy Greena41314f2011-05-23 10:00:03 +01001413
1414 /* allocate the per-connection user memory (if any) */
Andy Green6ee372f2012-04-09 15:09:01 +08001415 if (wsi->protocol->per_session_data_size &&
1416 !libwebsocket_ensure_user_space(wsi))
1417 goto bail2;
Andy Greena41314f2011-05-23 10:00:03 +01001418
1419 /* clear his proxy connection timeout */
1420
1421 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1422
1423 /* mark him as being alive */
1424
1425 wsi->state = WSI_STATE_ESTABLISHED;
1426 wsi->mode = LWS_CONNMODE_WS_CLIENT;
1427
Andy Green43db0452013-01-10 19:50:35 +08001428 lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
Andy Greena41314f2011-05-23 10:00:03 +01001429
1430 /* call him back to inform him he is up */
1431
1432 wsi->protocol->callback(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08001433 LWS_CALLBACK_CLIENT_ESTABLISHED,
1434 wsi->user_space, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01001435
1436 /*
1437 * inform all extensions, not just active ones since they
1438 * already know
1439 */
1440
1441 ext = context->extensions;
1442
1443 while (ext && ext->callback) {
1444 v = NULL;
1445 for (n = 0; n < wsi->count_active_extensions; n++)
1446 if (wsi->active_extensions[n] == ext)
1447 v = wsi->active_extensions_user[n];
1448
1449 ext->callback(context, ext, wsi,
1450 LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED, v, NULL, 0);
1451 ext++;
1452 }
1453
1454 return 0;
1455
1456bail3:
1457 if (wsi->c_protocol)
1458 free(wsi->c_protocol);
1459
1460bail2:
David Brooks80a44972012-04-20 12:18:47 +08001461 if (wsi->c_callback) wsi->c_callback(context, wsi,
1462 LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
1463 wsi->user_space,
1464 NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01001465 libwebsocket_close_and_free_session(context, wsi,
David Brooks80a44972012-04-20 12:18:47 +08001466 LWS_CLOSE_STATUS_NOSTATUS); // But this should be LWS_CLOSE_STATUS_PROTOCOL_ERR
1467
Andy Greena41314f2011-05-23 10:00:03 +01001468 return 1;
1469}
1470
1471
1472
Andy Green9f990342011-02-12 11:57:45 +00001473/**
1474 * libwebsocket_service_fd() - Service polled socket with something waiting
Peter Hinz56885f32011-03-02 22:03:47 +00001475 * @context: Websocket context
Andy Green9f990342011-02-12 11:57:45 +00001476 * @pollfd: The pollfd entry describing the socket fd and which events
Andy Green6ee372f2012-04-09 15:09:01 +08001477 * happened.
Andy Green9f990342011-02-12 11:57:45 +00001478 *
1479 * This function closes any active connections and then frees the
1480 * context. After calling this, any further use of the context is
1481 * undefined.
1482 */
1483
1484int
Peter Hinz56885f32011-03-02 22:03:47 +00001485libwebsocket_service_fd(struct libwebsocket_context *context,
Andy Green0d338332011-02-12 11:57:43 +00001486 struct pollfd *pollfd)
Andy Greenb45993c2010-12-18 15:13:50 +00001487{
Andy Green6ee372f2012-04-09 15:09:01 +08001488 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
1489 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena71eafc2011-02-14 17:59:43 +00001490 struct libwebsocket *wsi;
Andy Green0d338332011-02-12 11:57:43 +00001491 struct libwebsocket *new_wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00001492 int n;
Andy Green0d338332011-02-12 11:57:43 +00001493 int m;
Tobias Maiere8c9b562012-04-05 11:57:12 +02001494 ssize_t len;
Andy Green0d338332011-02-12 11:57:43 +00001495 int accept_fd;
1496 unsigned int clilen;
1497 struct sockaddr_in cli_addr;
Andy Greena71eafc2011-02-14 17:59:43 +00001498 struct timeval tv;
Andy Greenbe93fef2011-02-14 20:25:43 +00001499 char pkt[1024];
1500 char *p = &pkt[0];
Andy Green2366b1c2011-03-06 13:15:31 +00001501 int more = 1;
Andy Green98a717c2011-03-06 13:14:15 +00001502 struct lws_tokens eff_buf;
Andy Green6c939552011-03-08 08:56:57 +00001503 int opt = 1;
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001504 char c;
Andy Greenc6517fa2011-03-06 13:15:29 +00001505
Andy Greenbe93fef2011-02-14 20:25:43 +00001506#ifdef LWS_OPENSSL_SUPPORT
1507 char ssl_err_buf[512];
1508#endif
Andy Greena71eafc2011-02-14 17:59:43 +00001509 /*
1510 * you can call us with pollfd = NULL to just allow the once-per-second
1511 * global timeout checks; if less than a second since the last check
1512 * it returns immediately then.
1513 */
1514
1515 gettimeofday(&tv, NULL);
1516
Peter Hinz56885f32011-03-02 22:03:47 +00001517 if (context->last_timeout_check_s != tv.tv_sec) {
1518 context->last_timeout_check_s = tv.tv_sec;
Andy Greena71eafc2011-02-14 17:59:43 +00001519
1520 /* global timeout check once per second */
1521
Peter Hinz56885f32011-03-02 22:03:47 +00001522 for (n = 0; n < context->fds_count; n++) {
1523 wsi = wsi_from_fd(context, context->fds[n].fd);
Andy Greena71eafc2011-02-14 17:59:43 +00001524
Andy Greena41314f2011-05-23 10:00:03 +01001525 libwebsocket_service_timeout_check(context, wsi,
1526 tv.tv_sec);
Andy Greena71eafc2011-02-14 17:59:43 +00001527 }
1528 }
1529
1530 /* just here for timeout management? */
1531
1532 if (pollfd == NULL)
1533 return 0;
1534
1535 /* no, here to service a socket descriptor */
1536
Peter Hinz56885f32011-03-02 22:03:47 +00001537 wsi = wsi_from_fd(context, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001538
Andy Green0d338332011-02-12 11:57:43 +00001539 if (wsi == NULL)
Andy Greenfa3f4052012-10-07 20:40:35 +08001540 return 0;
Andy Green8f037e42010-12-19 22:13:26 +00001541
Andy Green0d338332011-02-12 11:57:43 +00001542 switch (wsi->mode) {
1543 case LWS_CONNMODE_SERVER_LISTENER:
1544
1545 /* pollin means a client has connected to us then */
1546
David Galeanob88e0962013-01-10 09:54:10 +08001547 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001548 break;
1549
David Galeanof7009352011-09-26 12:09:54 +01001550 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001551 lwsl_warn("too busy to accept new client\n");
David Galeanof7009352011-09-26 12:09:54 +01001552 break;
1553 }
1554
Andy Green0d338332011-02-12 11:57:43 +00001555 /* listen socket got an unencrypted connection... */
1556
1557 clilen = sizeof(cli_addr);
1558 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1559 &clilen);
1560 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001561 lwsl_warn("ERROR on accept: %d\n", strerror(errno));
Andy Green3928f612012-07-20 12:58:38 +08001562 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001563 }
1564
Andy Green6c939552011-03-08 08:56:57 +00001565 /* Disable Nagle */
1566 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08001567 setsockopt(accept_fd, IPPROTO_TCP, TCP_NODELAY,
1568 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00001569
Andy Green07034092011-02-13 08:37:12 +00001570 /*
1571 * look at who we connected to and give user code a chance
1572 * to reject based on client IP. There's no protocol selected
1573 * yet so we issue this to protocols[0]
1574 */
1575
Peter Hinz56885f32011-03-02 22:03:47 +00001576 if ((context->protocols[0].callback)(context, wsi,
Andy Green07034092011-02-13 08:37:12 +00001577 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
Andy Green6ee372f2012-04-09 15:09:01 +08001578 (void *)(long)accept_fd, NULL, 0)) {
Andy Green43db0452013-01-10 19:50:35 +08001579 lwsl_debug("Callback denied network connection\n");
Andy Green3fc2c652013-01-14 15:35:02 +08001580 compatible_close(accept_fd);
Andy Green07034092011-02-13 08:37:12 +00001581 break;
1582 }
1583
Andy Greena41314f2011-05-23 10:00:03 +01001584 new_wsi = libwebsocket_create_new_server_wsi(context);
David Galeanoed3c8402013-01-10 10:45:24 +08001585 if (new_wsi == NULL) {
Andy Green3fc2c652013-01-14 15:35:02 +08001586 compatible_close(accept_fd);
Andy Green0d338332011-02-12 11:57:43 +00001587 break;
David Galeanoed3c8402013-01-10 10:45:24 +08001588 }
Andy Green0d338332011-02-12 11:57:43 +00001589
Andy Green0d338332011-02-12 11:57:43 +00001590 new_wsi->sock = accept_fd;
Andy Greena41314f2011-05-23 10:00:03 +01001591
Andy Green0d338332011-02-12 11:57:43 +00001592
1593#ifdef LWS_OPENSSL_SUPPORT
1594 new_wsi->ssl = NULL;
Andy Green0d338332011-02-12 11:57:43 +00001595
Peter Hinz56885f32011-03-02 22:03:47 +00001596 if (context->use_ssl) {
Andy Green0d338332011-02-12 11:57:43 +00001597
Peter Hinz56885f32011-03-02 22:03:47 +00001598 new_wsi->ssl = SSL_new(context->ssl_ctx);
Andy Green0d338332011-02-12 11:57:43 +00001599 if (new_wsi->ssl == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08001600 lwsl_err("SSL_new failed: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001601 ERR_error_string(SSL_get_error(
1602 new_wsi->ssl, 0), NULL));
Andy Green1f9bf522011-02-14 21:14:37 +00001603 libwebsockets_decode_ssl_error();
Andy Green0d338332011-02-12 11:57:43 +00001604 free(new_wsi);
Andy Green3fc2c652013-01-14 15:35:02 +08001605 compatible_close(accept_fd);
Andy Green0d338332011-02-12 11:57:43 +00001606 break;
1607 }
1608
Larry Hayes455d1fe2013-01-15 01:03:58 +08001609 SSL_set_ex_data(new_wsi->ssl,
1610 openssl_websocket_private_data_index, context);
1611
Andy Green0d338332011-02-12 11:57:43 +00001612 SSL_set_fd(new_wsi->ssl, accept_fd);
1613
1614 n = SSL_accept(new_wsi->ssl);
1615 if (n != 1) {
1616 /*
1617 * browsers seem to probe with various
1618 * ssl params which fail then retry
1619 * and succeed
1620 */
Andy Green43db0452013-01-10 19:50:35 +08001621 lwsl_debug("SSL_accept failed skt %u: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001622 pollfd->fd,
1623 ERR_error_string(SSL_get_error(
1624 new_wsi->ssl, n), NULL));
1625 SSL_free(
1626 new_wsi->ssl);
1627 free(new_wsi);
Andy Green3fc2c652013-01-14 15:35:02 +08001628 compatible_close(accept_fd);
Andy Green0d338332011-02-12 11:57:43 +00001629 break;
1630 }
Andy Green6ee372f2012-04-09 15:09:01 +08001631
Andy Green43db0452013-01-10 19:50:35 +08001632 lwsl_debug("accepted new SSL conn "
Andy Green0d338332011-02-12 11:57:43 +00001633 "port %u on fd=%d SSL ver %s\n",
1634 ntohs(cli_addr.sin_port), accept_fd,
1635 SSL_get_version(new_wsi->ssl));
1636
1637 } else
1638#endif
Andy Green43db0452013-01-10 19:50:35 +08001639 lwsl_debug("accepted new conn port %u on fd=%d\n",
Andy Green0d338332011-02-12 11:57:43 +00001640 ntohs(cli_addr.sin_port), accept_fd);
1641
Peter Hinz56885f32011-03-02 22:03:47 +00001642 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001643
Andy Green0d338332011-02-12 11:57:43 +00001644 /*
1645 * make sure NO events are seen yet on this new socket
1646 * (otherwise we inherit old fds[client].revents from
1647 * previous socket there and die mysteriously! )
1648 */
Peter Hinz56885f32011-03-02 22:03:47 +00001649 context->fds[context->fds_count].revents = 0;
Andy Green0d338332011-02-12 11:57:43 +00001650
Peter Hinz56885f32011-03-02 22:03:47 +00001651 context->fds[context->fds_count].events = POLLIN;
1652 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001653
Andy Green3221f922011-02-12 13:14:11 +00001654 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001655 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001656 LWS_CALLBACK_ADD_POLL_FD,
1657 (void *)(long)accept_fd, NULL, POLLIN);
1658
Andy Green0d338332011-02-12 11:57:43 +00001659 break;
1660
1661 case LWS_CONNMODE_BROADCAST_PROXY_LISTENER:
1662
1663 /* as we are listening, POLLIN means accept() is needed */
Andy Green6ee372f2012-04-09 15:09:01 +08001664
David Galeanob88e0962013-01-10 09:54:10 +08001665 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001666 break;
1667
1668 /* listen socket got an unencrypted connection... */
1669
1670 clilen = sizeof(cli_addr);
1671 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1672 &clilen);
1673 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001674 lwsl_warn("ERROR on accept %d\n", accept_fd);
Andy Green3928f612012-07-20 12:58:38 +08001675 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001676 }
1677
Peter Hinz56885f32011-03-02 22:03:47 +00001678 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001679 lwsl_err("too busy to accept new broadcast "
Andy Green3221f922011-02-12 13:14:11 +00001680 "proxy client\n");
Andy Green41c58032013-01-12 13:21:08 +08001681 goto bail_prox_listener;
Andy Green0d338332011-02-12 11:57:43 +00001682 }
1683
1684 /* create a dummy wsi for the connection and add it */
1685
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001686 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08001687 if (new_wsi == NULL) {
1688 lwsl_err("Out of mem\n");
1689 goto bail_prox_listener;
1690 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001691 memset(new_wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00001692 new_wsi->sock = accept_fd;
1693 new_wsi->mode = LWS_CONNMODE_BROADCAST_PROXY;
1694 new_wsi->state = WSI_STATE_ESTABLISHED;
Andy Greend6e09112011-03-05 16:12:15 +00001695 new_wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00001696 /* note which protocol we are proxying */
1697 new_wsi->protocol_index_for_broadcast_proxy =
1698 wsi->protocol_index_for_broadcast_proxy;
Peter Hinz56885f32011-03-02 22:03:47 +00001699 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001700
1701 /* add connected socket to internal poll array */
1702
Peter Hinz56885f32011-03-02 22:03:47 +00001703 context->fds[context->fds_count].revents = 0;
1704 context->fds[context->fds_count].events = POLLIN;
1705 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001706
Andy Green3221f922011-02-12 13:14:11 +00001707 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001708 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001709 LWS_CALLBACK_ADD_POLL_FD,
1710 (void *)(long)accept_fd, NULL, POLLIN);
1711
Andy Green0d338332011-02-12 11:57:43 +00001712 break;
1713
Andy Green41c58032013-01-12 13:21:08 +08001714bail_prox_listener:
Andy Green3fc2c652013-01-14 15:35:02 +08001715 compatible_close(accept_fd);
Andy Green41c58032013-01-12 13:21:08 +08001716 break;
1717
Andy Green0d338332011-02-12 11:57:43 +00001718 case LWS_CONNMODE_BROADCAST_PROXY:
Andy Green8f037e42010-12-19 22:13:26 +00001719
Andy Greenb45993c2010-12-18 15:13:50 +00001720 /* handle session socket closed */
Andy Green8f037e42010-12-19 22:13:26 +00001721
Andy Green0d338332011-02-12 11:57:43 +00001722 if (pollfd->revents & (POLLERR | POLLHUP)) {
Andy Green8f037e42010-12-19 22:13:26 +00001723
Andy Green43db0452013-01-10 19:50:35 +08001724 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Timothy J Fontaineb86d64e2011-02-14 17:55:27 +00001725 (void *)wsi, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001726
Peter Hinz56885f32011-03-02 22:03:47 +00001727 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001728 LWS_CLOSE_STATUS_NORMAL);
Andy Green4b6fbe12011-02-14 08:03:48 +00001729 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00001730 }
Andy Green8f037e42010-12-19 22:13:26 +00001731
Andy Green3b84c002011-03-06 13:14:42 +00001732 /*
1733 * either extension code with stuff to spill, or the user code,
1734 * requested a callback when it was OK to write
1735 */
Andy Green90c7cbc2011-01-27 06:26:52 +00001736
Andy Green3b84c002011-03-06 13:14:42 +00001737 if (pollfd->revents & POLLOUT)
Andy Green6ee372f2012-04-09 15:09:01 +08001738 if (lws_handle_POLLOUT_event(context, wsi,
1739 pollfd) < 0) {
1740 libwebsocket_close_and_free_session(
1741 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00001742 return 1;
1743 }
Andy Green90c7cbc2011-01-27 06:26:52 +00001744
Andy Greenb45993c2010-12-18 15:13:50 +00001745 /* any incoming data ready? */
1746
Andy Green0d338332011-02-12 11:57:43 +00001747 if (!(pollfd->revents & POLLIN))
1748 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001749
Andy Green0d338332011-02-12 11:57:43 +00001750 /* get the issued broadcast payload from the socket */
Andy Greenb45993c2010-12-18 15:13:50 +00001751
Andy Green0d338332011-02-12 11:57:43 +00001752 len = read(pollfd->fd, buf + LWS_SEND_BUFFER_PRE_PADDING,
1753 MAX_BROADCAST_PAYLOAD);
1754 if (len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001755 lwsl_err("Error reading broadcast payload\n");
Andy Green4b6fbe12011-02-14 08:03:48 +00001756 break;
Andy Green0d338332011-02-12 11:57:43 +00001757 }
Andy Greenb45993c2010-12-18 15:13:50 +00001758
Andy Green0d338332011-02-12 11:57:43 +00001759 /* broadcast it to all guys with this protocol index */
Andy Green8f037e42010-12-19 22:13:26 +00001760
Andy Green0d338332011-02-12 11:57:43 +00001761 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Green8f037e42010-12-19 22:13:26 +00001762
Peter Hinz56885f32011-03-02 22:03:47 +00001763 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00001764
Peter Hinz56885f32011-03-02 22:03:47 +00001765 new_wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00001766
Andy Green0d338332011-02-12 11:57:43 +00001767 /* only to clients we are serving to */
Andy Greenb45993c2010-12-18 15:13:50 +00001768
Andy Green0d338332011-02-12 11:57:43 +00001769 if (new_wsi->mode != LWS_CONNMODE_WS_SERVING)
Andy Greenb45993c2010-12-18 15:13:50 +00001770 continue;
1771
1772 /*
1773 * never broadcast to non-established
1774 * connection
1775 */
1776
Andy Green0d338332011-02-12 11:57:43 +00001777 if (new_wsi->state != WSI_STATE_ESTABLISHED)
Andy Green4739e5c2011-01-22 12:51:57 +00001778 continue;
1779
Andy Greenb45993c2010-12-18 15:13:50 +00001780 /*
1781 * only broadcast to connections using
1782 * the requested protocol
1783 */
1784
Andy Green0d338332011-02-12 11:57:43 +00001785 if (new_wsi->protocol->protocol_index !=
1786 wsi->protocol_index_for_broadcast_proxy)
Andy Greenb45993c2010-12-18 15:13:50 +00001787 continue;
1788
Andy Green8f037e42010-12-19 22:13:26 +00001789 /* broadcast it to this connection */
1790
Peter Hinz56885f32011-03-02 22:03:47 +00001791 new_wsi->protocol->callback(context, new_wsi,
Andy Green8f037e42010-12-19 22:13:26 +00001792 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00001793 new_wsi->user_space,
Andy Green0ca6a172010-12-19 20:50:01 +00001794 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
Andy Greenb45993c2010-12-18 15:13:50 +00001795 }
Andy Green0d338332011-02-12 11:57:43 +00001796 }
1797 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001798
Andy Greenbe93fef2011-02-14 20:25:43 +00001799 case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
1800
1801 /* handle proxy hung up on us */
1802
1803 if (pollfd->revents & (POLLERR | POLLHUP)) {
1804
Andy Green43db0452013-01-10 19:50:35 +08001805 lwsl_warn("Proxy connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00001806 (void *)wsi, pollfd->fd);
1807
Peter Hinz56885f32011-03-02 22:03:47 +00001808 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001809 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001810 return 1;
1811 }
1812
Andy Green72c34322011-04-16 10:46:21 +01001813 n = recv(wsi->sock, pkt, sizeof pkt, 0);
Andy Greenbe93fef2011-02-14 20:25:43 +00001814 if (n < 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001815 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001816 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001817 lwsl_err("ERROR reading from proxy socket\n");
Andy Greenbe93fef2011-02-14 20:25:43 +00001818 return 1;
1819 }
1820
1821 pkt[13] = '\0';
1822 if (strcmp(pkt, "HTTP/1.0 200 ") != 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001823 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001824 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001825 lwsl_err("ERROR from proxy: %s\n", pkt);
Andy Greenbe93fef2011-02-14 20:25:43 +00001826 return 1;
1827 }
1828
1829 /* clear his proxy connection timeout */
1830
1831 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1832
1833 /* fallthru */
1834
1835 case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
1836
1837 #ifdef LWS_OPENSSL_SUPPORT
Ken Atherton8360a472012-05-03 11:45:04 +08001838 if (wsi->use_ssl && !wsi->ssl) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001839
Peter Hinz56885f32011-03-02 22:03:47 +00001840 wsi->ssl = SSL_new(context->ssl_client_ctx);
1841 wsi->client_bio = BIO_new_socket(wsi->sock,
1842 BIO_NOCLOSE);
Andy Greenbe93fef2011-02-14 20:25:43 +00001843 SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
1844
Andy Green6901cb32011-02-21 08:06:47 +00001845 SSL_set_ex_data(wsi->ssl,
Andy Green2e24da02011-03-05 16:12:04 +00001846 openssl_websocket_private_data_index,
Peter Hinz56885f32011-03-02 22:03:47 +00001847 context);
Ken Atherton8360a472012-05-03 11:45:04 +08001848 }
Andy Green6901cb32011-02-21 08:06:47 +00001849
Ken Atherton8360a472012-05-03 11:45:04 +08001850 if (wsi->use_ssl) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001851 if (SSL_connect(wsi->ssl) <= 0) {
Ken Atherton8360a472012-05-03 11:45:04 +08001852
1853 /*
1854 * retry if new data comes until we
1855 * run into the connection timeout or win
1856 */
1857
Andy Green43db0452013-01-10 19:50:35 +08001858 lwsl_err("SSL connect error %s\n",
Andy Green687b0182011-02-26 11:04:01 +00001859 ERR_error_string(ERR_get_error(),
1860 ssl_err_buf));
Ken Atherton8360a472012-05-03 11:45:04 +08001861 return 0;
Andy Greenbe93fef2011-02-14 20:25:43 +00001862 }
1863
1864 n = SSL_get_verify_result(wsi->ssl);
Andy Green2e24da02011-03-05 16:12:04 +00001865 if ((n != X509_V_OK) && (
Andy Green687b0182011-02-26 11:04:01 +00001866 n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
1867 wsi->use_ssl != 2)) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001868
Andy Green43db0452013-01-10 19:50:35 +08001869 lwsl_err("server's cert didn't "
Andy Green687b0182011-02-26 11:04:01 +00001870 "look good %d\n", n);
Peter Hinz56885f32011-03-02 22:03:47 +00001871 libwebsocket_close_and_free_session(context,
1872 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Green687b0182011-02-26 11:04:01 +00001873 return 1;
Andy Greenbe93fef2011-02-14 20:25:43 +00001874 }
Ken Atherton8360a472012-05-03 11:45:04 +08001875 } else
Andy Greenbe93fef2011-02-14 20:25:43 +00001876 wsi->ssl = NULL;
1877 #endif
1878
Andy Greena41314f2011-05-23 10:00:03 +01001879 p = libwebsockets_generate_client_handshake(context, wsi, p);
Andy Green6ee372f2012-04-09 15:09:01 +08001880 if (p == NULL)
Andy Greenbe93fef2011-02-14 20:25:43 +00001881 return 1;
Andy Greeneeaacb32011-03-01 20:44:24 +00001882
Andy Greenbe93fef2011-02-14 20:25:43 +00001883 /* send our request to the server */
1884
1885 #ifdef LWS_OPENSSL_SUPPORT
1886 if (wsi->use_ssl)
1887 n = SSL_write(wsi->ssl, pkt, p - pkt);
1888 else
1889 #endif
1890 n = send(wsi->sock, pkt, p - pkt, 0);
1891
1892 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001893 lwsl_debug("ERROR writing to client socket\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001894 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001895 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001896 return 1;
1897 }
1898
1899 wsi->parser_state = WSI_TOKEN_NAME_PART;
1900 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
1901 libwebsocket_set_timeout(wsi,
David Galeanoc9f1ff82013-01-09 18:01:23 +08001902 PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, AWAITING_TIMEOUT);
Andy Greenbe93fef2011-02-14 20:25:43 +00001903
1904 break;
1905
1906 case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
1907
1908 /* handle server hung up on us */
1909
1910 if (pollfd->revents & (POLLERR | POLLHUP)) {
1911
Andy Green43db0452013-01-10 19:50:35 +08001912 lwsl_debug("Server connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00001913 (void *)wsi, pollfd->fd);
1914
1915 goto bail3;
1916 }
1917
1918
1919 /* interpret the server response */
1920
1921 /*
1922 * HTTP/1.1 101 Switching Protocols
1923 * Upgrade: websocket
1924 * Connection: Upgrade
1925 * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
1926 * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
1927 * Sec-WebSocket-Protocol: chat
1928 */
1929
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001930 /*
1931 * we have to take some care here to only take from the
1932 * socket bytewise. The browser may (and has been seen to
1933 * in the case that onopen() performs websocket traffic)
1934 * coalesce both handshake response and websocket traffic
1935 * in one packet, since at that point the connection is
1936 * definitively ready from browser pov.
1937 */
Andy Greenbe93fef2011-02-14 20:25:43 +00001938
Andy Green7b5af9a2012-04-09 15:23:47 +08001939 len = 1;
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001940 while (wsi->parser_state != WSI_PARSING_COMPLETE && len > 0) {
1941#ifdef LWS_OPENSSL_SUPPORT
1942 if (wsi->use_ssl)
1943 len = SSL_read(wsi->ssl, &c, 1);
1944 else
1945#endif
1946 len = recv(wsi->sock, &c, 1, 0);
1947
1948 libwebsocket_parse(wsi, c);
Andy Greenbe93fef2011-02-14 20:25:43 +00001949 }
1950
Andy Green27a0b912011-04-16 10:54:28 +01001951 /*
Andy Green6ee372f2012-04-09 15:09:01 +08001952 * hs may also be coming in multiple packets, there is a 5-sec
Andy Green27a0b912011-04-16 10:54:28 +01001953 * libwebsocket timeout still active here too, so if parsing did
1954 * not complete just wait for next packet coming in this state
1955 */
1956
1957 if (wsi->parser_state != WSI_PARSING_COMPLETE)
1958 break;
Andy Greenbe93fef2011-02-14 20:25:43 +00001959
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001960 /*
1961 * otherwise deal with the handshake. If there's any
1962 * packet traffic already arrived we'll trigger poll() again
1963 * right away and deal with it that way
1964 */
1965
Andy Greena41314f2011-05-23 10:00:03 +01001966 return lws_client_interpret_server_handshake(context, wsi);
Andy Greenbe93fef2011-02-14 20:25:43 +00001967
1968bail3:
1969 if (wsi->c_protocol)
1970 free(wsi->c_protocol);
Peter Hinz56885f32011-03-02 22:03:47 +00001971 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08001972 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001973 return 1;
Andy Greena41314f2011-05-23 10:00:03 +01001974
1975 case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
Andy Green43db0452013-01-10 19:50:35 +08001976 lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
Andy Greena41314f2011-05-23 10:00:03 +01001977 break;
1978
1979 case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
Andy Green43db0452013-01-10 19:50:35 +08001980 lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
Andy Greena41314f2011-05-23 10:00:03 +01001981 break;
1982
Andy Greenbe93fef2011-02-14 20:25:43 +00001983
Andy Green0d338332011-02-12 11:57:43 +00001984 case LWS_CONNMODE_WS_SERVING:
1985 case LWS_CONNMODE_WS_CLIENT:
1986
1987 /* handle session socket closed */
1988
1989 if (pollfd->revents & (POLLERR | POLLHUP)) {
1990
Andy Green43db0452013-01-10 19:50:35 +08001991 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Andy Green0d338332011-02-12 11:57:43 +00001992 (void *)wsi, pollfd->fd);
1993
Peter Hinz56885f32011-03-02 22:03:47 +00001994 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001995 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green4b6fbe12011-02-14 08:03:48 +00001996 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00001997 }
1998
Andy Green0d338332011-02-12 11:57:43 +00001999 /* the guy requested a callback when it was OK to write */
2000
Andy Greenda527df2011-03-07 07:08:12 +00002001 if ((pollfd->revents & POLLOUT) &&
2002 wsi->state == WSI_STATE_ESTABLISHED)
2003 if (lws_handle_POLLOUT_event(context, wsi,
2004 pollfd) < 0) {
2005 libwebsocket_close_and_free_session(
2006 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00002007 return 1;
2008 }
Andy Green0d338332011-02-12 11:57:43 +00002009
Andy Green0d338332011-02-12 11:57:43 +00002010
2011 /* any incoming data ready? */
2012
2013 if (!(pollfd->revents & POLLIN))
2014 break;
2015
Andy Greenb45993c2010-12-18 15:13:50 +00002016#ifdef LWS_OPENSSL_SUPPORT
David Galeano7ffbe1b2013-01-10 10:35:32 +08002017read_pending:
Andy Green0d338332011-02-12 11:57:43 +00002018 if (wsi->ssl)
Andy Green98a717c2011-03-06 13:14:15 +00002019 eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);
Andy Greenb45993c2010-12-18 15:13:50 +00002020 else
2021#endif
Andy Green98a717c2011-03-06 13:14:15 +00002022 eff_buf.token_len =
Andy Green72c34322011-04-16 10:46:21 +01002023 recv(pollfd->fd, buf, sizeof buf, 0);
Andy Greenb45993c2010-12-18 15:13:50 +00002024
Andy Green98a717c2011-03-06 13:14:15 +00002025 if (eff_buf.token_len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002026 lwsl_debug("Socket read returned %d\n",
Andy Green98a717c2011-03-06 13:14:15 +00002027 eff_buf.token_len);
Alon Levydc93b7f2012-10-19 11:21:57 +02002028 if (errno != EINTR && errno != EAGAIN)
Andy Green6ee372f2012-04-09 15:09:01 +08002029 libwebsocket_close_and_free_session(context,
2030 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Nick Dowellc04c1932012-04-05 10:29:39 +08002031 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002032 }
Andy Green98a717c2011-03-06 13:14:15 +00002033 if (!eff_buf.token_len) {
Peter Hinz56885f32011-03-02 22:03:47 +00002034 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002035 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenfa3f4052012-10-07 20:40:35 +08002036 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00002037 }
2038
Andy Green98a717c2011-03-06 13:14:15 +00002039 /*
2040 * give any active extensions a chance to munge the buffer
2041 * before parse. We pass in a pointer to an lws_tokens struct
2042 * prepared with the default buffer and content length that's in
2043 * there. Rather than rewrite the default buffer, extensions
2044 * that expect to grow the buffer can adapt .token to
2045 * point to their own per-connection buffer in the extension
2046 * user allocation. By default with no extensions or no
2047 * extension callback handling, just the normal input buffer is
2048 * used then so it is efficient.
2049 */
Andy Greenb45993c2010-12-18 15:13:50 +00002050
Andy Green98a717c2011-03-06 13:14:15 +00002051 eff_buf.token = (char *)buf;
Andy Greenb45993c2010-12-18 15:13:50 +00002052
Andy Green98a717c2011-03-06 13:14:15 +00002053 more = 1;
2054 while (more) {
Andy Green0d338332011-02-12 11:57:43 +00002055
Andy Green98a717c2011-03-06 13:14:15 +00002056 more = 0;
2057
2058 for (n = 0; n < wsi->count_active_extensions; n++) {
Andy Green46c2ea02011-03-22 09:04:01 +00002059 m = wsi->active_extensions[n]->callback(context,
2060 wsi->active_extensions[n], wsi,
Andy Green98a717c2011-03-06 13:14:15 +00002061 LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
Andy Green46c2ea02011-03-22 09:04:01 +00002062 wsi->active_extensions_user[n],
2063 &eff_buf, 0);
Andy Green98a717c2011-03-06 13:14:15 +00002064 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002065 lwsl_ext(
Andy Green6ee372f2012-04-09 15:09:01 +08002066 "Extension reports fatal error\n");
2067 libwebsocket_close_and_free_session(
2068 context, wsi,
2069 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green98a717c2011-03-06 13:14:15 +00002070 return 1;
2071 }
2072 if (m)
2073 more = 1;
2074 }
2075
2076 /* service incoming data */
2077
2078 if (eff_buf.token_len) {
2079 n = libwebsocket_read(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002080 (unsigned char *)eff_buf.token,
2081 eff_buf.token_len);
Andy Green98a717c2011-03-06 13:14:15 +00002082 if (n < 0)
2083 /* we closed wsi */
2084 return 1;
2085 }
2086
2087 eff_buf.token = NULL;
2088 eff_buf.token_len = 0;
2089 }
David Galeano7ffbe1b2013-01-10 10:35:32 +08002090
2091#ifdef LWS_OPENSSL_SUPPORT
2092 if (wsi->ssl && SSL_pending(wsi->ssl))
2093 goto read_pending;
2094#endif
Andy Green98a717c2011-03-06 13:14:15 +00002095 break;
Andy Greenb45993c2010-12-18 15:13:50 +00002096 }
2097
2098 return 0;
2099}
2100
Andy Green0d338332011-02-12 11:57:43 +00002101
Andy Green6964bb52011-01-23 16:50:33 +00002102/**
2103 * libwebsocket_context_destroy() - Destroy the websocket context
Peter Hinz56885f32011-03-02 22:03:47 +00002104 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002105 *
2106 * This function closes any active connections and then frees the
2107 * context. After calling this, any further use of the context is
2108 * undefined.
2109 */
2110void
Peter Hinz56885f32011-03-02 22:03:47 +00002111libwebsocket_context_destroy(struct libwebsocket_context *context)
Andy Green6964bb52011-01-23 16:50:33 +00002112{
Andy Green0d338332011-02-12 11:57:43 +00002113 int n;
2114 int m;
2115 struct libwebsocket *wsi;
Andy Greena41314f2011-05-23 10:00:03 +01002116 struct libwebsocket_extension *ext;
Andy Green6964bb52011-01-23 16:50:33 +00002117
Andy Green4b6fbe12011-02-14 08:03:48 +00002118 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002119 for (m = 0; m < context->fd_hashtable[n].length; m++) {
2120 wsi = context->fd_hashtable[n].wsi[m];
2121 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002122 LWS_CLOSE_STATUS_GOINGAWAY);
Andy Greenf3d3b402011-02-09 07:16:34 +00002123 }
Andy Green6964bb52011-01-23 16:50:33 +00002124
Andy Greena41314f2011-05-23 10:00:03 +01002125 /*
2126 * give all extensions a chance to clean up any per-context
2127 * allocations they might have made
2128 */
2129
2130 ext = context->extensions;
2131 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
2132 if (context->listen_port)
2133 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
Paulo Roberto Urio1f680ab2012-06-04 08:40:28 +08002134 while (ext && ext->callback) {
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002135 ext->callback(context, ext, NULL, (enum libwebsocket_extension_callback_reasons)m, NULL, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01002136 ext++;
2137 }
2138
Peter Hinz56885f32011-03-02 22:03:47 +00002139#ifdef WIN32
2140#else
2141 close(context->fd_random);
Andy Green6964bb52011-01-23 16:50:33 +00002142#endif
2143
Peter Hinz56885f32011-03-02 22:03:47 +00002144#ifdef LWS_OPENSSL_SUPPORT
2145 if (context->ssl_ctx)
2146 SSL_CTX_free(context->ssl_ctx);
2147 if (context->ssl_client_ctx)
2148 SSL_CTX_free(context->ssl_client_ctx);
2149#endif
2150
2151 free(context);
2152
2153#ifdef WIN32
2154 WSACleanup();
2155#endif
Andy Green6964bb52011-01-23 16:50:33 +00002156}
2157
Alon Levy0291eb32012-10-19 11:21:56 +02002158LWS_EXTERN void *
2159libwebsocket_context_user(struct libwebsocket_context *context)
2160{
2161 return context->user_space;
2162}
2163
Andy Green6964bb52011-01-23 16:50:33 +00002164/**
2165 * libwebsocket_service() - Service any pending websocket activity
Peter Hinz56885f32011-03-02 22:03:47 +00002166 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002167 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
2168 * service otherwise block and service immediately, returning
2169 * after the timeout if nothing needed service.
2170 *
2171 * This function deals with any pending websocket traffic, for three
2172 * kinds of event. It handles these events on both server and client
2173 * types of connection the same.
2174 *
2175 * 1) Accept new connections to our context's server
2176 *
2177 * 2) Perform pending broadcast writes initiated from other forked
2178 * processes (effectively serializing asynchronous broadcasts)
2179 *
2180 * 3) Call the receive callback for incoming frame data received by
2181 * server or client connections.
2182 *
2183 * You need to call this service function periodically to all the above
2184 * functions to happen; if your application is single-threaded you can
2185 * just call it in your main event loop.
2186 *
2187 * Alternatively you can fork a new process that asynchronously handles
2188 * calling this service in a loop. In that case you are happy if this
2189 * call blocks your thread until it needs to take care of something and
2190 * would call it with a large nonzero timeout. Your loop then takes no
2191 * CPU while there is nothing happening.
2192 *
2193 * If you are calling it in a single-threaded app, you don't want it to
2194 * wait around blocking other things in your loop from happening, so you
2195 * would call it with a timeout_ms of 0, so it returns immediately if
2196 * nothing is pending, or as soon as it services whatever was pending.
2197 */
2198
Andy Greenb45993c2010-12-18 15:13:50 +00002199
Andy Greene92cd172011-01-19 13:11:55 +00002200int
Peter Hinz56885f32011-03-02 22:03:47 +00002201libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
Andy Greene92cd172011-01-19 13:11:55 +00002202{
2203 int n;
Andy Greene92cd172011-01-19 13:11:55 +00002204
2205 /* stay dead once we are dead */
2206
Peter Hinz56885f32011-03-02 22:03:47 +00002207 if (context == NULL)
Andy Greene92cd172011-01-19 13:11:55 +00002208 return 1;
2209
Andy Green0d338332011-02-12 11:57:43 +00002210 /* wait for something to need service */
Andy Green4739e5c2011-01-22 12:51:57 +00002211
Peter Hinz56885f32011-03-02 22:03:47 +00002212 n = poll(context->fds, context->fds_count, timeout_ms);
Andy Green3221f922011-02-12 13:14:11 +00002213 if (n == 0) /* poll timeout */
2214 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002215
Andy Green62c54d22011-02-14 09:14:25 +00002216 if (n < 0) {
Andy Green5e1fa172011-02-10 09:07:05 +00002217 /*
Andy Green43db0452013-01-10 19:50:35 +08002218 lwsl_err("Listen Socket dead\n");
Andy Green5e1fa172011-02-10 09:07:05 +00002219 */
Andy Green3928f612012-07-20 12:58:38 +08002220 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002221 }
Andy Greene92cd172011-01-19 13:11:55 +00002222
2223 /* handle accept on listening socket? */
2224
Peter Hinz56885f32011-03-02 22:03:47 +00002225 for (n = 0; n < context->fds_count; n++)
2226 if (context->fds[n].revents)
Andy Green3928f612012-07-20 12:58:38 +08002227 if (libwebsocket_service_fd(context,
2228 &context->fds[n]) < 0)
2229 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002230 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002231}
2232
Andy Greena41314f2011-05-23 10:00:03 +01002233int
2234lws_any_extension_handled(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002235 struct libwebsocket *wsi,
2236 enum libwebsocket_extension_callback_reasons r,
Andy Greena41314f2011-05-23 10:00:03 +01002237 void *v, size_t len)
2238{
2239 int n;
2240 int handled = 0;
2241
2242 /* maybe an extension will take care of it for us */
2243
2244 for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
2245 if (!wsi->active_extensions[n]->callback)
2246 continue;
2247
2248 handled |= wsi->active_extensions[n]->callback(context,
2249 wsi->active_extensions[n], wsi,
2250 r, wsi->active_extensions_user[n], v, len);
2251 }
2252
2253 return handled;
2254}
2255
2256
2257void *
2258lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002259 struct libwebsocket_extension *ext)
Andy Greena41314f2011-05-23 10:00:03 +01002260{
2261 int n = 0;
2262
Andy Green68b45042011-05-25 21:41:57 +01002263 if (wsi == NULL)
2264 return NULL;
2265
Andy Greena41314f2011-05-23 10:00:03 +01002266 while (n < wsi->count_active_extensions) {
2267 if (wsi->active_extensions[n] != ext) {
2268 n++;
2269 continue;
2270 }
2271 return wsi->active_extensions_user[n];
2272 }
2273
2274 return NULL;
2275}
2276
Andy Green90c7cbc2011-01-27 06:26:52 +00002277/**
2278 * libwebsocket_callback_on_writable() - Request a callback when this socket
2279 * becomes able to be written to without
2280 * blocking
Andy Green32375b72011-02-19 08:32:53 +00002281 *
Peter Hinz56885f32011-03-02 22:03:47 +00002282 * @context: libwebsockets context
Andy Green90c7cbc2011-01-27 06:26:52 +00002283 * @wsi: Websocket connection instance to get callback for
2284 */
2285
2286int
Peter Hinz56885f32011-03-02 22:03:47 +00002287libwebsocket_callback_on_writable(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002288 struct libwebsocket *wsi)
Andy Green90c7cbc2011-01-27 06:26:52 +00002289{
Andy Green90c7cbc2011-01-27 06:26:52 +00002290 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002291 int handled = 0;
2292
2293 /* maybe an extension will take care of it for us */
2294
2295 for (n = 0; n < wsi->count_active_extensions; n++) {
2296 if (!wsi->active_extensions[n]->callback)
2297 continue;
2298
2299 handled |= wsi->active_extensions[n]->callback(context,
2300 wsi->active_extensions[n], wsi,
2301 LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
2302 wsi->active_extensions_user[n], NULL, 0);
2303 }
2304
2305 if (handled)
2306 return 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002307
Peter Hinz56885f32011-03-02 22:03:47 +00002308 for (n = 0; n < context->fds_count; n++)
2309 if (context->fds[n].fd == wsi->sock) {
2310 context->fds[n].events |= POLLOUT;
Andy Greena41314f2011-05-23 10:00:03 +01002311 n = context->fds_count + 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002312 }
2313
Andy Greena41314f2011-05-23 10:00:03 +01002314 if (n == context->fds_count)
Andy Green43db0452013-01-10 19:50:35 +08002315 lwsl_err("libwebsocket_callback_on_writable: "
Andy Green6ee372f2012-04-09 15:09:01 +08002316 "failed to find socket %d\n", wsi->sock);
Andy Greena41314f2011-05-23 10:00:03 +01002317
Andy Green3221f922011-02-12 13:14:11 +00002318 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002319 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002320 LWS_CALLBACK_SET_MODE_POLL_FD,
2321 (void *)(long)wsi->sock, NULL, POLLOUT);
2322
Andy Green90c7cbc2011-01-27 06:26:52 +00002323 return 1;
2324}
2325
2326/**
2327 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
2328 * all connections using the given protocol when it
2329 * becomes possible to write to each socket without
2330 * blocking in turn.
2331 *
2332 * @protocol: Protocol whose connections will get callbacks
2333 */
2334
2335int
2336libwebsocket_callback_on_writable_all_protocol(
2337 const struct libwebsocket_protocols *protocol)
2338{
Peter Hinz56885f32011-03-02 22:03:47 +00002339 struct libwebsocket_context *context = protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002340 int n;
Andy Green0d338332011-02-12 11:57:43 +00002341 int m;
2342 struct libwebsocket *wsi;
Andy Green90c7cbc2011-01-27 06:26:52 +00002343
Andy Green0d338332011-02-12 11:57:43 +00002344 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
2345
Peter Hinz56885f32011-03-02 22:03:47 +00002346 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Green0d338332011-02-12 11:57:43 +00002347
Peter Hinz56885f32011-03-02 22:03:47 +00002348 wsi = context->fd_hashtable[n].wsi[m];
Andy Green0d338332011-02-12 11:57:43 +00002349
2350 if (wsi->protocol == protocol)
Peter Hinz56885f32011-03-02 22:03:47 +00002351 libwebsocket_callback_on_writable(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002352 }
2353 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002354
2355 return 0;
2356}
2357
Andy Greenbe93fef2011-02-14 20:25:43 +00002358/**
2359 * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
2360 *
2361 * You will not need this unless you are doing something special
2362 *
2363 * @wsi: Websocket connection instance
2364 * @reason: timeout reason
2365 * @secs: how many seconds
2366 */
2367
2368void
2369libwebsocket_set_timeout(struct libwebsocket *wsi,
2370 enum pending_timeout reason, int secs)
2371{
2372 struct timeval tv;
2373
2374 gettimeofday(&tv, NULL);
2375
2376 wsi->pending_timeout_limit = tv.tv_sec + secs;
2377 wsi->pending_timeout = reason;
2378}
2379
Andy Greena6cbece2011-01-27 20:06:03 +00002380
2381/**
2382 * libwebsocket_get_socket_fd() - returns the socket file descriptor
2383 *
2384 * You will not need this unless you are doing something special
2385 *
2386 * @wsi: Websocket connection instance
2387 */
2388
2389int
2390libwebsocket_get_socket_fd(struct libwebsocket *wsi)
2391{
2392 return wsi->sock;
2393}
2394
Andy Green90c7cbc2011-01-27 06:26:52 +00002395/**
2396 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
2397 * receieved packets.
2398 *
2399 * If the output side of a server process becomes choked, this allows flow
2400 * control for the input side.
2401 *
2402 * @wsi: Websocket connection instance to get callback for
2403 * @enable: 0 = disable read servicing for this connection, 1 = enable
2404 */
2405
2406int
2407libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
2408{
Peter Hinz56885f32011-03-02 22:03:47 +00002409 struct libwebsocket_context *context = wsi->protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002410 int n;
2411
Peter Hinz56885f32011-03-02 22:03:47 +00002412 for (n = 0; n < context->fds_count; n++)
2413 if (context->fds[n].fd == wsi->sock) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002414 if (enable)
Peter Hinz56885f32011-03-02 22:03:47 +00002415 context->fds[n].events |= POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002416 else
Peter Hinz56885f32011-03-02 22:03:47 +00002417 context->fds[n].events &= ~POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002418
2419 return 0;
2420 }
2421
Andy Green3221f922011-02-12 13:14:11 +00002422 if (enable)
2423 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002424 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002425 LWS_CALLBACK_SET_MODE_POLL_FD,
2426 (void *)(long)wsi->sock, NULL, POLLIN);
2427 else
2428 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002429 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002430 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
2431 (void *)(long)wsi->sock, NULL, POLLIN);
2432
Andy Greena41314f2011-05-23 10:00:03 +01002433#if 0
Andy Green43db0452013-01-10 19:50:35 +08002434 lwsl_err("libwebsocket_rx_flow_control unable to find socket\n");
Andy Greena41314f2011-05-23 10:00:03 +01002435#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002436 return 1;
2437}
2438
Andy Green2ac5a6f2011-01-28 10:00:18 +00002439/**
2440 * libwebsocket_canonical_hostname() - returns this host's hostname
2441 *
2442 * This is typically used by client code to fill in the host parameter
2443 * when making a client connection. You can only call it after the context
2444 * has been created.
2445 *
Peter Hinz56885f32011-03-02 22:03:47 +00002446 * @context: Websocket context
Andy Green2ac5a6f2011-01-28 10:00:18 +00002447 */
2448
2449
2450extern const char *
Peter Hinz56885f32011-03-02 22:03:47 +00002451libwebsocket_canonical_hostname(struct libwebsocket_context *context)
Andy Green2ac5a6f2011-01-28 10:00:18 +00002452{
Peter Hinz56885f32011-03-02 22:03:47 +00002453 return (const char *)context->canonical_hostname;
Andy Green2ac5a6f2011-01-28 10:00:18 +00002454}
2455
2456
Andy Green90c7cbc2011-01-27 06:26:52 +00002457static void sigpipe_handler(int x)
2458{
2459}
2460
Andy Green6901cb32011-02-21 08:06:47 +00002461#ifdef LWS_OPENSSL_SUPPORT
2462static int
2463OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
2464{
2465
2466 SSL *ssl;
2467 int n;
Andy Green2e24da02011-03-05 16:12:04 +00002468 struct libwebsocket_context *context;
Andy Green6901cb32011-02-21 08:06:47 +00002469
2470 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
2471 SSL_get_ex_data_X509_STORE_CTX_idx());
2472
2473 /*
Andy Green2e24da02011-03-05 16:12:04 +00002474 * !!! nasty openssl requires the index to come as a library-scope
2475 * static
Andy Green6901cb32011-02-21 08:06:47 +00002476 */
Andy Green2e24da02011-03-05 16:12:04 +00002477 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
Andy Green6ee372f2012-04-09 15:09:01 +08002478
Peter Hinz56885f32011-03-02 22:03:47 +00002479 n = context->protocols[0].callback(NULL, NULL,
Andy Green6901cb32011-02-21 08:06:47 +00002480 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
2481 x509_ctx, ssl, preverify_ok);
2482
2483 /* convert return code from 0 = OK to 1 = OK */
2484
2485 if (!n)
2486 n = 1;
2487 else
2488 n = 0;
2489
2490 return n;
2491}
2492#endif
2493
Andy Greenb45993c2010-12-18 15:13:50 +00002494
Andy Greenab990e42010-10-31 12:42:52 +00002495/**
Andy Green4739e5c2011-01-22 12:51:57 +00002496 * libwebsocket_create_context() - Create the websocket handler
2497 * @port: Port to listen on... you can use 0 to suppress listening on
Andy Green6964bb52011-01-23 16:50:33 +00002498 * any port, that's what you want if you are not running a
2499 * websocket server at all but just using it as a client
Peter Hinz56885f32011-03-02 22:03:47 +00002500 * @interf: NULL to bind the listen socket to all interfaces, or the
Andy Green32375b72011-02-19 08:32:53 +00002501 * interface name, eg, "eth2"
Andy Green4f3943a2010-11-12 10:44:16 +00002502 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +00002503 * specific callback for each one. The list is ended with an
2504 * entry that has a NULL callback pointer.
Andy Green6964bb52011-01-23 16:50:33 +00002505 * It's not const because we write the owning_server member
Andy Greenc5114822011-03-06 10:29:35 +00002506 * @extensions: NULL or array of libwebsocket_extension structs listing the
Andy Green6ee372f2012-04-09 15:09:01 +08002507 * extensions this context supports
Andy Green3faa9c72010-11-08 17:03:03 +00002508 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +00002509 * to listen using SSL, set to the filepath to fetch the
2510 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +00002511 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +00002512 * else ignored
David Galeano2f82be82013-01-09 16:25:54 +08002513 * @ssl_ca_filepath: CA certificate filepath or NULL
Andy Green3faa9c72010-11-08 17:03:03 +00002514 * @gid: group id to change to after setting listen socket, or -1.
2515 * @uid: user id to change to after setting listen socket, or -1.
Andy Greenbfb051f2011-02-09 08:49:14 +00002516 * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
Andy Green15e31f32012-10-19 18:36:28 +08002517 * @user: optional user pointer that can be recovered via the context
2518 * pointer using libwebsocket_context_user
Andy Green05464c62010-11-12 10:44:18 +00002519 *
Andy Green8f037e42010-12-19 22:13:26 +00002520 * This function creates the listening socket and takes care
2521 * of all initialization in one step.
2522 *
Andy Greene92cd172011-01-19 13:11:55 +00002523 * After initialization, it returns a struct libwebsocket_context * that
2524 * represents this server. After calling, user code needs to take care
2525 * of calling libwebsocket_service() with the context pointer to get the
2526 * server's sockets serviced. This can be done in the same process context
2527 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +00002528 *
Andy Green8f037e42010-12-19 22:13:26 +00002529 * The protocol callback functions are called for a handful of events
2530 * including http requests coming in, websocket connections becoming
2531 * established, and data arriving; it's also called periodically to allow
2532 * async transmission.
2533 *
2534 * HTTP requests are sent always to the FIRST protocol in @protocol, since
2535 * at that time websocket protocol has not been negotiated. Other
2536 * protocols after the first one never see any HTTP callack activity.
2537 *
2538 * The server created is a simple http server by default; part of the
2539 * websocket standard is upgrading this http connection to a websocket one.
2540 *
2541 * This allows the same server to provide files like scripts and favicon /
2542 * images or whatever over http and dynamic data over websockets all in
2543 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +00002544 */
Andy Green4ea60062010-10-30 12:15:07 +01002545
Andy Greene92cd172011-01-19 13:11:55 +00002546struct libwebsocket_context *
Peter Hinz56885f32011-03-02 22:03:47 +00002547libwebsocket_create_context(int port, const char *interf,
Andy Greenb45993c2010-12-18 15:13:50 +00002548 struct libwebsocket_protocols *protocols,
Andy Greend6e09112011-03-05 16:12:15 +00002549 struct libwebsocket_extension *extensions,
Andy Green8f037e42010-12-19 22:13:26 +00002550 const char *ssl_cert_filepath,
2551 const char *ssl_private_key_filepath,
David Galeano2f82be82013-01-09 16:25:54 +08002552 const char *ssl_ca_filepath,
Alon Levy0291eb32012-10-19 11:21:56 +02002553 int gid, int uid, unsigned int options,
David Galeano2f82be82013-01-09 16:25:54 +08002554 void *user)
Andy Greenff95d7a2010-10-28 22:36:01 +01002555{
2556 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002557 int m;
Andy Green4739e5c2011-01-22 12:51:57 +00002558 int sockfd = 0;
Andy Green251f6fa2010-11-03 11:13:06 +00002559 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +01002560 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +00002561 int opt = 1;
Peter Hinz56885f32011-03-02 22:03:47 +00002562 struct libwebsocket_context *context = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002563 unsigned int slen;
Andy Green9659f372011-01-27 22:01:43 +00002564 char *p;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002565 char hostname[1024] = "";
Andy Greena69f0512012-05-03 12:32:38 +08002566// struct hostent *he;
Andy Green0d338332011-02-12 11:57:43 +00002567 struct libwebsocket *wsi;
Andy Greena69f0512012-05-03 12:32:38 +08002568 struct sockaddr sa;
Andy Greenff95d7a2010-10-28 22:36:01 +01002569
Andy Green3faa9c72010-11-08 17:03:03 +00002570#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +00002571 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +00002572 char ssl_err_buf[512];
Andy Green3faa9c72010-11-08 17:03:03 +00002573#endif
2574
Andy Green43db0452013-01-10 19:50:35 +08002575 lwsl_info("Initial logging level %d\n", log_level);
Andy Greenc0d6b632013-01-12 23:42:17 +08002576 lwsl_info(" FD_HASHTABLE_MODULUS: %u\n", FD_HASHTABLE_MODULUS);
2577 lwsl_info(" MAX_CLIENTS: %u\n", MAX_CLIENTS);
2578 lwsl_info(" LWS_MAX_HEADER_NAME_LENGTH: %u\n", LWS_MAX_HEADER_NAME_LENGTH);
2579 lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
2580 lwsl_info(" LWS_INITIAL_HDR_ALLOC: %u\n", LWS_INITIAL_HDR_ALLOC);
2581 lwsl_info(" LWS_ADDITIONAL_HDR_ALLOC: %u\n", LWS_ADDITIONAL_HDR_ALLOC);
2582 lwsl_info(" MAX_USER_RX_BUFFER: %u\n", MAX_USER_RX_BUFFER);
2583 lwsl_info(" MAX_BROADCAST_PAYLOAD: %u\n", MAX_BROADCAST_PAYLOAD);
2584 lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
2585 lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE);
2586 lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED);
2587 lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT);
2588 lwsl_info(" CIPHERS_LIST_STRING: '%s'\n", CIPHERS_LIST_STRING);
2589 lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
2590 lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER);
Andy Green43db0452013-01-10 19:50:35 +08002591
Peter Hinz56885f32011-03-02 22:03:47 +00002592#ifdef _WIN32
2593 {
2594 WORD wVersionRequested;
2595 WSADATA wsaData;
2596 int err;
Andy Green6ee372f2012-04-09 15:09:01 +08002597 HMODULE wsdll;
Peter Hinz56885f32011-03-02 22:03:47 +00002598
2599 /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
2600 wVersionRequested = MAKEWORD(2, 2);
2601
2602 err = WSAStartup(wVersionRequested, &wsaData);
2603 if (err != 0) {
2604 /* Tell the user that we could not find a usable */
2605 /* Winsock DLL. */
Andy Green43db0452013-01-10 19:50:35 +08002606 lwsl_err("WSAStartup failed with error: %d\n", err);
Peter Hinz56885f32011-03-02 22:03:47 +00002607 return NULL;
2608 }
David Galeano7b11fec2011-10-04 19:55:18 +08002609
Andy Green6ee372f2012-04-09 15:09:01 +08002610 /* default to a poll() made out of select() */
2611 poll = emulated_poll;
David Galeano7b11fec2011-10-04 19:55:18 +08002612
Andy Green6ee372f2012-04-09 15:09:01 +08002613 /* if windows socket lib available, use his WSAPoll */
David Galeanocb193682013-01-09 15:29:00 +08002614 wsdll = GetModuleHandle(_T("Ws2_32.dll"));
Andy Green6ee372f2012-04-09 15:09:01 +08002615 if (wsdll)
2616 poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
Peter Hinz56885f32011-03-02 22:03:47 +00002617 }
2618#endif
2619
2620
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002621 context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context));
Peter Hinz56885f32011-03-02 22:03:47 +00002622 if (!context) {
Andy Green43db0452013-01-10 19:50:35 +08002623 lwsl_err("No memory for websocket context\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002624 return NULL;
2625 }
Peter Hinz56885f32011-03-02 22:03:47 +00002626 context->protocols = protocols;
2627 context->listen_port = port;
2628 context->http_proxy_port = 0;
2629 context->http_proxy_address[0] = '\0';
2630 context->options = options;
2631 context->fds_count = 0;
Andy Greend6e09112011-03-05 16:12:15 +00002632 context->extensions = extensions;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002633 context->last_timeout_check_s = 0;
Alon Levy0291eb32012-10-19 11:21:56 +02002634 context->user_space = user;
Andy Green9659f372011-01-27 22:01:43 +00002635
Peter Hinz56885f32011-03-02 22:03:47 +00002636#ifdef WIN32
2637 context->fd_random = 0;
2638#else
2639 context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
2640 if (context->fd_random < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002641 lwsl_err("Unable to open random device %s %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002642 SYSTEM_RANDOM_FILEPATH, context->fd_random);
Andy Green44eee682011-02-10 09:32:24 +00002643 return NULL;
2644 }
Peter Hinz56885f32011-03-02 22:03:47 +00002645#endif
Andy Green44eee682011-02-10 09:32:24 +00002646
Peter Hinz56885f32011-03-02 22:03:47 +00002647#ifdef LWS_OPENSSL_SUPPORT
2648 context->use_ssl = 0;
2649 context->ssl_ctx = NULL;
2650 context->ssl_client_ctx = NULL;
Andy Green2e24da02011-03-05 16:12:04 +00002651 openssl_websocket_private_data_index = 0;
Peter Hinz56885f32011-03-02 22:03:47 +00002652#endif
Andy Green2ac5a6f2011-01-28 10:00:18 +00002653
Andy Green788c4a82012-10-22 12:29:57 +01002654 if (options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME) {
Andy Greena69f0512012-05-03 12:32:38 +08002655
Andy Green788c4a82012-10-22 12:29:57 +01002656 strcpy(context->canonical_hostname, "unknown");
Andy Greena69f0512012-05-03 12:32:38 +08002657
Andy Green788c4a82012-10-22 12:29:57 +01002658 } else {
2659
2660 /* find canonical hostname */
2661
2662 hostname[(sizeof hostname) - 1] = '\0';
2663 memset(&sa, 0, sizeof(sa));
2664 sa.sa_family = AF_INET;
2665 sa.sa_data[(sizeof sa.sa_data) - 1] = '\0';
2666 gethostname(hostname, (sizeof hostname) - 1);
2667
2668 n = 0;
2669
David Galeanoed3c8402013-01-10 10:45:24 +08002670 if (strlen(hostname) < sizeof(sa.sa_data) - 1) {
Andy Green788c4a82012-10-22 12:29:57 +01002671 strcpy(sa.sa_data, hostname);
Andy Green43db0452013-01-10 19:50:35 +08002672 // lwsl_debug("my host name is %s\n", sa.sa_data);
Andy Green788c4a82012-10-22 12:29:57 +01002673 n = getnameinfo(&sa, sizeof(sa), hostname,
2674 (sizeof hostname) - 1, NULL, 0, 0);
2675 }
2676
2677 if (!n) {
2678 strncpy(context->canonical_hostname, hostname,
2679 sizeof context->canonical_hostname - 1);
2680 context->canonical_hostname[
2681 sizeof context->canonical_hostname - 1] = '\0';
2682 } else
2683 strncpy(context->canonical_hostname, hostname,
2684 sizeof context->canonical_hostname - 1);
2685
Andy Green43db0452013-01-10 19:50:35 +08002686 // lwsl_debug("context->canonical_hostname = %s\n",
Andy Green788c4a82012-10-22 12:29:57 +01002687 // context->canonical_hostname);
Andy Greena69f0512012-05-03 12:32:38 +08002688 }
2689
Andy Green9659f372011-01-27 22:01:43 +00002690 /* split the proxy ads:port if given */
2691
2692 p = getenv("http_proxy");
2693 if (p) {
Peter Hinz56885f32011-03-02 22:03:47 +00002694 strncpy(context->http_proxy_address, p,
Andy Green6ee372f2012-04-09 15:09:01 +08002695 sizeof context->http_proxy_address - 1);
Peter Hinz56885f32011-03-02 22:03:47 +00002696 context->http_proxy_address[
2697 sizeof context->http_proxy_address - 1] = '\0';
Andy Green9659f372011-01-27 22:01:43 +00002698
Peter Hinz56885f32011-03-02 22:03:47 +00002699 p = strchr(context->http_proxy_address, ':');
Andy Green9659f372011-01-27 22:01:43 +00002700 if (p == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002701 lwsl_err("http_proxy needs to be ads:port\n");
Andy Green9659f372011-01-27 22:01:43 +00002702 return NULL;
2703 }
2704 *p = '\0';
Peter Hinz56885f32011-03-02 22:03:47 +00002705 context->http_proxy_port = atoi(p + 1);
Andy Green9659f372011-01-27 22:01:43 +00002706
Andy Green43db0452013-01-10 19:50:35 +08002707 lwsl_debug("Using proxy %s:%u\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002708 context->http_proxy_address,
2709 context->http_proxy_port);
Andy Green9659f372011-01-27 22:01:43 +00002710 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002711
2712 if (port) {
2713
Andy Green3faa9c72010-11-08 17:03:03 +00002714#ifdef LWS_OPENSSL_SUPPORT
Peter Hinz56885f32011-03-02 22:03:47 +00002715 context->use_ssl = ssl_cert_filepath != NULL &&
Andy Green90c7cbc2011-01-27 06:26:52 +00002716 ssl_private_key_filepath != NULL;
Peter Hinz56885f32011-03-02 22:03:47 +00002717 if (context->use_ssl)
Andy Green43db0452013-01-10 19:50:35 +08002718 lwsl_info(" Compiled with SSL support, using it\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002719 else
Andy Green43db0452013-01-10 19:50:35 +08002720 lwsl_info(" Compiled with SSL support, not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +00002721
Andy Green90c7cbc2011-01-27 06:26:52 +00002722#else
2723 if (ssl_cert_filepath != NULL &&
2724 ssl_private_key_filepath != NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002725 lwsl_info(" Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +00002726 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002727 }
Andy Green43db0452013-01-10 19:50:35 +08002728 lwsl_info(" Compiled without SSL support, "
Andy Green90c7cbc2011-01-27 06:26:52 +00002729 "serving unencrypted\n");
2730#endif
2731 }
2732
2733 /* ignore SIGPIPE */
Peter Hinz56885f32011-03-02 22:03:47 +00002734#ifdef WIN32
2735#else
Andy Green90c7cbc2011-01-27 06:26:52 +00002736 signal(SIGPIPE, sigpipe_handler);
Peter Hinz56885f32011-03-02 22:03:47 +00002737#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002738
2739
2740#ifdef LWS_OPENSSL_SUPPORT
2741
2742 /* basic openssl init */
2743
2744 SSL_library_init();
2745
2746 OpenSSL_add_all_algorithms();
2747 SSL_load_error_strings();
2748
Andy Green2e24da02011-03-05 16:12:04 +00002749 openssl_websocket_private_data_index =
Andy Green6901cb32011-02-21 08:06:47 +00002750 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
2751
Andy Green90c7cbc2011-01-27 06:26:52 +00002752 /*
2753 * Firefox insists on SSLv23 not SSLv3
2754 * Konq disables SSLv2 by default now, SSLv23 works
2755 */
2756
2757 method = (SSL_METHOD *)SSLv23_server_method();
2758 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002759 lwsl_err("problem creating ssl method: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002760 ERR_error_string(ERR_get_error(), ssl_err_buf));
2761 return NULL;
2762 }
Peter Hinz56885f32011-03-02 22:03:47 +00002763 context->ssl_ctx = SSL_CTX_new(method); /* create context */
2764 if (!context->ssl_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002765 lwsl_err("problem creating ssl context: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002766 ERR_error_string(ERR_get_error(), ssl_err_buf));
2767 return NULL;
2768 }
2769
David Galeanocc148e42013-01-10 10:18:59 +08002770#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002771 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002772#endif
David Galeano77a677c2013-01-10 10:14:12 +08002773 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002774 SSL_CTX_set_cipher_list(context->ssl_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002775
Andy Green90c7cbc2011-01-27 06:26:52 +00002776 /* client context */
Andy Green6ee372f2012-04-09 15:09:01 +08002777
2778 if (port == CONTEXT_PORT_NO_LISTEN) {
Peter Hinz56885f32011-03-02 22:03:47 +00002779 method = (SSL_METHOD *)SSLv23_client_method();
2780 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002781 lwsl_err("problem creating ssl method: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002782 ERR_error_string(ERR_get_error(), ssl_err_buf));
2783 return NULL;
2784 }
2785 /* create context */
2786 context->ssl_client_ctx = SSL_CTX_new(method);
2787 if (!context->ssl_client_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002788 lwsl_err("problem creating ssl context: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002789 ERR_error_string(ERR_get_error(), ssl_err_buf));
2790 return NULL;
2791 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002792
David Galeanocc148e42013-01-10 10:18:59 +08002793#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002794 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002795#endif
David Galeano77a677c2013-01-10 10:14:12 +08002796 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002797 SSL_CTX_set_cipher_list(context->ssl_client_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002798
Peter Hinz56885f32011-03-02 22:03:47 +00002799 /* openssl init for cert verification (for client sockets) */
David Galeano2f82be82013-01-09 16:25:54 +08002800 if (!ssl_ca_filepath) {
2801 if (!SSL_CTX_load_verify_locations(
2802 context->ssl_client_ctx, NULL,
2803 LWS_OPENSSL_CLIENT_CERTS))
Andy Green43db0452013-01-10 19:50:35 +08002804 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002805 "Unable to load SSL Client certs from %s "
2806 "(set by --with-client-cert-dir= in configure) -- "
2807 " client ssl isn't going to work",
2808 LWS_OPENSSL_CLIENT_CERTS);
2809 } else
2810 if (!SSL_CTX_load_verify_locations(
2811 context->ssl_client_ctx, ssl_ca_filepath,
2812 NULL))
Andy Green43db0452013-01-10 19:50:35 +08002813 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002814 "Unable to load SSL Client certs "
2815 "file from %s -- client ssl isn't "
2816 "going to work", ssl_ca_filepath);
Peter Hinz56885f32011-03-02 22:03:47 +00002817
2818 /*
2819 * callback allowing user code to load extra verification certs
2820 * helping the client to verify server identity
2821 */
2822
2823 context->protocols[0].callback(context, NULL,
2824 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
2825 context->ssl_client_ctx, NULL, 0);
Andy Green90c7cbc2011-01-27 06:26:52 +00002826 }
Andy Green6ee372f2012-04-09 15:09:01 +08002827
Andy Greenc6bf2c22011-02-20 11:10:47 +00002828 /* as a server, are we requiring clients to identify themselves? */
2829
2830 if (options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
2831
2832 /* absolutely require the client cert */
Andy Green6ee372f2012-04-09 15:09:01 +08002833
Peter Hinz56885f32011-03-02 22:03:47 +00002834 SSL_CTX_set_verify(context->ssl_ctx,
Andy Green6901cb32011-02-21 08:06:47 +00002835 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2836 OpenSSL_verify_callback);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002837
2838 /*
2839 * give user code a chance to load certs into the server
2840 * allowing it to verify incoming client certs
2841 */
2842
Peter Hinz56885f32011-03-02 22:03:47 +00002843 context->protocols[0].callback(context, NULL,
Andy Greenc6bf2c22011-02-20 11:10:47 +00002844 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
Peter Hinz56885f32011-03-02 22:03:47 +00002845 context->ssl_ctx, NULL, 0);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002846 }
2847
Peter Hinz56885f32011-03-02 22:03:47 +00002848 if (context->use_ssl) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002849
2850 /* openssl init for server sockets */
2851
Andy Green3faa9c72010-11-08 17:03:03 +00002852 /* set the local certificate from CertFile */
David Galeano9b3d4b22013-01-10 10:11:21 +08002853 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
2854 ssl_cert_filepath);
Andy Green3faa9c72010-11-08 17:03:03 +00002855 if (n != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002856 lwsl_err("problem getting cert '%s': %s\n",
Andy Green3faa9c72010-11-08 17:03:03 +00002857 ssl_cert_filepath,
2858 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002859 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002860 }
2861 /* set the private key from KeyFile */
Peter Hinz56885f32011-03-02 22:03:47 +00002862 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
2863 ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002864 lwsl_err("ssl problem getting key '%s': %s\n",
Andy Green018d8eb2010-11-08 21:04:23 +00002865 ssl_private_key_filepath,
2866 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002867 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002868 }
2869 /* verify private key */
Peter Hinz56885f32011-03-02 22:03:47 +00002870 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
Andy Green43db0452013-01-10 19:50:35 +08002871 lwsl_err("Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +00002872 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002873 }
2874
2875 /* SSL is happy and has a cert it's content with */
2876 }
2877#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002878
Andy Greendf736162011-01-18 15:39:02 +00002879 /* selftest */
2880
2881 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +00002882 return NULL;
Andy Greendf736162011-01-18 15:39:02 +00002883
Andy Green0d338332011-02-12 11:57:43 +00002884 /* fd hashtable init */
2885
2886 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002887 context->fd_hashtable[n].length = 0;
Andy Green0d338332011-02-12 11:57:43 +00002888
Andy Greenb45993c2010-12-18 15:13:50 +00002889 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +00002890
Andy Green4739e5c2011-01-22 12:51:57 +00002891 if (port) {
Andy Green8f037e42010-12-19 22:13:26 +00002892
Andy Green4739e5c2011-01-22 12:51:57 +00002893 sockfd = socket(AF_INET, SOCK_STREAM, 0);
2894 if (sockfd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002895 lwsl_err("ERROR opening socket");
Andy Green4739e5c2011-01-22 12:51:57 +00002896 return NULL;
2897 }
Andy Green775c0dd2010-10-29 14:15:22 +01002898
Andy Green4739e5c2011-01-22 12:51:57 +00002899 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08002900 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
2901 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00002902
2903 /* Disable Nagle */
2904 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08002905 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
2906 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00002907
Andy Green4739e5c2011-01-22 12:51:57 +00002908 bzero((char *) &serv_addr, sizeof(serv_addr));
2909 serv_addr.sin_family = AF_INET;
Peter Hinz56885f32011-03-02 22:03:47 +00002910 if (interf == NULL)
Andy Green32375b72011-02-19 08:32:53 +00002911 serv_addr.sin_addr.s_addr = INADDR_ANY;
2912 else
Peter Hinz56885f32011-03-02 22:03:47 +00002913 interface_to_sa(interf, &serv_addr,
Andy Green32375b72011-02-19 08:32:53 +00002914 sizeof(serv_addr));
Andy Green4739e5c2011-01-22 12:51:57 +00002915 serv_addr.sin_port = htons(port);
2916
2917 n = bind(sockfd, (struct sockaddr *) &serv_addr,
2918 sizeof(serv_addr));
2919 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002920 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Green8f037e42010-12-19 22:13:26 +00002921 port, n, errno);
Andy Green41c58032013-01-12 13:21:08 +08002922 close(sockfd);
Andy Green4739e5c2011-01-22 12:51:57 +00002923 return NULL;
2924 }
Andy Green0d338332011-02-12 11:57:43 +00002925
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002926 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08002927 if (wsi == NULL) {
2928 lwsl_err("Out of mem\n");
2929 close(sockfd);
2930 return NULL;
2931 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002932 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00002933 wsi->sock = sockfd;
Andy Greend6e09112011-03-05 16:12:15 +00002934 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00002935 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
Peter Hinz56885f32011-03-02 22:03:47 +00002936 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002937
David Galeano36973092013-01-10 09:58:24 +08002938 listen(sockfd, SOMAXCONN);
Andy Green43db0452013-01-10 19:50:35 +08002939 lwsl_info(" Listening on port %d\n", port);
Andy Green0d338332011-02-12 11:57:43 +00002940
2941 /* list in the internal poll array */
Andy Green6ee372f2012-04-09 15:09:01 +08002942
Peter Hinz56885f32011-03-02 22:03:47 +00002943 context->fds[context->fds_count].fd = sockfd;
2944 context->fds[context->fds_count++].events = POLLIN;
Andy Green3221f922011-02-12 13:14:11 +00002945
2946 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002947 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002948 LWS_CALLBACK_ADD_POLL_FD,
2949 (void *)(long)sockfd, NULL, POLLIN);
2950
Andy Green8f037e42010-12-19 22:13:26 +00002951 }
Andy Greenb45993c2010-12-18 15:13:50 +00002952
Andy Green6ee372f2012-04-09 15:09:01 +08002953 /*
2954 * drop any root privs for this process
2955 * to listen on port < 1023 we would have needed root, but now we are
2956 * listening, we don't want the power for anything else
2957 */
Peter Hinz56885f32011-03-02 22:03:47 +00002958#ifdef WIN32
2959#else
Andy Green3faa9c72010-11-08 17:03:03 +00002960 if (gid != -1)
2961 if (setgid(gid))
Andy Green43db0452013-01-10 19:50:35 +08002962 lwsl_warn("setgid: %s\n", strerror(errno));
Andy Green3faa9c72010-11-08 17:03:03 +00002963 if (uid != -1)
2964 if (setuid(uid))
Andy Green43db0452013-01-10 19:50:35 +08002965 lwsl_warn("setuid: %s\n", strerror(errno));
Peter Hinz56885f32011-03-02 22:03:47 +00002966#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002967
2968 /* set up our internal broadcast trigger sockets per-protocol */
2969
Peter Hinz56885f32011-03-02 22:03:47 +00002970 for (context->count_protocols = 0;
2971 protocols[context->count_protocols].callback;
2972 context->count_protocols++) {
Andy Green2d1301e2011-05-24 10:14:41 +01002973
Andy Green43db0452013-01-10 19:50:35 +08002974 lwsl_parser(" Protocol: %s\n",
2975 protocols[context->count_protocols].name);
Andy Green2d1301e2011-05-24 10:14:41 +01002976
Peter Hinz56885f32011-03-02 22:03:47 +00002977 protocols[context->count_protocols].owning_server = context;
2978 protocols[context->count_protocols].protocol_index =
2979 context->count_protocols;
Andy Greenb45993c2010-12-18 15:13:50 +00002980
2981 fd = socket(AF_INET, SOCK_STREAM, 0);
2982 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002983 lwsl_err("ERROR opening socket");
Andy Greene92cd172011-01-19 13:11:55 +00002984 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002985 }
Andy Green8f037e42010-12-19 22:13:26 +00002986
Andy Greenb45993c2010-12-18 15:13:50 +00002987 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08002988 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt,
2989 sizeof(opt));
Andy Greenb45993c2010-12-18 15:13:50 +00002990
2991 bzero((char *) &serv_addr, sizeof(serv_addr));
2992 serv_addr.sin_family = AF_INET;
2993 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
2994 serv_addr.sin_port = 0; /* pick the port for us */
2995
2996 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
2997 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002998 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Greenb45993c2010-12-18 15:13:50 +00002999 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +00003000 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003001 }
3002
3003 slen = sizeof cli_addr;
3004 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
3005 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003006 lwsl_err("getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +00003007 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003008 }
Peter Hinz56885f32011-03-02 22:03:47 +00003009 protocols[context->count_protocols].broadcast_socket_port =
Andy Greenb45993c2010-12-18 15:13:50 +00003010 ntohs(cli_addr.sin_port);
3011 listen(fd, 5);
3012
Andy Green43db0452013-01-10 19:50:35 +08003013 lwsl_debug(" Protocol %s broadcast socket %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00003014 protocols[context->count_protocols].name,
Andy Greenb45993c2010-12-18 15:13:50 +00003015 ntohs(cli_addr.sin_port));
3016
Andy Green0d338332011-02-12 11:57:43 +00003017 /* dummy wsi per broadcast proxy socket */
3018
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003019 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08003020 if (wsi == NULL) {
3021 lwsl_err("Out of mem\n");
3022 close(fd);
3023 return NULL;
3024 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003025 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00003026 wsi->sock = fd;
3027 wsi->mode = LWS_CONNMODE_BROADCAST_PROXY_LISTENER;
Andy Greend6e09112011-03-05 16:12:15 +00003028 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00003029 /* note which protocol we are proxying */
Peter Hinz56885f32011-03-02 22:03:47 +00003030 wsi->protocol_index_for_broadcast_proxy =
3031 context->count_protocols;
3032 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00003033
3034 /* list in internal poll array */
3035
Peter Hinz56885f32011-03-02 22:03:47 +00003036 context->fds[context->fds_count].fd = fd;
3037 context->fds[context->fds_count].events = POLLIN;
3038 context->fds[context->fds_count].revents = 0;
3039 context->fds_count++;
Andy Green3221f922011-02-12 13:14:11 +00003040
3041 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00003042 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00003043 LWS_CALLBACK_ADD_POLL_FD,
3044 (void *)(long)fd, NULL, POLLIN);
Andy Greenb45993c2010-12-18 15:13:50 +00003045 }
3046
Andy Greena41314f2011-05-23 10:00:03 +01003047 /*
3048 * give all extensions a chance to create any per-context
3049 * allocations they need
3050 */
3051
3052 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
3053 if (port)
3054 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
Andrew Chambersd5512172012-05-20 08:17:09 +08003055
3056 if (extensions) {
3057 while (extensions->callback) {
Andy Green43db0452013-01-10 19:50:35 +08003058 lwsl_ext(" Extension: %s\n", extensions->name);
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003059 extensions->callback(context, extensions, NULL,
3060 (enum libwebsocket_extension_callback_reasons)m,
3061 NULL, NULL, 0);
Andrew Chambersd5512172012-05-20 08:17:09 +08003062 extensions++;
3063 }
Andy Greena41314f2011-05-23 10:00:03 +01003064 }
3065
Peter Hinz56885f32011-03-02 22:03:47 +00003066 return context;
Andy Greene92cd172011-01-19 13:11:55 +00003067}
Andy Greenb45993c2010-12-18 15:13:50 +00003068
Andy Green4739e5c2011-01-22 12:51:57 +00003069
Andy Greened11a022011-01-20 10:23:50 +00003070#ifndef LWS_NO_FORK
3071
Andy Greene92cd172011-01-19 13:11:55 +00003072/**
3073 * libwebsockets_fork_service_loop() - Optional helper function forks off
3074 * a process for the websocket server loop.
Andy Green6964bb52011-01-23 16:50:33 +00003075 * You don't have to use this but if not, you
3076 * have to make sure you are calling
3077 * libwebsocket_service periodically to service
3078 * the websocket traffic
Peter Hinz56885f32011-03-02 22:03:47 +00003079 * @context: server context returned by creation function
Andy Greene92cd172011-01-19 13:11:55 +00003080 */
Andy Greenb45993c2010-12-18 15:13:50 +00003081
Andy Greene92cd172011-01-19 13:11:55 +00003082int
Peter Hinz56885f32011-03-02 22:03:47 +00003083libwebsockets_fork_service_loop(struct libwebsocket_context *context)
Andy Greene92cd172011-01-19 13:11:55 +00003084{
Andy Greene92cd172011-01-19 13:11:55 +00003085 int fd;
3086 struct sockaddr_in cli_addr;
3087 int n;
Andy Green3221f922011-02-12 13:14:11 +00003088 int p;
Andy Greenb45993c2010-12-18 15:13:50 +00003089
Andy Greened11a022011-01-20 10:23:50 +00003090 n = fork();
3091 if (n < 0)
3092 return n;
3093
3094 if (!n) {
3095
3096 /* main process context */
3097
Andy Green3221f922011-02-12 13:14:11 +00003098 /*
3099 * set up the proxy sockets to allow broadcast from
3100 * service process context
3101 */
3102
Peter Hinz56885f32011-03-02 22:03:47 +00003103 for (p = 0; p < context->count_protocols; p++) {
Andy Greened11a022011-01-20 10:23:50 +00003104 fd = socket(AF_INET, SOCK_STREAM, 0);
3105 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003106 lwsl_err("Unable to create socket\n");
Andy Greened11a022011-01-20 10:23:50 +00003107 return -1;
3108 }
3109 cli_addr.sin_family = AF_INET;
3110 cli_addr.sin_port = htons(
Peter Hinz56885f32011-03-02 22:03:47 +00003111 context->protocols[p].broadcast_socket_port);
Andy Greened11a022011-01-20 10:23:50 +00003112 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3113 n = connect(fd, (struct sockaddr *)&cli_addr,
3114 sizeof cli_addr);
3115 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003116 lwsl_err("Unable to connect to "
Andy Greened11a022011-01-20 10:23:50 +00003117 "broadcast socket %d, %s\n",
Andy Green3221f922011-02-12 13:14:11 +00003118 n, strerror(errno));
Andy Greened11a022011-01-20 10:23:50 +00003119 return -1;
3120 }
3121
Peter Hinz56885f32011-03-02 22:03:47 +00003122 context->protocols[p].broadcast_socket_user_fd = fd;
Andy Greened11a022011-01-20 10:23:50 +00003123 }
3124
Andy Greene92cd172011-01-19 13:11:55 +00003125 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00003126 }
3127
Artem Baguinski91531662011-12-14 22:14:03 +01003128#ifdef HAVE_SYS_PRCTL_H
Andy Greenb45993c2010-12-18 15:13:50 +00003129 /* we want a SIGHUP when our parent goes down */
3130 prctl(PR_SET_PDEATHSIG, SIGHUP);
Artem Baguinski91531662011-12-14 22:14:03 +01003131#endif
Andy Greenb45993c2010-12-18 15:13:50 +00003132
3133 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +00003134
Artem Baguinski91531662011-12-14 22:14:03 +01003135 while (1) {
Peter Hinz56885f32011-03-02 22:03:47 +00003136 if (libwebsocket_service(context, 1000))
Andy Green3928f612012-07-20 12:58:38 +08003137 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003138//#ifndef HAVE_SYS_PRCTL_H
Artem Baguinski91531662011-12-14 22:14:03 +01003139/*
3140 * on systems without prctl() (i.e. anything but linux) we can notice that our
3141 * parent is dead if getppid() returns 1. FIXME apparently this is not true for
3142 * solaris, could remember ppid right after fork and wait for it to change.
3143 */
3144
3145 if (getppid() == 1)
3146 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003147//#endif
Artem Baguinski91531662011-12-14 22:14:03 +01003148 }
3149
Andy Green8f037e42010-12-19 22:13:26 +00003150
Andy Green3928f612012-07-20 12:58:38 +08003151 return 1;
Andy Greenff95d7a2010-10-28 22:36:01 +01003152}
3153
Andy Greened11a022011-01-20 10:23:50 +00003154#endif
3155
Andy Greenb45993c2010-12-18 15:13:50 +00003156/**
3157 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +00003158 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +00003159 * @wsi: pointer to struct websocket you want to know the protocol of
3160 *
Andy Green8f037e42010-12-19 22:13:26 +00003161 *
3162 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +00003163 * the callback.
3164 */
Andy Greenab990e42010-10-31 12:42:52 +00003165
Andy Greenb45993c2010-12-18 15:13:50 +00003166const struct libwebsocket_protocols *
3167libwebsockets_get_protocol(struct libwebsocket *wsi)
3168{
3169 return wsi->protocol;
3170}
3171
3172/**
Andy Greene92cd172011-01-19 13:11:55 +00003173 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +00003174 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +00003175 * @protocol: pointer to the protocol you will broadcast to all members of
3176 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +00003177 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
3178 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
3179 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +00003180 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +00003181 *
3182 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +00003183 * the given protocol. It does not send the data directly; instead it calls
3184 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
3185 * wants to actually send the data for that connection, the callback itself
3186 * should call libwebsocket_write().
3187 *
3188 * libwebsockets_broadcast() can be called from another fork context without
3189 * having to take any care about data visibility between the processes, it'll
3190 * "just work".
3191 */
3192
3193
3194int
Andy Green8f037e42010-12-19 22:13:26 +00003195libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +00003196 unsigned char *buf, size_t len)
3197{
Peter Hinz56885f32011-03-02 22:03:47 +00003198 struct libwebsocket_context *context = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +00003199 int n;
Andy Green0d338332011-02-12 11:57:43 +00003200 int m;
Andy Green6ee372f2012-04-09 15:09:01 +08003201 struct libwebsocket *wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00003202
3203 if (!protocol->broadcast_socket_user_fd) {
3204 /*
Andy Greene92cd172011-01-19 13:11:55 +00003205 * We are either running unforked / flat, or we are being
3206 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +00003207 * eg, from a callback. In that case don't use sockets for
3208 * broadcast IPC (since we can't open a socket connection to
3209 * a socket listening on our own thread) but directly do the
3210 * send action.
3211 *
3212 * Locking is not needed because we are by definition being
3213 * called in the poll thread context and are serialized.
3214 */
3215
Andy Green0d338332011-02-12 11:57:43 +00003216 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003217
Peter Hinz56885f32011-03-02 22:03:47 +00003218 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003219
Peter Hinz56885f32011-03-02 22:03:47 +00003220 wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00003221
Andy Green0d338332011-02-12 11:57:43 +00003222 if (wsi->mode != LWS_CONNMODE_WS_SERVING)
3223 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00003224
Andy Green0d338332011-02-12 11:57:43 +00003225 /*
3226 * never broadcast to
3227 * non-established connections
3228 */
3229 if (wsi->state != WSI_STATE_ESTABLISHED)
3230 continue;
3231
3232 /* only broadcast to guys using
3233 * requested protocol
3234 */
3235 if (wsi->protocol != protocol)
3236 continue;
3237
Peter Hinz56885f32011-03-02 22:03:47 +00003238 wsi->protocol->callback(context, wsi,
Andy Green8f037e42010-12-19 22:13:26 +00003239 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00003240 wsi->user_space,
Andy Greenb45993c2010-12-18 15:13:50 +00003241 buf, len);
Andy Green0d338332011-02-12 11:57:43 +00003242 }
Andy Greenb45993c2010-12-18 15:13:50 +00003243 }
3244
3245 return 0;
3246 }
3247
Andy Green0ca6a172010-12-19 20:50:01 +00003248 /*
3249 * We're being called from a different process context than the server
3250 * loop. Instead of broadcasting directly, we send our
3251 * payload on a socket to do the IPC; the server process will serialize
3252 * the broadcast action in its main poll() loop.
3253 *
3254 * There's one broadcast socket listening for each protocol supported
3255 * set up when the websocket server initializes
3256 */
3257
Andy Green6964bb52011-01-23 16:50:33 +00003258 n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
Andy Greenb45993c2010-12-18 15:13:50 +00003259
3260 return n;
3261}
Andy Green82c3d542011-03-07 21:16:31 +00003262
3263int
3264libwebsocket_is_final_fragment(struct libwebsocket *wsi)
3265{
3266 return wsi->final;
3267}
Alex Bligh49146db2011-11-07 17:19:25 +08003268
David Galeanoe2cf9922013-01-09 18:06:55 +08003269unsigned char
3270libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
3271{
3272 return wsi->rsv;
3273}
3274
Alex Bligh49146db2011-11-07 17:19:25 +08003275void *
3276libwebsocket_ensure_user_space(struct libwebsocket *wsi)
3277{
3278 /* allocate the per-connection user memory (if any) */
3279
3280 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
3281 wsi->user_space = malloc(
3282 wsi->protocol->per_session_data_size);
3283 if (wsi->user_space == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08003284 lwsl_err("Out of memory for conn user space\n");
Alex Bligh49146db2011-11-07 17:19:25 +08003285 return NULL;
3286 }
Andy Green6ee372f2012-04-09 15:09:01 +08003287 memset(wsi->user_space, 0,
3288 wsi->protocol->per_session_data_size);
Alex Bligh49146db2011-11-07 17:19:25 +08003289 }
3290 return wsi->user_space;
3291}
Andy Green43db0452013-01-10 19:50:35 +08003292
Andy Greende8f27a2013-01-12 09:17:42 +08003293
3294static void lwsl_emit_stderr(const char *line)
3295{
3296 fprintf(stderr, "%s", line);
3297}
3298
Andy Green43db0452013-01-10 19:50:35 +08003299void _lws_log(int filter, const char *format, ...)
3300{
Andy Greende8f27a2013-01-12 09:17:42 +08003301 char buf[256];
Andy Green43db0452013-01-10 19:50:35 +08003302 va_list ap;
3303 int n;
Andy Greende8f27a2013-01-12 09:17:42 +08003304 int pos = 0;
Andy Green8a265092013-01-12 09:25:07 +08003305 struct timeval tv;
Andy Green43db0452013-01-10 19:50:35 +08003306
3307 if (!(log_level & filter))
3308 return;
3309
Andy Green8a265092013-01-12 09:25:07 +08003310 gettimeofday(&tv, NULL);
3311
Andy Green43db0452013-01-10 19:50:35 +08003312 for (n = 0; n < LLL_COUNT; n++)
3313 if (filter == (1 << n)) {
Andy Green8a265092013-01-12 09:25:07 +08003314 pos = sprintf(buf, "[%ld:%04ld] %s: ", tv.tv_sec,
3315 tv.tv_usec / 100, log_level_names[n]);
Andy Green43db0452013-01-10 19:50:35 +08003316 break;
3317 }
3318
3319 va_start(ap, format);
Andy Greende8f27a2013-01-12 09:17:42 +08003320 vsnprintf(buf + pos, (sizeof buf) - pos, format, ap);
3321 buf[(sizeof buf) - 1] = '\0';
3322 va_end(ap);
3323
3324 lwsl_emit(buf);
Andy Green43db0452013-01-10 19:50:35 +08003325}
3326
3327/**
3328 * lws_set_log_level() - Set the logging bitfield
3329 * @level: OR together the LLL_ debug contexts you want output from
Andy Greende8f27a2013-01-12 09:17:42 +08003330 * @log_emit_function: NULL to leave it as it is, or a user-supplied
3331 * function to perform log string emission instead of
3332 * the default stderr one.
Andy Green43db0452013-01-10 19:50:35 +08003333 *
Andy Greende8f27a2013-01-12 09:17:42 +08003334 * log level defaults to "err" and "warn" contexts enabled only and
3335 * emission on stderr.
Andy Green43db0452013-01-10 19:50:35 +08003336 */
3337
Andy Greende8f27a2013-01-12 09:17:42 +08003338void lws_set_log_level(int level, void (*log_emit_function)(const char *line))
Andy Green43db0452013-01-10 19:50:35 +08003339{
3340 log_level = level;
Andy Greende8f27a2013-01-12 09:17:42 +08003341 if (log_emit_function)
3342 lwsl_emit = log_emit_function;
Andy Green43db0452013-01-10 19:50:35 +08003343}