blob: bbbbe4936203dd869daa045674b96358f2004964 [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;
Andy Greend280b6e2013-01-15 13:40:23 +0800773 new_wsi->mode = LWS_CONNMODE_HTTP_SERVING;
Andy Greena41314f2011-05-23 10:00:03 +0100774
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
Andy Green65b0e912013-01-16 07:59:47 +08001537 /*
1538 * deal with listen service piggybacking
1539 * every listen_service_modulo services of other fds, we
1540 * sneak one in to service the listen socket if there's anything waiting
1541 *
1542 * To handle connection storms, as found in ab, if we previously saw a
1543 * pending connection here, it causes us to check again next time.
1544 */
1545
1546 if (context->listen_service_fd && pollfd->fd != context->listen_service_fd) {
1547 context->listen_service_count++;
1548 if (context->listen_service_extraseen ||
1549 context->listen_service_count == context->listen_service_modulo) {
1550 context->listen_service_count = 0;
1551 m = 1;
1552 if (context->listen_service_extraseen > 5)
1553 m = 2;
1554 while (m--) {
1555 /* even with extpoll, we prepared this internal fds for listen */
1556 n = poll(&context->fds[0], 1, 0);
1557 if (n > 0) { /* there's a connection waiting for us */
1558 libwebsocket_service_fd(context, &context->fds[0]);
1559 context->listen_service_extraseen++;
1560 } else {
1561 if (context->listen_service_extraseen)
1562 context->listen_service_extraseen--;
1563 break;
1564 }
1565 }
1566 }
1567
1568 }
1569
1570 /* okay, what we came here to do... */
1571
Peter Hinz56885f32011-03-02 22:03:47 +00001572 wsi = wsi_from_fd(context, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001573
Andy Greend280b6e2013-01-15 13:40:23 +08001574 if (wsi == NULL) {
1575 lwsl_debug("hm fd %d has NULL wsi\n", pollfd->fd);
Andy Greenfa3f4052012-10-07 20:40:35 +08001576 return 0;
Andy Greend280b6e2013-01-15 13:40:23 +08001577 }
Andy Green8f037e42010-12-19 22:13:26 +00001578
Andy Green0d338332011-02-12 11:57:43 +00001579 switch (wsi->mode) {
Andy Greend280b6e2013-01-15 13:40:23 +08001580
1581 case LWS_CONNMODE_HTTP_SERVING:
1582
1583 /* handle http headers coming in */
1584
1585 /* any incoming data ready? */
1586
1587 if (pollfd->revents & POLLIN) {
1588
1589 #ifdef LWS_OPENSSL_SUPPORT
1590 if (wsi->ssl)
1591 len = SSL_read(wsi->ssl, buf, sizeof buf);
1592 else
1593 #endif
1594 len = recv(pollfd->fd, buf, sizeof buf, 0);
1595
1596 if (len < 0) {
1597 lwsl_debug("Socket read returned %d\n", len);
1598 if (errno != EINTR && errno != EAGAIN)
1599 libwebsocket_close_and_free_session(context,
1600 wsi, LWS_CLOSE_STATUS_NOSTATUS);
1601 return 1;
1602 }
1603 if (!len) {
1604 libwebsocket_close_and_free_session(context, wsi,
1605 LWS_CLOSE_STATUS_NOSTATUS);
1606 return 0;
1607 }
1608
1609 n = libwebsocket_read(context, wsi, buf, len);
1610 if (n < 0)
1611 /* we closed wsi */
1612 return 1;
1613 }
1614
1615 /* this handles POLLOUT for http serving fragments */
1616
1617 if (!(pollfd->revents & POLLOUT))
1618 break;
1619
1620 /* one shot */
1621 pollfd->events &= ~POLLOUT;
1622
1623 if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE)
1624 break;
1625
1626 if (libwebsockets_serve_http_file_fragment(context, wsi) < 0)
1627 libwebsocket_close_and_free_session(context, wsi,
1628 LWS_CLOSE_STATUS_NOSTATUS);
1629 else
1630 if (wsi->state == WSI_STATE_HTTP && wsi->protocol->callback)
1631 if (wsi->protocol->callback(context, wsi, LWS_CALLBACK_HTTP_FILE_COMPLETION, wsi->user_space,
1632 wsi->filepath, wsi->filepos))
1633 libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
1634 break;
1635
Andy Green0d338332011-02-12 11:57:43 +00001636 case LWS_CONNMODE_SERVER_LISTENER:
1637
1638 /* pollin means a client has connected to us then */
1639
David Galeanob88e0962013-01-10 09:54:10 +08001640 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001641 break;
1642
David Galeanof7009352011-09-26 12:09:54 +01001643 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001644 lwsl_warn("too busy to accept new client\n");
David Galeanof7009352011-09-26 12:09:54 +01001645 break;
1646 }
1647
Andy Green0d338332011-02-12 11:57:43 +00001648 /* listen socket got an unencrypted connection... */
1649
1650 clilen = sizeof(cli_addr);
1651 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1652 &clilen);
1653 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001654 lwsl_warn("ERROR on accept: %d\n", strerror(errno));
Andy Green3928f612012-07-20 12:58:38 +08001655 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001656 }
1657
Andy Green6c939552011-03-08 08:56:57 +00001658 /* Disable Nagle */
1659 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08001660 setsockopt(accept_fd, IPPROTO_TCP, TCP_NODELAY,
1661 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00001662
Andy Green07034092011-02-13 08:37:12 +00001663 /*
1664 * look at who we connected to and give user code a chance
1665 * to reject based on client IP. There's no protocol selected
1666 * yet so we issue this to protocols[0]
1667 */
1668
Peter Hinz56885f32011-03-02 22:03:47 +00001669 if ((context->protocols[0].callback)(context, wsi,
Andy Green07034092011-02-13 08:37:12 +00001670 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
Andy Green6ee372f2012-04-09 15:09:01 +08001671 (void *)(long)accept_fd, NULL, 0)) {
Andy Green43db0452013-01-10 19:50:35 +08001672 lwsl_debug("Callback denied network connection\n");
Andy Green3fc2c652013-01-14 15:35:02 +08001673 compatible_close(accept_fd);
Andy Green07034092011-02-13 08:37:12 +00001674 break;
1675 }
1676
Andy Greena41314f2011-05-23 10:00:03 +01001677 new_wsi = libwebsocket_create_new_server_wsi(context);
David Galeanoed3c8402013-01-10 10:45:24 +08001678 if (new_wsi == NULL) {
Andy Green3fc2c652013-01-14 15:35:02 +08001679 compatible_close(accept_fd);
Andy Green0d338332011-02-12 11:57:43 +00001680 break;
David Galeanoed3c8402013-01-10 10:45:24 +08001681 }
Andy Green0d338332011-02-12 11:57:43 +00001682
Andy Green0d338332011-02-12 11:57:43 +00001683 new_wsi->sock = accept_fd;
Andy Greena41314f2011-05-23 10:00:03 +01001684
Andy Green0d338332011-02-12 11:57:43 +00001685
1686#ifdef LWS_OPENSSL_SUPPORT
1687 new_wsi->ssl = NULL;
Andy Green0d338332011-02-12 11:57:43 +00001688
Peter Hinz56885f32011-03-02 22:03:47 +00001689 if (context->use_ssl) {
Andy Green0d338332011-02-12 11:57:43 +00001690
Peter Hinz56885f32011-03-02 22:03:47 +00001691 new_wsi->ssl = SSL_new(context->ssl_ctx);
Andy Green0d338332011-02-12 11:57:43 +00001692 if (new_wsi->ssl == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08001693 lwsl_err("SSL_new failed: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001694 ERR_error_string(SSL_get_error(
1695 new_wsi->ssl, 0), NULL));
Andy Green1f9bf522011-02-14 21:14:37 +00001696 libwebsockets_decode_ssl_error();
Andy Green0d338332011-02-12 11:57:43 +00001697 free(new_wsi);
Andy Green3fc2c652013-01-14 15:35:02 +08001698 compatible_close(accept_fd);
Andy Green0d338332011-02-12 11:57:43 +00001699 break;
1700 }
1701
Larry Hayes455d1fe2013-01-15 01:03:58 +08001702 SSL_set_ex_data(new_wsi->ssl,
1703 openssl_websocket_private_data_index, context);
1704
Andy Green0d338332011-02-12 11:57:43 +00001705 SSL_set_fd(new_wsi->ssl, accept_fd);
1706
1707 n = SSL_accept(new_wsi->ssl);
1708 if (n != 1) {
1709 /*
1710 * browsers seem to probe with various
1711 * ssl params which fail then retry
1712 * and succeed
1713 */
Andy Green43db0452013-01-10 19:50:35 +08001714 lwsl_debug("SSL_accept failed skt %u: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001715 pollfd->fd,
1716 ERR_error_string(SSL_get_error(
1717 new_wsi->ssl, n), NULL));
1718 SSL_free(
1719 new_wsi->ssl);
1720 free(new_wsi);
Andy Green3fc2c652013-01-14 15:35:02 +08001721 compatible_close(accept_fd);
Andy Green0d338332011-02-12 11:57:43 +00001722 break;
1723 }
Andy Green6ee372f2012-04-09 15:09:01 +08001724
Andy Green43db0452013-01-10 19:50:35 +08001725 lwsl_debug("accepted new SSL conn "
Andy Green0d338332011-02-12 11:57:43 +00001726 "port %u on fd=%d SSL ver %s\n",
1727 ntohs(cli_addr.sin_port), accept_fd,
1728 SSL_get_version(new_wsi->ssl));
1729
1730 } else
1731#endif
Andy Green43db0452013-01-10 19:50:35 +08001732 lwsl_debug("accepted new conn port %u on fd=%d\n",
Andy Green0d338332011-02-12 11:57:43 +00001733 ntohs(cli_addr.sin_port), accept_fd);
1734
Peter Hinz56885f32011-03-02 22:03:47 +00001735 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001736
Andy Green0d338332011-02-12 11:57:43 +00001737 /*
1738 * make sure NO events are seen yet on this new socket
1739 * (otherwise we inherit old fds[client].revents from
1740 * previous socket there and die mysteriously! )
1741 */
Peter Hinz56885f32011-03-02 22:03:47 +00001742 context->fds[context->fds_count].revents = 0;
Andy Green0d338332011-02-12 11:57:43 +00001743
Peter Hinz56885f32011-03-02 22:03:47 +00001744 context->fds[context->fds_count].events = POLLIN;
1745 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001746
Andy Green3221f922011-02-12 13:14:11 +00001747 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001748 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001749 LWS_CALLBACK_ADD_POLL_FD,
1750 (void *)(long)accept_fd, NULL, POLLIN);
1751
Andy Green0d338332011-02-12 11:57:43 +00001752 break;
1753
1754 case LWS_CONNMODE_BROADCAST_PROXY_LISTENER:
1755
1756 /* as we are listening, POLLIN means accept() is needed */
Andy Green6ee372f2012-04-09 15:09:01 +08001757
David Galeanob88e0962013-01-10 09:54:10 +08001758 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001759 break;
1760
1761 /* listen socket got an unencrypted connection... */
1762
1763 clilen = sizeof(cli_addr);
1764 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1765 &clilen);
1766 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001767 lwsl_warn("ERROR on accept %d\n", accept_fd);
Andy Green3928f612012-07-20 12:58:38 +08001768 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001769 }
1770
Peter Hinz56885f32011-03-02 22:03:47 +00001771 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001772 lwsl_err("too busy to accept new broadcast "
Andy Green3221f922011-02-12 13:14:11 +00001773 "proxy client\n");
Andy Green41c58032013-01-12 13:21:08 +08001774 goto bail_prox_listener;
Andy Green0d338332011-02-12 11:57:43 +00001775 }
1776
1777 /* create a dummy wsi for the connection and add it */
1778
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001779 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08001780 if (new_wsi == NULL) {
1781 lwsl_err("Out of mem\n");
1782 goto bail_prox_listener;
1783 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001784 memset(new_wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00001785 new_wsi->sock = accept_fd;
1786 new_wsi->mode = LWS_CONNMODE_BROADCAST_PROXY;
1787 new_wsi->state = WSI_STATE_ESTABLISHED;
Andy Greend6e09112011-03-05 16:12:15 +00001788 new_wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00001789 /* note which protocol we are proxying */
1790 new_wsi->protocol_index_for_broadcast_proxy =
1791 wsi->protocol_index_for_broadcast_proxy;
Peter Hinz56885f32011-03-02 22:03:47 +00001792 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001793
1794 /* add connected socket to internal poll array */
1795
Peter Hinz56885f32011-03-02 22:03:47 +00001796 context->fds[context->fds_count].revents = 0;
1797 context->fds[context->fds_count].events = POLLIN;
1798 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001799
Andy Green3221f922011-02-12 13:14:11 +00001800 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001801 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001802 LWS_CALLBACK_ADD_POLL_FD,
1803 (void *)(long)accept_fd, NULL, POLLIN);
1804
Andy Green0d338332011-02-12 11:57:43 +00001805 break;
1806
Andy Green41c58032013-01-12 13:21:08 +08001807bail_prox_listener:
Andy Green3fc2c652013-01-14 15:35:02 +08001808 compatible_close(accept_fd);
Andy Green41c58032013-01-12 13:21:08 +08001809 break;
1810
Andy Green0d338332011-02-12 11:57:43 +00001811 case LWS_CONNMODE_BROADCAST_PROXY:
Andy Green8f037e42010-12-19 22:13:26 +00001812
Andy Greenb45993c2010-12-18 15:13:50 +00001813 /* handle session socket closed */
Andy Green8f037e42010-12-19 22:13:26 +00001814
Andy Green0d338332011-02-12 11:57:43 +00001815 if (pollfd->revents & (POLLERR | POLLHUP)) {
Andy Green8f037e42010-12-19 22:13:26 +00001816
Andy Green43db0452013-01-10 19:50:35 +08001817 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Timothy J Fontaineb86d64e2011-02-14 17:55:27 +00001818 (void *)wsi, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001819
Peter Hinz56885f32011-03-02 22:03:47 +00001820 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001821 LWS_CLOSE_STATUS_NORMAL);
Andy Green4b6fbe12011-02-14 08:03:48 +00001822 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00001823 }
Andy Green8f037e42010-12-19 22:13:26 +00001824
Andy Green3b84c002011-03-06 13:14:42 +00001825 /*
1826 * either extension code with stuff to spill, or the user code,
1827 * requested a callback when it was OK to write
1828 */
Andy Green90c7cbc2011-01-27 06:26:52 +00001829
Andy Green3b84c002011-03-06 13:14:42 +00001830 if (pollfd->revents & POLLOUT)
Andy Green6ee372f2012-04-09 15:09:01 +08001831 if (lws_handle_POLLOUT_event(context, wsi,
1832 pollfd) < 0) {
1833 libwebsocket_close_and_free_session(
1834 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00001835 return 1;
1836 }
Andy Green90c7cbc2011-01-27 06:26:52 +00001837
Andy Greenb45993c2010-12-18 15:13:50 +00001838 /* any incoming data ready? */
1839
Andy Green0d338332011-02-12 11:57:43 +00001840 if (!(pollfd->revents & POLLIN))
1841 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001842
Andy Green0d338332011-02-12 11:57:43 +00001843 /* get the issued broadcast payload from the socket */
Andy Greenb45993c2010-12-18 15:13:50 +00001844
Andy Green0d338332011-02-12 11:57:43 +00001845 len = read(pollfd->fd, buf + LWS_SEND_BUFFER_PRE_PADDING,
1846 MAX_BROADCAST_PAYLOAD);
1847 if (len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001848 lwsl_err("Error reading broadcast payload\n");
Andy Green4b6fbe12011-02-14 08:03:48 +00001849 break;
Andy Green0d338332011-02-12 11:57:43 +00001850 }
Andy Greenb45993c2010-12-18 15:13:50 +00001851
Andy Green0d338332011-02-12 11:57:43 +00001852 /* broadcast it to all guys with this protocol index */
Andy Green8f037e42010-12-19 22:13:26 +00001853
Andy Green0d338332011-02-12 11:57:43 +00001854 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Green8f037e42010-12-19 22:13:26 +00001855
Peter Hinz56885f32011-03-02 22:03:47 +00001856 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00001857
Peter Hinz56885f32011-03-02 22:03:47 +00001858 new_wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00001859
Andy Green0d338332011-02-12 11:57:43 +00001860 /* only to clients we are serving to */
Andy Greenb45993c2010-12-18 15:13:50 +00001861
Andy Green0d338332011-02-12 11:57:43 +00001862 if (new_wsi->mode != LWS_CONNMODE_WS_SERVING)
Andy Greenb45993c2010-12-18 15:13:50 +00001863 continue;
1864
1865 /*
1866 * never broadcast to non-established
1867 * connection
1868 */
1869
Andy Green0d338332011-02-12 11:57:43 +00001870 if (new_wsi->state != WSI_STATE_ESTABLISHED)
Andy Green4739e5c2011-01-22 12:51:57 +00001871 continue;
1872
Andy Greenb45993c2010-12-18 15:13:50 +00001873 /*
1874 * only broadcast to connections using
1875 * the requested protocol
1876 */
1877
Andy Green0d338332011-02-12 11:57:43 +00001878 if (new_wsi->protocol->protocol_index !=
1879 wsi->protocol_index_for_broadcast_proxy)
Andy Greenb45993c2010-12-18 15:13:50 +00001880 continue;
1881
Andy Green8f037e42010-12-19 22:13:26 +00001882 /* broadcast it to this connection */
1883
Peter Hinz56885f32011-03-02 22:03:47 +00001884 new_wsi->protocol->callback(context, new_wsi,
Andy Green8f037e42010-12-19 22:13:26 +00001885 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00001886 new_wsi->user_space,
Andy Green0ca6a172010-12-19 20:50:01 +00001887 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
Andy Greenb45993c2010-12-18 15:13:50 +00001888 }
Andy Green0d338332011-02-12 11:57:43 +00001889 }
1890 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001891
Andy Greenbe93fef2011-02-14 20:25:43 +00001892 case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
1893
1894 /* handle proxy hung up on us */
1895
1896 if (pollfd->revents & (POLLERR | POLLHUP)) {
1897
Andy Green43db0452013-01-10 19:50:35 +08001898 lwsl_warn("Proxy connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00001899 (void *)wsi, pollfd->fd);
1900
Peter Hinz56885f32011-03-02 22:03:47 +00001901 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001902 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001903 return 1;
1904 }
1905
Andy Green72c34322011-04-16 10:46:21 +01001906 n = recv(wsi->sock, pkt, sizeof pkt, 0);
Andy Greenbe93fef2011-02-14 20:25:43 +00001907 if (n < 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001908 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001909 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001910 lwsl_err("ERROR reading from proxy socket\n");
Andy Greenbe93fef2011-02-14 20:25:43 +00001911 return 1;
1912 }
1913
1914 pkt[13] = '\0';
1915 if (strcmp(pkt, "HTTP/1.0 200 ") != 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001916 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001917 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001918 lwsl_err("ERROR from proxy: %s\n", pkt);
Andy Greenbe93fef2011-02-14 20:25:43 +00001919 return 1;
1920 }
1921
1922 /* clear his proxy connection timeout */
1923
1924 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1925
1926 /* fallthru */
1927
1928 case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
1929
Andy Green73abc252013-01-13 11:05:30 +08001930 /*
1931 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
1932 * timeout protection set in client-handshake.c
1933 */
1934
Andy Greenbe93fef2011-02-14 20:25:43 +00001935 #ifdef LWS_OPENSSL_SUPPORT
Andy Green73abc252013-01-13 11:05:30 +08001936
1937 /*
1938 * take care of our libwebsocket_callback_on_writable
1939 * happening at a time when there's no real connection yet
1940 */
1941
1942 pollfd->events &= ~POLLOUT;
1943
1944 /* external POLL support via protocol 0 */
1945 context->protocols[0].callback(context, wsi,
1946 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
1947 (void *)(long)wsi->sock, NULL, POLLOUT);
1948
1949 /* we can retry this... so just cook the SSL BIO the first time */
1950
Ken Atherton8360a472012-05-03 11:45:04 +08001951 if (wsi->use_ssl && !wsi->ssl) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001952
Peter Hinz56885f32011-03-02 22:03:47 +00001953 wsi->ssl = SSL_new(context->ssl_client_ctx);
1954 wsi->client_bio = BIO_new_socket(wsi->sock,
1955 BIO_NOCLOSE);
Andy Greenbe93fef2011-02-14 20:25:43 +00001956 SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
1957
Andy Green6901cb32011-02-21 08:06:47 +00001958 SSL_set_ex_data(wsi->ssl,
Andy Green2e24da02011-03-05 16:12:04 +00001959 openssl_websocket_private_data_index,
Peter Hinz56885f32011-03-02 22:03:47 +00001960 context);
Ken Atherton8360a472012-05-03 11:45:04 +08001961 }
Andy Green6901cb32011-02-21 08:06:47 +00001962
Ken Atherton8360a472012-05-03 11:45:04 +08001963 if (wsi->use_ssl) {
Andy Green73abc252013-01-13 11:05:30 +08001964 n = SSL_connect(wsi->ssl);
Ken Atherton8360a472012-05-03 11:45:04 +08001965
Andy Green73abc252013-01-13 11:05:30 +08001966 if (n < 0) {
1967 n = SSL_get_error(wsi->ssl, n);
1968
1969 if (n == SSL_ERROR_WANT_READ ||
1970 n == SSL_ERROR_WANT_WRITE) {
1971 /*
1972 * wants us to retry connect due to state of the
1973 * underlying ssl layer... but since it may be
1974 * stalled on blocked write, no incoming data may
1975 * arrive to trigger the retry. Force (possibly
1976 * many if the SSL state persists in returning the
1977 * condition code, but other sockets are getting
1978 * serviced inbetweentimes) us to get called back
1979 * when writable.
1980 */
1981
1982 lwsl_info("SSL_connect -> SSL_ERROR_WANT_... retrying\n");
1983 libwebsocket_callback_on_writable(context, wsi);
1984
1985 return 0; /* no error */
1986 }
1987 n = -1;
1988 }
1989
1990 if (n <= 0) {
Ken Atherton8360a472012-05-03 11:45:04 +08001991 /*
1992 * retry if new data comes until we
1993 * run into the connection timeout or win
1994 */
1995
Andy Green43db0452013-01-10 19:50:35 +08001996 lwsl_err("SSL connect error %s\n",
Andy Green687b0182011-02-26 11:04:01 +00001997 ERR_error_string(ERR_get_error(),
1998 ssl_err_buf));
Ken Atherton8360a472012-05-03 11:45:04 +08001999 return 0;
Andy Greenbe93fef2011-02-14 20:25:43 +00002000 }
2001
2002 n = SSL_get_verify_result(wsi->ssl);
Andy Green2e24da02011-03-05 16:12:04 +00002003 if ((n != X509_V_OK) && (
Andy Green687b0182011-02-26 11:04:01 +00002004 n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
2005 wsi->use_ssl != 2)) {
Andy Greenbe93fef2011-02-14 20:25:43 +00002006
Andy Green43db0452013-01-10 19:50:35 +08002007 lwsl_err("server's cert didn't "
Andy Green687b0182011-02-26 11:04:01 +00002008 "look good %d\n", n);
Peter Hinz56885f32011-03-02 22:03:47 +00002009 libwebsocket_close_and_free_session(context,
2010 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Green687b0182011-02-26 11:04:01 +00002011 return 1;
Andy Greenbe93fef2011-02-14 20:25:43 +00002012 }
Ken Atherton8360a472012-05-03 11:45:04 +08002013 } else
Andy Greenbe93fef2011-02-14 20:25:43 +00002014 wsi->ssl = NULL;
2015 #endif
2016
Andy Greena41314f2011-05-23 10:00:03 +01002017 p = libwebsockets_generate_client_handshake(context, wsi, p);
Andy Green6ee372f2012-04-09 15:09:01 +08002018 if (p == NULL)
Andy Greenbe93fef2011-02-14 20:25:43 +00002019 return 1;
Andy Greeneeaacb32011-03-01 20:44:24 +00002020
Andy Greenbe93fef2011-02-14 20:25:43 +00002021 /* send our request to the server */
2022
2023 #ifdef LWS_OPENSSL_SUPPORT
2024 if (wsi->use_ssl)
2025 n = SSL_write(wsi->ssl, pkt, p - pkt);
2026 else
2027 #endif
2028 n = send(wsi->sock, pkt, p - pkt, 0);
2029
2030 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002031 lwsl_debug("ERROR writing to client socket\n");
Peter Hinz56885f32011-03-02 22:03:47 +00002032 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002033 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00002034 return 1;
2035 }
2036
2037 wsi->parser_state = WSI_TOKEN_NAME_PART;
2038 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
2039 libwebsocket_set_timeout(wsi,
David Galeanoc9f1ff82013-01-09 18:01:23 +08002040 PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, AWAITING_TIMEOUT);
Andy Greenbe93fef2011-02-14 20:25:43 +00002041
2042 break;
2043
2044 case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
2045
2046 /* handle server hung up on us */
2047
2048 if (pollfd->revents & (POLLERR | POLLHUP)) {
2049
Andy Green43db0452013-01-10 19:50:35 +08002050 lwsl_debug("Server connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00002051 (void *)wsi, pollfd->fd);
2052
2053 goto bail3;
2054 }
2055
2056
2057 /* interpret the server response */
2058
2059 /*
2060 * HTTP/1.1 101 Switching Protocols
2061 * Upgrade: websocket
2062 * Connection: Upgrade
2063 * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
2064 * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
2065 * Sec-WebSocket-Protocol: chat
2066 */
2067
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08002068 /*
2069 * we have to take some care here to only take from the
2070 * socket bytewise. The browser may (and has been seen to
2071 * in the case that onopen() performs websocket traffic)
2072 * coalesce both handshake response and websocket traffic
2073 * in one packet, since at that point the connection is
2074 * definitively ready from browser pov.
2075 */
Andy Greenbe93fef2011-02-14 20:25:43 +00002076
Andy Green7b5af9a2012-04-09 15:23:47 +08002077 len = 1;
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08002078 while (wsi->parser_state != WSI_PARSING_COMPLETE && len > 0) {
2079#ifdef LWS_OPENSSL_SUPPORT
2080 if (wsi->use_ssl)
2081 len = SSL_read(wsi->ssl, &c, 1);
2082 else
2083#endif
2084 len = recv(wsi->sock, &c, 1, 0);
2085
2086 libwebsocket_parse(wsi, c);
Andy Greenbe93fef2011-02-14 20:25:43 +00002087 }
2088
Andy Green27a0b912011-04-16 10:54:28 +01002089 /*
Andy Green6ee372f2012-04-09 15:09:01 +08002090 * hs may also be coming in multiple packets, there is a 5-sec
Andy Green27a0b912011-04-16 10:54:28 +01002091 * libwebsocket timeout still active here too, so if parsing did
2092 * not complete just wait for next packet coming in this state
2093 */
2094
2095 if (wsi->parser_state != WSI_PARSING_COMPLETE)
2096 break;
Andy Greenbe93fef2011-02-14 20:25:43 +00002097
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08002098 /*
2099 * otherwise deal with the handshake. If there's any
2100 * packet traffic already arrived we'll trigger poll() again
2101 * right away and deal with it that way
2102 */
2103
Andy Greena41314f2011-05-23 10:00:03 +01002104 return lws_client_interpret_server_handshake(context, wsi);
Andy Greenbe93fef2011-02-14 20:25:43 +00002105
2106bail3:
2107 if (wsi->c_protocol)
2108 free(wsi->c_protocol);
Peter Hinz56885f32011-03-02 22:03:47 +00002109 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002110 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00002111 return 1;
Andy Greena41314f2011-05-23 10:00:03 +01002112
2113 case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
Andy Green43db0452013-01-10 19:50:35 +08002114 lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
Andy Greena41314f2011-05-23 10:00:03 +01002115 break;
2116
2117 case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
Andy Green43db0452013-01-10 19:50:35 +08002118 lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
Andy Greena41314f2011-05-23 10:00:03 +01002119 break;
2120
Andy Greenbe93fef2011-02-14 20:25:43 +00002121
Andy Green0d338332011-02-12 11:57:43 +00002122 case LWS_CONNMODE_WS_SERVING:
2123 case LWS_CONNMODE_WS_CLIENT:
2124
2125 /* handle session socket closed */
2126
2127 if (pollfd->revents & (POLLERR | POLLHUP)) {
2128
Andy Green43db0452013-01-10 19:50:35 +08002129 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Andy Green0d338332011-02-12 11:57:43 +00002130 (void *)wsi, pollfd->fd);
2131
Peter Hinz56885f32011-03-02 22:03:47 +00002132 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002133 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green4b6fbe12011-02-14 08:03:48 +00002134 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002135 }
2136
Andy Green0d338332011-02-12 11:57:43 +00002137 /* the guy requested a callback when it was OK to write */
2138
Andy Greenda527df2011-03-07 07:08:12 +00002139 if ((pollfd->revents & POLLOUT) &&
2140 wsi->state == WSI_STATE_ESTABLISHED)
2141 if (lws_handle_POLLOUT_event(context, wsi,
2142 pollfd) < 0) {
2143 libwebsocket_close_and_free_session(
2144 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00002145 return 1;
2146 }
Andy Green0d338332011-02-12 11:57:43 +00002147
Andy Green0d338332011-02-12 11:57:43 +00002148
2149 /* any incoming data ready? */
2150
2151 if (!(pollfd->revents & POLLIN))
2152 break;
2153
Andy Greenb45993c2010-12-18 15:13:50 +00002154#ifdef LWS_OPENSSL_SUPPORT
David Galeano7ffbe1b2013-01-10 10:35:32 +08002155read_pending:
Andy Green0d338332011-02-12 11:57:43 +00002156 if (wsi->ssl)
Andy Green98a717c2011-03-06 13:14:15 +00002157 eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);
Andy Greenb45993c2010-12-18 15:13:50 +00002158 else
2159#endif
Andy Green98a717c2011-03-06 13:14:15 +00002160 eff_buf.token_len =
Andy Green72c34322011-04-16 10:46:21 +01002161 recv(pollfd->fd, buf, sizeof buf, 0);
Andy Greenb45993c2010-12-18 15:13:50 +00002162
Andy Green98a717c2011-03-06 13:14:15 +00002163 if (eff_buf.token_len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002164 lwsl_debug("Socket read returned %d\n",
Andy Green98a717c2011-03-06 13:14:15 +00002165 eff_buf.token_len);
Alon Levydc93b7f2012-10-19 11:21:57 +02002166 if (errno != EINTR && errno != EAGAIN)
Andy Green6ee372f2012-04-09 15:09:01 +08002167 libwebsocket_close_and_free_session(context,
2168 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Nick Dowellc04c1932012-04-05 10:29:39 +08002169 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002170 }
Andy Green98a717c2011-03-06 13:14:15 +00002171 if (!eff_buf.token_len) {
Peter Hinz56885f32011-03-02 22:03:47 +00002172 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002173 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenfa3f4052012-10-07 20:40:35 +08002174 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00002175 }
2176
Andy Green98a717c2011-03-06 13:14:15 +00002177 /*
2178 * give any active extensions a chance to munge the buffer
2179 * before parse. We pass in a pointer to an lws_tokens struct
2180 * prepared with the default buffer and content length that's in
2181 * there. Rather than rewrite the default buffer, extensions
2182 * that expect to grow the buffer can adapt .token to
2183 * point to their own per-connection buffer in the extension
2184 * user allocation. By default with no extensions or no
2185 * extension callback handling, just the normal input buffer is
2186 * used then so it is efficient.
2187 */
Andy Greenb45993c2010-12-18 15:13:50 +00002188
Andy Green98a717c2011-03-06 13:14:15 +00002189 eff_buf.token = (char *)buf;
Andy Greenb45993c2010-12-18 15:13:50 +00002190
Andy Green98a717c2011-03-06 13:14:15 +00002191 more = 1;
2192 while (more) {
Andy Green0d338332011-02-12 11:57:43 +00002193
Andy Green98a717c2011-03-06 13:14:15 +00002194 more = 0;
2195
2196 for (n = 0; n < wsi->count_active_extensions; n++) {
Andy Green46c2ea02011-03-22 09:04:01 +00002197 m = wsi->active_extensions[n]->callback(context,
2198 wsi->active_extensions[n], wsi,
Andy Green98a717c2011-03-06 13:14:15 +00002199 LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
Andy Green46c2ea02011-03-22 09:04:01 +00002200 wsi->active_extensions_user[n],
2201 &eff_buf, 0);
Andy Green98a717c2011-03-06 13:14:15 +00002202 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002203 lwsl_ext(
Andy Green6ee372f2012-04-09 15:09:01 +08002204 "Extension reports fatal error\n");
2205 libwebsocket_close_and_free_session(
2206 context, wsi,
2207 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green98a717c2011-03-06 13:14:15 +00002208 return 1;
2209 }
2210 if (m)
2211 more = 1;
2212 }
2213
2214 /* service incoming data */
2215
2216 if (eff_buf.token_len) {
2217 n = libwebsocket_read(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002218 (unsigned char *)eff_buf.token,
2219 eff_buf.token_len);
Andy Green98a717c2011-03-06 13:14:15 +00002220 if (n < 0)
2221 /* we closed wsi */
2222 return 1;
2223 }
2224
2225 eff_buf.token = NULL;
2226 eff_buf.token_len = 0;
2227 }
David Galeano7ffbe1b2013-01-10 10:35:32 +08002228
2229#ifdef LWS_OPENSSL_SUPPORT
2230 if (wsi->ssl && SSL_pending(wsi->ssl))
2231 goto read_pending;
2232#endif
Andy Green98a717c2011-03-06 13:14:15 +00002233 break;
Andy Greenb45993c2010-12-18 15:13:50 +00002234 }
2235
2236 return 0;
2237}
2238
Andy Green0d338332011-02-12 11:57:43 +00002239
Andy Green6964bb52011-01-23 16:50:33 +00002240/**
2241 * libwebsocket_context_destroy() - Destroy the websocket context
Peter Hinz56885f32011-03-02 22:03:47 +00002242 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002243 *
2244 * This function closes any active connections and then frees the
2245 * context. After calling this, any further use of the context is
2246 * undefined.
2247 */
2248void
Peter Hinz56885f32011-03-02 22:03:47 +00002249libwebsocket_context_destroy(struct libwebsocket_context *context)
Andy Green6964bb52011-01-23 16:50:33 +00002250{
Andy Green0d338332011-02-12 11:57:43 +00002251 int n;
2252 int m;
2253 struct libwebsocket *wsi;
Andy Greena41314f2011-05-23 10:00:03 +01002254 struct libwebsocket_extension *ext;
Andy Green6964bb52011-01-23 16:50:33 +00002255
Andy Green4b6fbe12011-02-14 08:03:48 +00002256 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002257 for (m = 0; m < context->fd_hashtable[n].length; m++) {
2258 wsi = context->fd_hashtable[n].wsi[m];
2259 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002260 LWS_CLOSE_STATUS_GOINGAWAY);
Andy Greenf3d3b402011-02-09 07:16:34 +00002261 }
Andy Green6964bb52011-01-23 16:50:33 +00002262
Andy Greena41314f2011-05-23 10:00:03 +01002263 /*
2264 * give all extensions a chance to clean up any per-context
2265 * allocations they might have made
2266 */
2267
2268 ext = context->extensions;
2269 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
2270 if (context->listen_port)
2271 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
Paulo Roberto Urio1f680ab2012-06-04 08:40:28 +08002272 while (ext && ext->callback) {
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002273 ext->callback(context, ext, NULL, (enum libwebsocket_extension_callback_reasons)m, NULL, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01002274 ext++;
2275 }
2276
Peter Hinz56885f32011-03-02 22:03:47 +00002277#ifdef WIN32
2278#else
2279 close(context->fd_random);
Andy Green6964bb52011-01-23 16:50:33 +00002280#endif
2281
Peter Hinz56885f32011-03-02 22:03:47 +00002282#ifdef LWS_OPENSSL_SUPPORT
2283 if (context->ssl_ctx)
2284 SSL_CTX_free(context->ssl_ctx);
2285 if (context->ssl_client_ctx)
2286 SSL_CTX_free(context->ssl_client_ctx);
2287#endif
2288
2289 free(context);
2290
2291#ifdef WIN32
2292 WSACleanup();
2293#endif
Andy Green6964bb52011-01-23 16:50:33 +00002294}
2295
Alon Levy0291eb32012-10-19 11:21:56 +02002296LWS_EXTERN void *
2297libwebsocket_context_user(struct libwebsocket_context *context)
2298{
2299 return context->user_space;
2300}
2301
Andy Green6964bb52011-01-23 16:50:33 +00002302/**
2303 * libwebsocket_service() - Service any pending websocket activity
Peter Hinz56885f32011-03-02 22:03:47 +00002304 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002305 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
2306 * service otherwise block and service immediately, returning
2307 * after the timeout if nothing needed service.
2308 *
2309 * This function deals with any pending websocket traffic, for three
2310 * kinds of event. It handles these events on both server and client
2311 * types of connection the same.
2312 *
2313 * 1) Accept new connections to our context's server
2314 *
2315 * 2) Perform pending broadcast writes initiated from other forked
2316 * processes (effectively serializing asynchronous broadcasts)
2317 *
2318 * 3) Call the receive callback for incoming frame data received by
2319 * server or client connections.
2320 *
2321 * You need to call this service function periodically to all the above
2322 * functions to happen; if your application is single-threaded you can
2323 * just call it in your main event loop.
2324 *
2325 * Alternatively you can fork a new process that asynchronously handles
2326 * calling this service in a loop. In that case you are happy if this
2327 * call blocks your thread until it needs to take care of something and
2328 * would call it with a large nonzero timeout. Your loop then takes no
2329 * CPU while there is nothing happening.
2330 *
2331 * If you are calling it in a single-threaded app, you don't want it to
2332 * wait around blocking other things in your loop from happening, so you
2333 * would call it with a timeout_ms of 0, so it returns immediately if
2334 * nothing is pending, or as soon as it services whatever was pending.
2335 */
2336
Andy Greenb45993c2010-12-18 15:13:50 +00002337
Andy Greene92cd172011-01-19 13:11:55 +00002338int
Peter Hinz56885f32011-03-02 22:03:47 +00002339libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
Andy Greene92cd172011-01-19 13:11:55 +00002340{
2341 int n;
Andy Greene92cd172011-01-19 13:11:55 +00002342
2343 /* stay dead once we are dead */
2344
Peter Hinz56885f32011-03-02 22:03:47 +00002345 if (context == NULL)
Andy Greene92cd172011-01-19 13:11:55 +00002346 return 1;
2347
Andy Green0d338332011-02-12 11:57:43 +00002348 /* wait for something to need service */
Andy Green4739e5c2011-01-22 12:51:57 +00002349
Peter Hinz56885f32011-03-02 22:03:47 +00002350 n = poll(context->fds, context->fds_count, timeout_ms);
Andy Green3221f922011-02-12 13:14:11 +00002351 if (n == 0) /* poll timeout */
2352 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002353
Andy Greend280b6e2013-01-15 13:40:23 +08002354
2355
Andy Green62c54d22011-02-14 09:14:25 +00002356 if (n < 0) {
Andy Green5e1fa172011-02-10 09:07:05 +00002357 /*
Andy Green43db0452013-01-10 19:50:35 +08002358 lwsl_err("Listen Socket dead\n");
Andy Green5e1fa172011-02-10 09:07:05 +00002359 */
Andy Green3928f612012-07-20 12:58:38 +08002360 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002361 }
Andy Greene92cd172011-01-19 13:11:55 +00002362
2363 /* handle accept on listening socket? */
2364
Peter Hinz56885f32011-03-02 22:03:47 +00002365 for (n = 0; n < context->fds_count; n++)
2366 if (context->fds[n].revents)
Andy Green3928f612012-07-20 12:58:38 +08002367 if (libwebsocket_service_fd(context,
2368 &context->fds[n]) < 0)
2369 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002370 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002371}
2372
Andy Greena41314f2011-05-23 10:00:03 +01002373int
2374lws_any_extension_handled(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002375 struct libwebsocket *wsi,
2376 enum libwebsocket_extension_callback_reasons r,
Andy Greena41314f2011-05-23 10:00:03 +01002377 void *v, size_t len)
2378{
2379 int n;
2380 int handled = 0;
2381
2382 /* maybe an extension will take care of it for us */
2383
2384 for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
2385 if (!wsi->active_extensions[n]->callback)
2386 continue;
2387
2388 handled |= wsi->active_extensions[n]->callback(context,
2389 wsi->active_extensions[n], wsi,
2390 r, wsi->active_extensions_user[n], v, len);
2391 }
2392
2393 return handled;
2394}
2395
2396
2397void *
2398lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002399 struct libwebsocket_extension *ext)
Andy Greena41314f2011-05-23 10:00:03 +01002400{
2401 int n = 0;
2402
Andy Green68b45042011-05-25 21:41:57 +01002403 if (wsi == NULL)
2404 return NULL;
2405
Andy Greena41314f2011-05-23 10:00:03 +01002406 while (n < wsi->count_active_extensions) {
2407 if (wsi->active_extensions[n] != ext) {
2408 n++;
2409 continue;
2410 }
2411 return wsi->active_extensions_user[n];
2412 }
2413
2414 return NULL;
2415}
2416
Andy Green90c7cbc2011-01-27 06:26:52 +00002417/**
2418 * libwebsocket_callback_on_writable() - Request a callback when this socket
2419 * becomes able to be written to without
2420 * blocking
Andy Green32375b72011-02-19 08:32:53 +00002421 *
Peter Hinz56885f32011-03-02 22:03:47 +00002422 * @context: libwebsockets context
Andy Green90c7cbc2011-01-27 06:26:52 +00002423 * @wsi: Websocket connection instance to get callback for
2424 */
2425
2426int
Peter Hinz56885f32011-03-02 22:03:47 +00002427libwebsocket_callback_on_writable(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002428 struct libwebsocket *wsi)
Andy Green90c7cbc2011-01-27 06:26:52 +00002429{
Andy Green90c7cbc2011-01-27 06:26:52 +00002430 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002431 int handled = 0;
2432
2433 /* maybe an extension will take care of it for us */
2434
2435 for (n = 0; n < wsi->count_active_extensions; n++) {
2436 if (!wsi->active_extensions[n]->callback)
2437 continue;
2438
2439 handled |= wsi->active_extensions[n]->callback(context,
2440 wsi->active_extensions[n], wsi,
2441 LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
2442 wsi->active_extensions_user[n], NULL, 0);
2443 }
2444
2445 if (handled)
2446 return 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002447
Peter Hinz56885f32011-03-02 22:03:47 +00002448 for (n = 0; n < context->fds_count; n++)
2449 if (context->fds[n].fd == wsi->sock) {
2450 context->fds[n].events |= POLLOUT;
Andy Greena41314f2011-05-23 10:00:03 +01002451 n = context->fds_count + 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002452 }
2453
Andy Greena41314f2011-05-23 10:00:03 +01002454 if (n == context->fds_count)
Andy Green43db0452013-01-10 19:50:35 +08002455 lwsl_err("libwebsocket_callback_on_writable: "
Andy Green6ee372f2012-04-09 15:09:01 +08002456 "failed to find socket %d\n", wsi->sock);
Andy Greena41314f2011-05-23 10:00:03 +01002457
Andy Green3221f922011-02-12 13:14:11 +00002458 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002459 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002460 LWS_CALLBACK_SET_MODE_POLL_FD,
2461 (void *)(long)wsi->sock, NULL, POLLOUT);
2462
Andy Green90c7cbc2011-01-27 06:26:52 +00002463 return 1;
2464}
2465
2466/**
2467 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
2468 * all connections using the given protocol when it
2469 * becomes possible to write to each socket without
2470 * blocking in turn.
2471 *
2472 * @protocol: Protocol whose connections will get callbacks
2473 */
2474
2475int
2476libwebsocket_callback_on_writable_all_protocol(
2477 const struct libwebsocket_protocols *protocol)
2478{
Peter Hinz56885f32011-03-02 22:03:47 +00002479 struct libwebsocket_context *context = protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002480 int n;
Andy Green0d338332011-02-12 11:57:43 +00002481 int m;
2482 struct libwebsocket *wsi;
Andy Green90c7cbc2011-01-27 06:26:52 +00002483
Andy Green0d338332011-02-12 11:57:43 +00002484 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
2485
Peter Hinz56885f32011-03-02 22:03:47 +00002486 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Green0d338332011-02-12 11:57:43 +00002487
Peter Hinz56885f32011-03-02 22:03:47 +00002488 wsi = context->fd_hashtable[n].wsi[m];
Andy Green0d338332011-02-12 11:57:43 +00002489
2490 if (wsi->protocol == protocol)
Peter Hinz56885f32011-03-02 22:03:47 +00002491 libwebsocket_callback_on_writable(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002492 }
2493 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002494
2495 return 0;
2496}
2497
Andy Greenbe93fef2011-02-14 20:25:43 +00002498/**
2499 * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
2500 *
2501 * You will not need this unless you are doing something special
2502 *
2503 * @wsi: Websocket connection instance
2504 * @reason: timeout reason
2505 * @secs: how many seconds
2506 */
2507
2508void
2509libwebsocket_set_timeout(struct libwebsocket *wsi,
2510 enum pending_timeout reason, int secs)
2511{
2512 struct timeval tv;
2513
2514 gettimeofday(&tv, NULL);
2515
2516 wsi->pending_timeout_limit = tv.tv_sec + secs;
2517 wsi->pending_timeout = reason;
2518}
2519
Andy Greena6cbece2011-01-27 20:06:03 +00002520
2521/**
2522 * libwebsocket_get_socket_fd() - returns the socket file descriptor
2523 *
2524 * You will not need this unless you are doing something special
2525 *
2526 * @wsi: Websocket connection instance
2527 */
2528
2529int
2530libwebsocket_get_socket_fd(struct libwebsocket *wsi)
2531{
2532 return wsi->sock;
2533}
2534
Andy Green90c7cbc2011-01-27 06:26:52 +00002535/**
2536 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
2537 * receieved packets.
2538 *
2539 * If the output side of a server process becomes choked, this allows flow
2540 * control for the input side.
2541 *
2542 * @wsi: Websocket connection instance to get callback for
2543 * @enable: 0 = disable read servicing for this connection, 1 = enable
2544 */
2545
2546int
2547libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
2548{
Peter Hinz56885f32011-03-02 22:03:47 +00002549 struct libwebsocket_context *context = wsi->protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002550 int n;
2551
Peter Hinz56885f32011-03-02 22:03:47 +00002552 for (n = 0; n < context->fds_count; n++)
2553 if (context->fds[n].fd == wsi->sock) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002554 if (enable)
Peter Hinz56885f32011-03-02 22:03:47 +00002555 context->fds[n].events |= POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002556 else
Peter Hinz56885f32011-03-02 22:03:47 +00002557 context->fds[n].events &= ~POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002558
2559 return 0;
2560 }
2561
Andy Green3221f922011-02-12 13:14:11 +00002562 if (enable)
2563 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002564 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002565 LWS_CALLBACK_SET_MODE_POLL_FD,
2566 (void *)(long)wsi->sock, NULL, POLLIN);
2567 else
2568 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002569 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002570 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
2571 (void *)(long)wsi->sock, NULL, POLLIN);
2572
Andy Greena41314f2011-05-23 10:00:03 +01002573#if 0
Andy Green43db0452013-01-10 19:50:35 +08002574 lwsl_err("libwebsocket_rx_flow_control unable to find socket\n");
Andy Greena41314f2011-05-23 10:00:03 +01002575#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002576 return 1;
2577}
2578
Andy Green2ac5a6f2011-01-28 10:00:18 +00002579/**
2580 * libwebsocket_canonical_hostname() - returns this host's hostname
2581 *
2582 * This is typically used by client code to fill in the host parameter
2583 * when making a client connection. You can only call it after the context
2584 * has been created.
2585 *
Peter Hinz56885f32011-03-02 22:03:47 +00002586 * @context: Websocket context
Andy Green2ac5a6f2011-01-28 10:00:18 +00002587 */
2588
2589
2590extern const char *
Peter Hinz56885f32011-03-02 22:03:47 +00002591libwebsocket_canonical_hostname(struct libwebsocket_context *context)
Andy Green2ac5a6f2011-01-28 10:00:18 +00002592{
Peter Hinz56885f32011-03-02 22:03:47 +00002593 return (const char *)context->canonical_hostname;
Andy Green2ac5a6f2011-01-28 10:00:18 +00002594}
2595
2596
Andy Green90c7cbc2011-01-27 06:26:52 +00002597static void sigpipe_handler(int x)
2598{
2599}
2600
Andy Green6901cb32011-02-21 08:06:47 +00002601#ifdef LWS_OPENSSL_SUPPORT
2602static int
2603OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
2604{
2605
2606 SSL *ssl;
2607 int n;
Andy Green2e24da02011-03-05 16:12:04 +00002608 struct libwebsocket_context *context;
Andy Green6901cb32011-02-21 08:06:47 +00002609
2610 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
2611 SSL_get_ex_data_X509_STORE_CTX_idx());
2612
2613 /*
Andy Green2e24da02011-03-05 16:12:04 +00002614 * !!! nasty openssl requires the index to come as a library-scope
2615 * static
Andy Green6901cb32011-02-21 08:06:47 +00002616 */
Andy Green2e24da02011-03-05 16:12:04 +00002617 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
Andy Green6ee372f2012-04-09 15:09:01 +08002618
Peter Hinz56885f32011-03-02 22:03:47 +00002619 n = context->protocols[0].callback(NULL, NULL,
Andy Green6901cb32011-02-21 08:06:47 +00002620 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
2621 x509_ctx, ssl, preverify_ok);
2622
2623 /* convert return code from 0 = OK to 1 = OK */
2624
2625 if (!n)
2626 n = 1;
2627 else
2628 n = 0;
2629
2630 return n;
2631}
2632#endif
2633
Andy Greenb45993c2010-12-18 15:13:50 +00002634
Andy Greenab990e42010-10-31 12:42:52 +00002635/**
Andy Green4739e5c2011-01-22 12:51:57 +00002636 * libwebsocket_create_context() - Create the websocket handler
2637 * @port: Port to listen on... you can use 0 to suppress listening on
Andy Green6964bb52011-01-23 16:50:33 +00002638 * any port, that's what you want if you are not running a
2639 * websocket server at all but just using it as a client
Peter Hinz56885f32011-03-02 22:03:47 +00002640 * @interf: NULL to bind the listen socket to all interfaces, or the
Andy Green32375b72011-02-19 08:32:53 +00002641 * interface name, eg, "eth2"
Andy Green4f3943a2010-11-12 10:44:16 +00002642 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +00002643 * specific callback for each one. The list is ended with an
2644 * entry that has a NULL callback pointer.
Andy Green6964bb52011-01-23 16:50:33 +00002645 * It's not const because we write the owning_server member
Andy Greenc5114822011-03-06 10:29:35 +00002646 * @extensions: NULL or array of libwebsocket_extension structs listing the
Andy Green6ee372f2012-04-09 15:09:01 +08002647 * extensions this context supports
Andy Green3faa9c72010-11-08 17:03:03 +00002648 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +00002649 * to listen using SSL, set to the filepath to fetch the
2650 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +00002651 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +00002652 * else ignored
David Galeano2f82be82013-01-09 16:25:54 +08002653 * @ssl_ca_filepath: CA certificate filepath or NULL
Andy Green3faa9c72010-11-08 17:03:03 +00002654 * @gid: group id to change to after setting listen socket, or -1.
2655 * @uid: user id to change to after setting listen socket, or -1.
Andy Greenbfb051f2011-02-09 08:49:14 +00002656 * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
Andy Green15e31f32012-10-19 18:36:28 +08002657 * @user: optional user pointer that can be recovered via the context
2658 * pointer using libwebsocket_context_user
Andy Green05464c62010-11-12 10:44:18 +00002659 *
Andy Green8f037e42010-12-19 22:13:26 +00002660 * This function creates the listening socket and takes care
2661 * of all initialization in one step.
2662 *
Andy Greene92cd172011-01-19 13:11:55 +00002663 * After initialization, it returns a struct libwebsocket_context * that
2664 * represents this server. After calling, user code needs to take care
2665 * of calling libwebsocket_service() with the context pointer to get the
2666 * server's sockets serviced. This can be done in the same process context
2667 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +00002668 *
Andy Green8f037e42010-12-19 22:13:26 +00002669 * The protocol callback functions are called for a handful of events
2670 * including http requests coming in, websocket connections becoming
2671 * established, and data arriving; it's also called periodically to allow
2672 * async transmission.
2673 *
2674 * HTTP requests are sent always to the FIRST protocol in @protocol, since
2675 * at that time websocket protocol has not been negotiated. Other
2676 * protocols after the first one never see any HTTP callack activity.
2677 *
2678 * The server created is a simple http server by default; part of the
2679 * websocket standard is upgrading this http connection to a websocket one.
2680 *
2681 * This allows the same server to provide files like scripts and favicon /
2682 * images or whatever over http and dynamic data over websockets all in
2683 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +00002684 */
Andy Green4ea60062010-10-30 12:15:07 +01002685
Andy Greene92cd172011-01-19 13:11:55 +00002686struct libwebsocket_context *
Peter Hinz56885f32011-03-02 22:03:47 +00002687libwebsocket_create_context(int port, const char *interf,
Andy Greenb45993c2010-12-18 15:13:50 +00002688 struct libwebsocket_protocols *protocols,
Andy Greend6e09112011-03-05 16:12:15 +00002689 struct libwebsocket_extension *extensions,
Andy Green8f037e42010-12-19 22:13:26 +00002690 const char *ssl_cert_filepath,
2691 const char *ssl_private_key_filepath,
David Galeano2f82be82013-01-09 16:25:54 +08002692 const char *ssl_ca_filepath,
Alon Levy0291eb32012-10-19 11:21:56 +02002693 int gid, int uid, unsigned int options,
David Galeano2f82be82013-01-09 16:25:54 +08002694 void *user)
Andy Greenff95d7a2010-10-28 22:36:01 +01002695{
2696 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002697 int m;
Andy Green4739e5c2011-01-22 12:51:57 +00002698 int sockfd = 0;
Andy Green251f6fa2010-11-03 11:13:06 +00002699 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +01002700 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +00002701 int opt = 1;
Peter Hinz56885f32011-03-02 22:03:47 +00002702 struct libwebsocket_context *context = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002703 unsigned int slen;
Andy Green9659f372011-01-27 22:01:43 +00002704 char *p;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002705 char hostname[1024] = "";
Andy Greena69f0512012-05-03 12:32:38 +08002706// struct hostent *he;
Andy Green0d338332011-02-12 11:57:43 +00002707 struct libwebsocket *wsi;
Andy Greena69f0512012-05-03 12:32:38 +08002708 struct sockaddr sa;
Andy Greenff95d7a2010-10-28 22:36:01 +01002709
Andy Green3faa9c72010-11-08 17:03:03 +00002710#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +00002711 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +00002712 char ssl_err_buf[512];
Andy Green3faa9c72010-11-08 17:03:03 +00002713#endif
2714
Andy Green43db0452013-01-10 19:50:35 +08002715 lwsl_info("Initial logging level %d\n", log_level);
Andy Greenc0d6b632013-01-12 23:42:17 +08002716 lwsl_info(" FD_HASHTABLE_MODULUS: %u\n", FD_HASHTABLE_MODULUS);
2717 lwsl_info(" MAX_CLIENTS: %u\n", MAX_CLIENTS);
2718 lwsl_info(" LWS_MAX_HEADER_NAME_LENGTH: %u\n", LWS_MAX_HEADER_NAME_LENGTH);
2719 lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
2720 lwsl_info(" LWS_INITIAL_HDR_ALLOC: %u\n", LWS_INITIAL_HDR_ALLOC);
2721 lwsl_info(" LWS_ADDITIONAL_HDR_ALLOC: %u\n", LWS_ADDITIONAL_HDR_ALLOC);
2722 lwsl_info(" MAX_USER_RX_BUFFER: %u\n", MAX_USER_RX_BUFFER);
2723 lwsl_info(" MAX_BROADCAST_PAYLOAD: %u\n", MAX_BROADCAST_PAYLOAD);
2724 lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
2725 lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE);
2726 lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED);
2727 lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT);
2728 lwsl_info(" CIPHERS_LIST_STRING: '%s'\n", CIPHERS_LIST_STRING);
2729 lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
2730 lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER);
Andy Green43db0452013-01-10 19:50:35 +08002731
Peter Hinz56885f32011-03-02 22:03:47 +00002732#ifdef _WIN32
2733 {
2734 WORD wVersionRequested;
2735 WSADATA wsaData;
2736 int err;
Andy Green6ee372f2012-04-09 15:09:01 +08002737 HMODULE wsdll;
Peter Hinz56885f32011-03-02 22:03:47 +00002738
2739 /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
2740 wVersionRequested = MAKEWORD(2, 2);
2741
2742 err = WSAStartup(wVersionRequested, &wsaData);
2743 if (err != 0) {
2744 /* Tell the user that we could not find a usable */
2745 /* Winsock DLL. */
Andy Green43db0452013-01-10 19:50:35 +08002746 lwsl_err("WSAStartup failed with error: %d\n", err);
Peter Hinz56885f32011-03-02 22:03:47 +00002747 return NULL;
2748 }
David Galeano7b11fec2011-10-04 19:55:18 +08002749
Andy Green6ee372f2012-04-09 15:09:01 +08002750 /* default to a poll() made out of select() */
2751 poll = emulated_poll;
David Galeano7b11fec2011-10-04 19:55:18 +08002752
Andy Green6ee372f2012-04-09 15:09:01 +08002753 /* if windows socket lib available, use his WSAPoll */
David Galeanocb193682013-01-09 15:29:00 +08002754 wsdll = GetModuleHandle(_T("Ws2_32.dll"));
Andy Green6ee372f2012-04-09 15:09:01 +08002755 if (wsdll)
2756 poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
Peter Hinz56885f32011-03-02 22:03:47 +00002757 }
2758#endif
2759
2760
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002761 context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context));
Peter Hinz56885f32011-03-02 22:03:47 +00002762 if (!context) {
Andy Green43db0452013-01-10 19:50:35 +08002763 lwsl_err("No memory for websocket context\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002764 return NULL;
2765 }
Peter Hinz56885f32011-03-02 22:03:47 +00002766 context->protocols = protocols;
2767 context->listen_port = port;
2768 context->http_proxy_port = 0;
2769 context->http_proxy_address[0] = '\0';
2770 context->options = options;
2771 context->fds_count = 0;
Andy Greend6e09112011-03-05 16:12:15 +00002772 context->extensions = extensions;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002773 context->last_timeout_check_s = 0;
Alon Levy0291eb32012-10-19 11:21:56 +02002774 context->user_space = user;
Andy Green9659f372011-01-27 22:01:43 +00002775
Peter Hinz56885f32011-03-02 22:03:47 +00002776#ifdef WIN32
2777 context->fd_random = 0;
2778#else
2779 context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
2780 if (context->fd_random < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002781 lwsl_err("Unable to open random device %s %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002782 SYSTEM_RANDOM_FILEPATH, context->fd_random);
Andy Green44eee682011-02-10 09:32:24 +00002783 return NULL;
2784 }
Peter Hinz56885f32011-03-02 22:03:47 +00002785#endif
Andy Green44eee682011-02-10 09:32:24 +00002786
Peter Hinz56885f32011-03-02 22:03:47 +00002787#ifdef LWS_OPENSSL_SUPPORT
2788 context->use_ssl = 0;
2789 context->ssl_ctx = NULL;
2790 context->ssl_client_ctx = NULL;
Andy Green2e24da02011-03-05 16:12:04 +00002791 openssl_websocket_private_data_index = 0;
Peter Hinz56885f32011-03-02 22:03:47 +00002792#endif
Andy Green2ac5a6f2011-01-28 10:00:18 +00002793
Andy Green788c4a82012-10-22 12:29:57 +01002794 if (options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME) {
Andy Greena69f0512012-05-03 12:32:38 +08002795
Andy Green788c4a82012-10-22 12:29:57 +01002796 strcpy(context->canonical_hostname, "unknown");
Andy Greena69f0512012-05-03 12:32:38 +08002797
Andy Green788c4a82012-10-22 12:29:57 +01002798 } else {
2799
2800 /* find canonical hostname */
2801
2802 hostname[(sizeof hostname) - 1] = '\0';
2803 memset(&sa, 0, sizeof(sa));
2804 sa.sa_family = AF_INET;
2805 sa.sa_data[(sizeof sa.sa_data) - 1] = '\0';
2806 gethostname(hostname, (sizeof hostname) - 1);
2807
2808 n = 0;
2809
David Galeanoed3c8402013-01-10 10:45:24 +08002810 if (strlen(hostname) < sizeof(sa.sa_data) - 1) {
Andy Green788c4a82012-10-22 12:29:57 +01002811 strcpy(sa.sa_data, hostname);
Andy Green43db0452013-01-10 19:50:35 +08002812 // lwsl_debug("my host name is %s\n", sa.sa_data);
Andy Green788c4a82012-10-22 12:29:57 +01002813 n = getnameinfo(&sa, sizeof(sa), hostname,
2814 (sizeof hostname) - 1, NULL, 0, 0);
2815 }
2816
2817 if (!n) {
2818 strncpy(context->canonical_hostname, hostname,
2819 sizeof context->canonical_hostname - 1);
2820 context->canonical_hostname[
2821 sizeof context->canonical_hostname - 1] = '\0';
2822 } else
2823 strncpy(context->canonical_hostname, hostname,
2824 sizeof context->canonical_hostname - 1);
2825
Andy Green43db0452013-01-10 19:50:35 +08002826 // lwsl_debug("context->canonical_hostname = %s\n",
Andy Green788c4a82012-10-22 12:29:57 +01002827 // context->canonical_hostname);
Andy Greena69f0512012-05-03 12:32:38 +08002828 }
2829
Andy Green9659f372011-01-27 22:01:43 +00002830 /* split the proxy ads:port if given */
2831
2832 p = getenv("http_proxy");
2833 if (p) {
Peter Hinz56885f32011-03-02 22:03:47 +00002834 strncpy(context->http_proxy_address, p,
Andy Green6ee372f2012-04-09 15:09:01 +08002835 sizeof context->http_proxy_address - 1);
Peter Hinz56885f32011-03-02 22:03:47 +00002836 context->http_proxy_address[
2837 sizeof context->http_proxy_address - 1] = '\0';
Andy Green9659f372011-01-27 22:01:43 +00002838
Peter Hinz56885f32011-03-02 22:03:47 +00002839 p = strchr(context->http_proxy_address, ':');
Andy Green9659f372011-01-27 22:01:43 +00002840 if (p == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002841 lwsl_err("http_proxy needs to be ads:port\n");
Andy Green9659f372011-01-27 22:01:43 +00002842 return NULL;
2843 }
2844 *p = '\0';
Peter Hinz56885f32011-03-02 22:03:47 +00002845 context->http_proxy_port = atoi(p + 1);
Andy Green9659f372011-01-27 22:01:43 +00002846
Andy Green43db0452013-01-10 19:50:35 +08002847 lwsl_debug("Using proxy %s:%u\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002848 context->http_proxy_address,
2849 context->http_proxy_port);
Andy Green9659f372011-01-27 22:01:43 +00002850 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002851
2852 if (port) {
2853
Andy Green3faa9c72010-11-08 17:03:03 +00002854#ifdef LWS_OPENSSL_SUPPORT
Peter Hinz56885f32011-03-02 22:03:47 +00002855 context->use_ssl = ssl_cert_filepath != NULL &&
Andy Green90c7cbc2011-01-27 06:26:52 +00002856 ssl_private_key_filepath != NULL;
Peter Hinz56885f32011-03-02 22:03:47 +00002857 if (context->use_ssl)
Andy Green43db0452013-01-10 19:50:35 +08002858 lwsl_info(" Compiled with SSL support, using it\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002859 else
Andy Green43db0452013-01-10 19:50:35 +08002860 lwsl_info(" Compiled with SSL support, not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +00002861
Andy Green90c7cbc2011-01-27 06:26:52 +00002862#else
2863 if (ssl_cert_filepath != NULL &&
2864 ssl_private_key_filepath != NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002865 lwsl_info(" Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +00002866 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002867 }
Andy Green43db0452013-01-10 19:50:35 +08002868 lwsl_info(" Compiled without SSL support, "
Andy Green90c7cbc2011-01-27 06:26:52 +00002869 "serving unencrypted\n");
2870#endif
2871 }
2872
2873 /* ignore SIGPIPE */
Peter Hinz56885f32011-03-02 22:03:47 +00002874#ifdef WIN32
2875#else
Andy Green90c7cbc2011-01-27 06:26:52 +00002876 signal(SIGPIPE, sigpipe_handler);
Peter Hinz56885f32011-03-02 22:03:47 +00002877#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002878
2879
2880#ifdef LWS_OPENSSL_SUPPORT
2881
2882 /* basic openssl init */
2883
2884 SSL_library_init();
2885
2886 OpenSSL_add_all_algorithms();
2887 SSL_load_error_strings();
2888
Andy Green2e24da02011-03-05 16:12:04 +00002889 openssl_websocket_private_data_index =
Andy Green6901cb32011-02-21 08:06:47 +00002890 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
2891
Andy Green90c7cbc2011-01-27 06:26:52 +00002892 /*
2893 * Firefox insists on SSLv23 not SSLv3
2894 * Konq disables SSLv2 by default now, SSLv23 works
2895 */
2896
2897 method = (SSL_METHOD *)SSLv23_server_method();
2898 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002899 lwsl_err("problem creating ssl method: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002900 ERR_error_string(ERR_get_error(), ssl_err_buf));
2901 return NULL;
2902 }
Peter Hinz56885f32011-03-02 22:03:47 +00002903 context->ssl_ctx = SSL_CTX_new(method); /* create context */
2904 if (!context->ssl_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002905 lwsl_err("problem creating ssl context: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002906 ERR_error_string(ERR_get_error(), ssl_err_buf));
2907 return NULL;
2908 }
2909
David Galeanocc148e42013-01-10 10:18:59 +08002910#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002911 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002912#endif
David Galeano77a677c2013-01-10 10:14:12 +08002913 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002914 SSL_CTX_set_cipher_list(context->ssl_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002915
Andy Green90c7cbc2011-01-27 06:26:52 +00002916 /* client context */
Andy Green6ee372f2012-04-09 15:09:01 +08002917
2918 if (port == CONTEXT_PORT_NO_LISTEN) {
Peter Hinz56885f32011-03-02 22:03:47 +00002919 method = (SSL_METHOD *)SSLv23_client_method();
2920 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002921 lwsl_err("problem creating ssl method: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002922 ERR_error_string(ERR_get_error(), ssl_err_buf));
2923 return NULL;
2924 }
2925 /* create context */
2926 context->ssl_client_ctx = SSL_CTX_new(method);
2927 if (!context->ssl_client_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002928 lwsl_err("problem creating ssl context: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002929 ERR_error_string(ERR_get_error(), ssl_err_buf));
2930 return NULL;
2931 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002932
David Galeanocc148e42013-01-10 10:18:59 +08002933#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002934 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002935#endif
David Galeano77a677c2013-01-10 10:14:12 +08002936 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002937 SSL_CTX_set_cipher_list(context->ssl_client_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002938
Peter Hinz56885f32011-03-02 22:03:47 +00002939 /* openssl init for cert verification (for client sockets) */
David Galeano2f82be82013-01-09 16:25:54 +08002940 if (!ssl_ca_filepath) {
2941 if (!SSL_CTX_load_verify_locations(
2942 context->ssl_client_ctx, NULL,
2943 LWS_OPENSSL_CLIENT_CERTS))
Andy Green43db0452013-01-10 19:50:35 +08002944 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002945 "Unable to load SSL Client certs from %s "
2946 "(set by --with-client-cert-dir= in configure) -- "
2947 " client ssl isn't going to work",
2948 LWS_OPENSSL_CLIENT_CERTS);
2949 } else
2950 if (!SSL_CTX_load_verify_locations(
2951 context->ssl_client_ctx, ssl_ca_filepath,
2952 NULL))
Andy Green43db0452013-01-10 19:50:35 +08002953 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002954 "Unable to load SSL Client certs "
2955 "file from %s -- client ssl isn't "
2956 "going to work", ssl_ca_filepath);
Peter Hinz56885f32011-03-02 22:03:47 +00002957
2958 /*
2959 * callback allowing user code to load extra verification certs
2960 * helping the client to verify server identity
2961 */
2962
2963 context->protocols[0].callback(context, NULL,
2964 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
2965 context->ssl_client_ctx, NULL, 0);
Andy Green90c7cbc2011-01-27 06:26:52 +00002966 }
Andy Green6ee372f2012-04-09 15:09:01 +08002967
Andy Greenc6bf2c22011-02-20 11:10:47 +00002968 /* as a server, are we requiring clients to identify themselves? */
2969
2970 if (options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
2971
2972 /* absolutely require the client cert */
Andy Green6ee372f2012-04-09 15:09:01 +08002973
Peter Hinz56885f32011-03-02 22:03:47 +00002974 SSL_CTX_set_verify(context->ssl_ctx,
Andy Green6901cb32011-02-21 08:06:47 +00002975 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2976 OpenSSL_verify_callback);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002977
2978 /*
2979 * give user code a chance to load certs into the server
2980 * allowing it to verify incoming client certs
2981 */
2982
Peter Hinz56885f32011-03-02 22:03:47 +00002983 context->protocols[0].callback(context, NULL,
Andy Greenc6bf2c22011-02-20 11:10:47 +00002984 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
Peter Hinz56885f32011-03-02 22:03:47 +00002985 context->ssl_ctx, NULL, 0);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002986 }
2987
Peter Hinz56885f32011-03-02 22:03:47 +00002988 if (context->use_ssl) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002989
2990 /* openssl init for server sockets */
2991
Andy Green3faa9c72010-11-08 17:03:03 +00002992 /* set the local certificate from CertFile */
David Galeano9b3d4b22013-01-10 10:11:21 +08002993 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
2994 ssl_cert_filepath);
Andy Green3faa9c72010-11-08 17:03:03 +00002995 if (n != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002996 lwsl_err("problem getting cert '%s': %s\n",
Andy Green3faa9c72010-11-08 17:03:03 +00002997 ssl_cert_filepath,
2998 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002999 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00003000 }
3001 /* set the private key from KeyFile */
Peter Hinz56885f32011-03-02 22:03:47 +00003002 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
3003 ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
Andy Green43db0452013-01-10 19:50:35 +08003004 lwsl_err("ssl problem getting key '%s': %s\n",
Andy Green018d8eb2010-11-08 21:04:23 +00003005 ssl_private_key_filepath,
3006 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00003007 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00003008 }
3009 /* verify private key */
Peter Hinz56885f32011-03-02 22:03:47 +00003010 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
Andy Green43db0452013-01-10 19:50:35 +08003011 lwsl_err("Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +00003012 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00003013 }
3014
3015 /* SSL is happy and has a cert it's content with */
3016 }
3017#endif
Andy Greenb45993c2010-12-18 15:13:50 +00003018
Andy Greendf736162011-01-18 15:39:02 +00003019 /* selftest */
3020
3021 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +00003022 return NULL;
Andy Greendf736162011-01-18 15:39:02 +00003023
Andy Green0d338332011-02-12 11:57:43 +00003024 /* fd hashtable init */
3025
3026 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00003027 context->fd_hashtable[n].length = 0;
Andy Green0d338332011-02-12 11:57:43 +00003028
Andy Greenb45993c2010-12-18 15:13:50 +00003029 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +00003030
Andy Green4739e5c2011-01-22 12:51:57 +00003031 if (port) {
Andy Green8f037e42010-12-19 22:13:26 +00003032
Andy Green4739e5c2011-01-22 12:51:57 +00003033 sockfd = socket(AF_INET, SOCK_STREAM, 0);
3034 if (sockfd < 0) {
Andy Greenf7609e92013-01-14 13:10:55 +08003035 lwsl_err("ERROR opening socket\n");
Andy Green4739e5c2011-01-22 12:51:57 +00003036 return NULL;
3037 }
Andy Green775c0dd2010-10-29 14:15:22 +01003038
Andy Green4739e5c2011-01-22 12:51:57 +00003039 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08003040 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
3041 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00003042
3043 /* Disable Nagle */
3044 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08003045 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
3046 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00003047
Andy Green4739e5c2011-01-22 12:51:57 +00003048 bzero((char *) &serv_addr, sizeof(serv_addr));
3049 serv_addr.sin_family = AF_INET;
Peter Hinz56885f32011-03-02 22:03:47 +00003050 if (interf == NULL)
Andy Green32375b72011-02-19 08:32:53 +00003051 serv_addr.sin_addr.s_addr = INADDR_ANY;
3052 else
Peter Hinz56885f32011-03-02 22:03:47 +00003053 interface_to_sa(interf, &serv_addr,
Andy Green32375b72011-02-19 08:32:53 +00003054 sizeof(serv_addr));
Andy Green4739e5c2011-01-22 12:51:57 +00003055 serv_addr.sin_port = htons(port);
3056
3057 n = bind(sockfd, (struct sockaddr *) &serv_addr,
3058 sizeof(serv_addr));
3059 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003060 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Green8f037e42010-12-19 22:13:26 +00003061 port, n, errno);
Andy Green41c58032013-01-12 13:21:08 +08003062 close(sockfd);
Andy Green4739e5c2011-01-22 12:51:57 +00003063 return NULL;
3064 }
Andy Green0d338332011-02-12 11:57:43 +00003065
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003066 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08003067 if (wsi == NULL) {
3068 lwsl_err("Out of mem\n");
3069 close(sockfd);
3070 return NULL;
3071 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003072 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00003073 wsi->sock = sockfd;
Andy Greend6e09112011-03-05 16:12:15 +00003074 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00003075 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
Peter Hinz56885f32011-03-02 22:03:47 +00003076 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00003077
Andy Green65b0e912013-01-16 07:59:47 +08003078 context->listen_service_modulo = LWS_LISTEN_SERVICE_MODULO;
3079 context->listen_service_count = 0;
3080 context->listen_service_fd = sockfd;
3081
Andy Greena824d182013-01-15 20:52:29 +08003082 listen(sockfd, LWS_SOMAXCONN);
Andy Green43db0452013-01-10 19:50:35 +08003083 lwsl_info(" Listening on port %d\n", port);
Andy Green0d338332011-02-12 11:57:43 +00003084
Andy Green65b0e912013-01-16 07:59:47 +08003085 /* list in the internal poll array - we're always first */
Andy Green6ee372f2012-04-09 15:09:01 +08003086
Peter Hinz56885f32011-03-02 22:03:47 +00003087 context->fds[context->fds_count].fd = sockfd;
3088 context->fds[context->fds_count++].events = POLLIN;
Andy Green3221f922011-02-12 13:14:11 +00003089
3090 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00003091 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00003092 LWS_CALLBACK_ADD_POLL_FD,
3093 (void *)(long)sockfd, NULL, POLLIN);
3094
Andy Green8f037e42010-12-19 22:13:26 +00003095 }
Andy Greenb45993c2010-12-18 15:13:50 +00003096
Andy Green6ee372f2012-04-09 15:09:01 +08003097 /*
3098 * drop any root privs for this process
3099 * to listen on port < 1023 we would have needed root, but now we are
3100 * listening, we don't want the power for anything else
3101 */
Peter Hinz56885f32011-03-02 22:03:47 +00003102#ifdef WIN32
3103#else
Andy Green3faa9c72010-11-08 17:03:03 +00003104 if (gid != -1)
3105 if (setgid(gid))
Andy Green43db0452013-01-10 19:50:35 +08003106 lwsl_warn("setgid: %s\n", strerror(errno));
Andy Green3faa9c72010-11-08 17:03:03 +00003107 if (uid != -1)
3108 if (setuid(uid))
Andy Green43db0452013-01-10 19:50:35 +08003109 lwsl_warn("setuid: %s\n", strerror(errno));
Peter Hinz56885f32011-03-02 22:03:47 +00003110#endif
Andy Greenb45993c2010-12-18 15:13:50 +00003111
3112 /* set up our internal broadcast trigger sockets per-protocol */
3113
Peter Hinz56885f32011-03-02 22:03:47 +00003114 for (context->count_protocols = 0;
3115 protocols[context->count_protocols].callback;
3116 context->count_protocols++) {
Andy Green2d1301e2011-05-24 10:14:41 +01003117
Andy Green43db0452013-01-10 19:50:35 +08003118 lwsl_parser(" Protocol: %s\n",
3119 protocols[context->count_protocols].name);
Andy Green2d1301e2011-05-24 10:14:41 +01003120
Peter Hinz56885f32011-03-02 22:03:47 +00003121 protocols[context->count_protocols].owning_server = context;
3122 protocols[context->count_protocols].protocol_index =
3123 context->count_protocols;
Andy Greenb45993c2010-12-18 15:13:50 +00003124
3125 fd = socket(AF_INET, SOCK_STREAM, 0);
3126 if (fd < 0) {
Andy Greenf7609e92013-01-14 13:10:55 +08003127 lwsl_err("ERROR opening socket\n");
Andy Greene92cd172011-01-19 13:11:55 +00003128 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003129 }
Andy Green8f037e42010-12-19 22:13:26 +00003130
Andy Greenb45993c2010-12-18 15:13:50 +00003131 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08003132 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt,
3133 sizeof(opt));
Andy Greenb45993c2010-12-18 15:13:50 +00003134
3135 bzero((char *) &serv_addr, sizeof(serv_addr));
3136 serv_addr.sin_family = AF_INET;
3137 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3138 serv_addr.sin_port = 0; /* pick the port for us */
3139
3140 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
3141 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003142 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Greenb45993c2010-12-18 15:13:50 +00003143 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +00003144 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003145 }
3146
3147 slen = sizeof cli_addr;
3148 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
3149 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003150 lwsl_err("getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +00003151 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003152 }
Peter Hinz56885f32011-03-02 22:03:47 +00003153 protocols[context->count_protocols].broadcast_socket_port =
Andy Greenb45993c2010-12-18 15:13:50 +00003154 ntohs(cli_addr.sin_port);
3155 listen(fd, 5);
3156
Andy Green43db0452013-01-10 19:50:35 +08003157 lwsl_debug(" Protocol %s broadcast socket %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00003158 protocols[context->count_protocols].name,
Andy Greenb45993c2010-12-18 15:13:50 +00003159 ntohs(cli_addr.sin_port));
3160
Andy Green0d338332011-02-12 11:57:43 +00003161 /* dummy wsi per broadcast proxy socket */
3162
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003163 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08003164 if (wsi == NULL) {
3165 lwsl_err("Out of mem\n");
3166 close(fd);
3167 return NULL;
3168 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003169 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00003170 wsi->sock = fd;
3171 wsi->mode = LWS_CONNMODE_BROADCAST_PROXY_LISTENER;
Andy Greend6e09112011-03-05 16:12:15 +00003172 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00003173 /* note which protocol we are proxying */
Peter Hinz56885f32011-03-02 22:03:47 +00003174 wsi->protocol_index_for_broadcast_proxy =
3175 context->count_protocols;
3176 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00003177
3178 /* list in internal poll array */
3179
Peter Hinz56885f32011-03-02 22:03:47 +00003180 context->fds[context->fds_count].fd = fd;
3181 context->fds[context->fds_count].events = POLLIN;
3182 context->fds[context->fds_count].revents = 0;
3183 context->fds_count++;
Andy Green3221f922011-02-12 13:14:11 +00003184
3185 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00003186 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00003187 LWS_CALLBACK_ADD_POLL_FD,
3188 (void *)(long)fd, NULL, POLLIN);
Andy Greenb45993c2010-12-18 15:13:50 +00003189 }
3190
Andy Greena41314f2011-05-23 10:00:03 +01003191 /*
3192 * give all extensions a chance to create any per-context
3193 * allocations they need
3194 */
3195
3196 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
3197 if (port)
3198 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
Andrew Chambersd5512172012-05-20 08:17:09 +08003199
3200 if (extensions) {
3201 while (extensions->callback) {
Andy Green43db0452013-01-10 19:50:35 +08003202 lwsl_ext(" Extension: %s\n", extensions->name);
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003203 extensions->callback(context, extensions, NULL,
3204 (enum libwebsocket_extension_callback_reasons)m,
3205 NULL, NULL, 0);
Andrew Chambersd5512172012-05-20 08:17:09 +08003206 extensions++;
3207 }
Andy Greena41314f2011-05-23 10:00:03 +01003208 }
3209
Peter Hinz56885f32011-03-02 22:03:47 +00003210 return context;
Andy Greene92cd172011-01-19 13:11:55 +00003211}
Andy Greenb45993c2010-12-18 15:13:50 +00003212
Andy Green4739e5c2011-01-22 12:51:57 +00003213
Andy Greened11a022011-01-20 10:23:50 +00003214#ifndef LWS_NO_FORK
3215
Andy Greene92cd172011-01-19 13:11:55 +00003216/**
3217 * libwebsockets_fork_service_loop() - Optional helper function forks off
3218 * a process for the websocket server loop.
Andy Green6964bb52011-01-23 16:50:33 +00003219 * You don't have to use this but if not, you
3220 * have to make sure you are calling
3221 * libwebsocket_service periodically to service
3222 * the websocket traffic
Peter Hinz56885f32011-03-02 22:03:47 +00003223 * @context: server context returned by creation function
Andy Greene92cd172011-01-19 13:11:55 +00003224 */
Andy Greenb45993c2010-12-18 15:13:50 +00003225
Andy Greene92cd172011-01-19 13:11:55 +00003226int
Peter Hinz56885f32011-03-02 22:03:47 +00003227libwebsockets_fork_service_loop(struct libwebsocket_context *context)
Andy Greene92cd172011-01-19 13:11:55 +00003228{
Andy Greene92cd172011-01-19 13:11:55 +00003229 int fd;
3230 struct sockaddr_in cli_addr;
3231 int n;
Andy Green3221f922011-02-12 13:14:11 +00003232 int p;
Andy Greenb45993c2010-12-18 15:13:50 +00003233
Andy Greened11a022011-01-20 10:23:50 +00003234 n = fork();
3235 if (n < 0)
3236 return n;
3237
3238 if (!n) {
3239
3240 /* main process context */
3241
Andy Green3221f922011-02-12 13:14:11 +00003242 /*
3243 * set up the proxy sockets to allow broadcast from
3244 * service process context
3245 */
3246
Peter Hinz56885f32011-03-02 22:03:47 +00003247 for (p = 0; p < context->count_protocols; p++) {
Andy Greened11a022011-01-20 10:23:50 +00003248 fd = socket(AF_INET, SOCK_STREAM, 0);
3249 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003250 lwsl_err("Unable to create socket\n");
Andy Greened11a022011-01-20 10:23:50 +00003251 return -1;
3252 }
3253 cli_addr.sin_family = AF_INET;
3254 cli_addr.sin_port = htons(
Peter Hinz56885f32011-03-02 22:03:47 +00003255 context->protocols[p].broadcast_socket_port);
Andy Greened11a022011-01-20 10:23:50 +00003256 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3257 n = connect(fd, (struct sockaddr *)&cli_addr,
3258 sizeof cli_addr);
3259 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003260 lwsl_err("Unable to connect to "
Andy Greened11a022011-01-20 10:23:50 +00003261 "broadcast socket %d, %s\n",
Andy Green3221f922011-02-12 13:14:11 +00003262 n, strerror(errno));
Andy Greened11a022011-01-20 10:23:50 +00003263 return -1;
3264 }
3265
Peter Hinz56885f32011-03-02 22:03:47 +00003266 context->protocols[p].broadcast_socket_user_fd = fd;
Andy Greened11a022011-01-20 10:23:50 +00003267 }
3268
Andy Greene92cd172011-01-19 13:11:55 +00003269 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00003270 }
3271
Artem Baguinski91531662011-12-14 22:14:03 +01003272#ifdef HAVE_SYS_PRCTL_H
Andy Greenb45993c2010-12-18 15:13:50 +00003273 /* we want a SIGHUP when our parent goes down */
3274 prctl(PR_SET_PDEATHSIG, SIGHUP);
Artem Baguinski91531662011-12-14 22:14:03 +01003275#endif
Andy Greenb45993c2010-12-18 15:13:50 +00003276
3277 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +00003278
Artem Baguinski91531662011-12-14 22:14:03 +01003279 while (1) {
Peter Hinz56885f32011-03-02 22:03:47 +00003280 if (libwebsocket_service(context, 1000))
Andy Green3928f612012-07-20 12:58:38 +08003281 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003282//#ifndef HAVE_SYS_PRCTL_H
Artem Baguinski91531662011-12-14 22:14:03 +01003283/*
3284 * on systems without prctl() (i.e. anything but linux) we can notice that our
3285 * parent is dead if getppid() returns 1. FIXME apparently this is not true for
3286 * solaris, could remember ppid right after fork and wait for it to change.
3287 */
3288
3289 if (getppid() == 1)
3290 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003291//#endif
Artem Baguinski91531662011-12-14 22:14:03 +01003292 }
3293
Andy Green8f037e42010-12-19 22:13:26 +00003294
Andy Green3928f612012-07-20 12:58:38 +08003295 return 1;
Andy Greenff95d7a2010-10-28 22:36:01 +01003296}
3297
Andy Greened11a022011-01-20 10:23:50 +00003298#endif
3299
Andy Greenb45993c2010-12-18 15:13:50 +00003300/**
3301 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +00003302 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +00003303 * @wsi: pointer to struct websocket you want to know the protocol of
3304 *
Andy Green8f037e42010-12-19 22:13:26 +00003305 *
3306 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +00003307 * the callback.
3308 */
Andy Greenab990e42010-10-31 12:42:52 +00003309
Andy Greenb45993c2010-12-18 15:13:50 +00003310const struct libwebsocket_protocols *
3311libwebsockets_get_protocol(struct libwebsocket *wsi)
3312{
3313 return wsi->protocol;
3314}
3315
3316/**
Andy Greene92cd172011-01-19 13:11:55 +00003317 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +00003318 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +00003319 * @protocol: pointer to the protocol you will broadcast to all members of
3320 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +00003321 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
3322 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
3323 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +00003324 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +00003325 *
3326 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +00003327 * the given protocol. It does not send the data directly; instead it calls
3328 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
3329 * wants to actually send the data for that connection, the callback itself
3330 * should call libwebsocket_write().
3331 *
3332 * libwebsockets_broadcast() can be called from another fork context without
3333 * having to take any care about data visibility between the processes, it'll
3334 * "just work".
3335 */
3336
3337
3338int
Andy Green8f037e42010-12-19 22:13:26 +00003339libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +00003340 unsigned char *buf, size_t len)
3341{
Peter Hinz56885f32011-03-02 22:03:47 +00003342 struct libwebsocket_context *context = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +00003343 int n;
Andy Green0d338332011-02-12 11:57:43 +00003344 int m;
Andy Green6ee372f2012-04-09 15:09:01 +08003345 struct libwebsocket *wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00003346
3347 if (!protocol->broadcast_socket_user_fd) {
3348 /*
Andy Greene92cd172011-01-19 13:11:55 +00003349 * We are either running unforked / flat, or we are being
3350 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +00003351 * eg, from a callback. In that case don't use sockets for
3352 * broadcast IPC (since we can't open a socket connection to
3353 * a socket listening on our own thread) but directly do the
3354 * send action.
3355 *
3356 * Locking is not needed because we are by definition being
3357 * called in the poll thread context and are serialized.
3358 */
3359
Andy Green0d338332011-02-12 11:57:43 +00003360 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003361
Peter Hinz56885f32011-03-02 22:03:47 +00003362 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003363
Peter Hinz56885f32011-03-02 22:03:47 +00003364 wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00003365
Andy Green0d338332011-02-12 11:57:43 +00003366 if (wsi->mode != LWS_CONNMODE_WS_SERVING)
3367 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00003368
Andy Green0d338332011-02-12 11:57:43 +00003369 /*
3370 * never broadcast to
3371 * non-established connections
3372 */
3373 if (wsi->state != WSI_STATE_ESTABLISHED)
3374 continue;
3375
3376 /* only broadcast to guys using
3377 * requested protocol
3378 */
3379 if (wsi->protocol != protocol)
3380 continue;
3381
Peter Hinz56885f32011-03-02 22:03:47 +00003382 wsi->protocol->callback(context, wsi,
Andy Green8f037e42010-12-19 22:13:26 +00003383 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00003384 wsi->user_space,
Andy Greenb45993c2010-12-18 15:13:50 +00003385 buf, len);
Andy Green0d338332011-02-12 11:57:43 +00003386 }
Andy Greenb45993c2010-12-18 15:13:50 +00003387 }
3388
3389 return 0;
3390 }
3391
Andy Green0ca6a172010-12-19 20:50:01 +00003392 /*
3393 * We're being called from a different process context than the server
3394 * loop. Instead of broadcasting directly, we send our
3395 * payload on a socket to do the IPC; the server process will serialize
3396 * the broadcast action in its main poll() loop.
3397 *
3398 * There's one broadcast socket listening for each protocol supported
3399 * set up when the websocket server initializes
3400 */
3401
Andy Green6964bb52011-01-23 16:50:33 +00003402 n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
Andy Greenb45993c2010-12-18 15:13:50 +00003403
3404 return n;
3405}
Andy Green82c3d542011-03-07 21:16:31 +00003406
3407int
3408libwebsocket_is_final_fragment(struct libwebsocket *wsi)
3409{
3410 return wsi->final;
3411}
Alex Bligh49146db2011-11-07 17:19:25 +08003412
David Galeanoe2cf9922013-01-09 18:06:55 +08003413unsigned char
3414libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
3415{
3416 return wsi->rsv;
3417}
3418
Alex Bligh49146db2011-11-07 17:19:25 +08003419void *
3420libwebsocket_ensure_user_space(struct libwebsocket *wsi)
3421{
3422 /* allocate the per-connection user memory (if any) */
3423
3424 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
3425 wsi->user_space = malloc(
3426 wsi->protocol->per_session_data_size);
3427 if (wsi->user_space == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08003428 lwsl_err("Out of memory for conn user space\n");
Alex Bligh49146db2011-11-07 17:19:25 +08003429 return NULL;
3430 }
Andy Green6ee372f2012-04-09 15:09:01 +08003431 memset(wsi->user_space, 0,
3432 wsi->protocol->per_session_data_size);
Alex Bligh49146db2011-11-07 17:19:25 +08003433 }
3434 return wsi->user_space;
3435}
Andy Green43db0452013-01-10 19:50:35 +08003436
Andy Greende8f27a2013-01-12 09:17:42 +08003437
3438static void lwsl_emit_stderr(const char *line)
3439{
3440 fprintf(stderr, "%s", line);
3441}
3442
Andy Green43db0452013-01-10 19:50:35 +08003443void _lws_log(int filter, const char *format, ...)
3444{
Andy Greende8f27a2013-01-12 09:17:42 +08003445 char buf[256];
Andy Green43db0452013-01-10 19:50:35 +08003446 va_list ap;
3447 int n;
Andy Greende8f27a2013-01-12 09:17:42 +08003448 int pos = 0;
Andy Green8a265092013-01-12 09:25:07 +08003449 struct timeval tv;
Andy Green43db0452013-01-10 19:50:35 +08003450
3451 if (!(log_level & filter))
3452 return;
3453
Andy Green8a265092013-01-12 09:25:07 +08003454 gettimeofday(&tv, NULL);
3455
Andy Green43db0452013-01-10 19:50:35 +08003456 for (n = 0; n < LLL_COUNT; n++)
3457 if (filter == (1 << n)) {
Andy Green8a265092013-01-12 09:25:07 +08003458 pos = sprintf(buf, "[%ld:%04ld] %s: ", tv.tv_sec,
3459 tv.tv_usec / 100, log_level_names[n]);
Andy Green43db0452013-01-10 19:50:35 +08003460 break;
3461 }
3462
3463 va_start(ap, format);
Andy Greende8f27a2013-01-12 09:17:42 +08003464 vsnprintf(buf + pos, (sizeof buf) - pos, format, ap);
3465 buf[(sizeof buf) - 1] = '\0';
3466 va_end(ap);
3467
3468 lwsl_emit(buf);
Andy Green43db0452013-01-10 19:50:35 +08003469}
3470
3471/**
3472 * lws_set_log_level() - Set the logging bitfield
3473 * @level: OR together the LLL_ debug contexts you want output from
Andy Greende8f27a2013-01-12 09:17:42 +08003474 * @log_emit_function: NULL to leave it as it is, or a user-supplied
3475 * function to perform log string emission instead of
3476 * the default stderr one.
Andy Green43db0452013-01-10 19:50:35 +08003477 *
Andy Greende8f27a2013-01-12 09:17:42 +08003478 * log level defaults to "err" and "warn" contexts enabled only and
3479 * emission on stderr.
Andy Green43db0452013-01-10 19:50:35 +08003480 */
3481
Andy Greende8f27a2013-01-12 09:17:42 +08003482void lws_set_log_level(int level, void (*log_emit_function)(const char *line))
Andy Green43db0452013-01-10 19:50:35 +08003483{
3484 log_level = level;
Andy Greende8f27a2013-01-12 09:17:42 +08003485 if (log_emit_function)
3486 lwsl_emit = log_emit_function;
Andy Green43db0452013-01-10 19:50:35 +08003487}