blob: 8bc91de1b00d1ac8f700748529098b99b12c981c [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
Peter Hinz56885f32011-03-02 22:03:47 +00001537 wsi = wsi_from_fd(context, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001538
Andy Greend280b6e2013-01-15 13:40:23 +08001539 if (wsi == NULL) {
1540 lwsl_debug("hm fd %d has NULL wsi\n", pollfd->fd);
Andy Greenfa3f4052012-10-07 20:40:35 +08001541 return 0;
Andy Greend280b6e2013-01-15 13:40:23 +08001542 }
Andy Green8f037e42010-12-19 22:13:26 +00001543
Andy Green0d338332011-02-12 11:57:43 +00001544 switch (wsi->mode) {
Andy Greend280b6e2013-01-15 13:40:23 +08001545
1546 case LWS_CONNMODE_HTTP_SERVING:
1547
1548 /* handle http headers coming in */
1549
1550 /* any incoming data ready? */
1551
1552 if (pollfd->revents & POLLIN) {
1553
1554 #ifdef LWS_OPENSSL_SUPPORT
1555 if (wsi->ssl)
1556 len = SSL_read(wsi->ssl, buf, sizeof buf);
1557 else
1558 #endif
1559 len = recv(pollfd->fd, buf, sizeof buf, 0);
1560
1561 if (len < 0) {
1562 lwsl_debug("Socket read returned %d\n", len);
1563 if (errno != EINTR && errno != EAGAIN)
1564 libwebsocket_close_and_free_session(context,
1565 wsi, LWS_CLOSE_STATUS_NOSTATUS);
1566 return 1;
1567 }
1568 if (!len) {
1569 libwebsocket_close_and_free_session(context, wsi,
1570 LWS_CLOSE_STATUS_NOSTATUS);
1571 return 0;
1572 }
1573
1574 n = libwebsocket_read(context, wsi, buf, len);
1575 if (n < 0)
1576 /* we closed wsi */
1577 return 1;
1578 }
1579
1580 /* this handles POLLOUT for http serving fragments */
1581
1582 if (!(pollfd->revents & POLLOUT))
1583 break;
1584
1585 /* one shot */
1586 pollfd->events &= ~POLLOUT;
1587
1588 if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE)
1589 break;
1590
1591 if (libwebsockets_serve_http_file_fragment(context, wsi) < 0)
1592 libwebsocket_close_and_free_session(context, wsi,
1593 LWS_CLOSE_STATUS_NOSTATUS);
1594 else
1595 if (wsi->state == WSI_STATE_HTTP && wsi->protocol->callback)
1596 if (wsi->protocol->callback(context, wsi, LWS_CALLBACK_HTTP_FILE_COMPLETION, wsi->user_space,
1597 wsi->filepath, wsi->filepos))
1598 libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
1599 break;
1600
Andy Green0d338332011-02-12 11:57:43 +00001601 case LWS_CONNMODE_SERVER_LISTENER:
1602
1603 /* pollin means a client has connected to us then */
1604
David Galeanob88e0962013-01-10 09:54:10 +08001605 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001606 break;
1607
David Galeanof7009352011-09-26 12:09:54 +01001608 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001609 lwsl_warn("too busy to accept new client\n");
David Galeanof7009352011-09-26 12:09:54 +01001610 break;
1611 }
1612
Andy Green0d338332011-02-12 11:57:43 +00001613 /* listen socket got an unencrypted connection... */
1614
1615 clilen = sizeof(cli_addr);
1616 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1617 &clilen);
1618 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001619 lwsl_warn("ERROR on accept: %d\n", strerror(errno));
Andy Green3928f612012-07-20 12:58:38 +08001620 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001621 }
1622
Andy Green6c939552011-03-08 08:56:57 +00001623 /* Disable Nagle */
1624 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08001625 setsockopt(accept_fd, IPPROTO_TCP, TCP_NODELAY,
1626 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00001627
Andy Green07034092011-02-13 08:37:12 +00001628 /*
1629 * look at who we connected to and give user code a chance
1630 * to reject based on client IP. There's no protocol selected
1631 * yet so we issue this to protocols[0]
1632 */
1633
Peter Hinz56885f32011-03-02 22:03:47 +00001634 if ((context->protocols[0].callback)(context, wsi,
Andy Green07034092011-02-13 08:37:12 +00001635 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
Andy Green6ee372f2012-04-09 15:09:01 +08001636 (void *)(long)accept_fd, NULL, 0)) {
Andy Green43db0452013-01-10 19:50:35 +08001637 lwsl_debug("Callback denied network connection\n");
Andy Green3fc2c652013-01-14 15:35:02 +08001638 compatible_close(accept_fd);
Andy Green07034092011-02-13 08:37:12 +00001639 break;
1640 }
1641
Andy Greena41314f2011-05-23 10:00:03 +01001642 new_wsi = libwebsocket_create_new_server_wsi(context);
David Galeanoed3c8402013-01-10 10:45:24 +08001643 if (new_wsi == NULL) {
Andy Green3fc2c652013-01-14 15:35:02 +08001644 compatible_close(accept_fd);
Andy Green0d338332011-02-12 11:57:43 +00001645 break;
David Galeanoed3c8402013-01-10 10:45:24 +08001646 }
Andy Green0d338332011-02-12 11:57:43 +00001647
Andy Green0d338332011-02-12 11:57:43 +00001648 new_wsi->sock = accept_fd;
Andy Greena41314f2011-05-23 10:00:03 +01001649
Andy Green0d338332011-02-12 11:57:43 +00001650
1651#ifdef LWS_OPENSSL_SUPPORT
1652 new_wsi->ssl = NULL;
Andy Green0d338332011-02-12 11:57:43 +00001653
Peter Hinz56885f32011-03-02 22:03:47 +00001654 if (context->use_ssl) {
Andy Green0d338332011-02-12 11:57:43 +00001655
Peter Hinz56885f32011-03-02 22:03:47 +00001656 new_wsi->ssl = SSL_new(context->ssl_ctx);
Andy Green0d338332011-02-12 11:57:43 +00001657 if (new_wsi->ssl == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08001658 lwsl_err("SSL_new failed: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001659 ERR_error_string(SSL_get_error(
1660 new_wsi->ssl, 0), NULL));
Andy Green1f9bf522011-02-14 21:14:37 +00001661 libwebsockets_decode_ssl_error();
Andy Green0d338332011-02-12 11:57:43 +00001662 free(new_wsi);
Andy Green3fc2c652013-01-14 15:35:02 +08001663 compatible_close(accept_fd);
Andy Green0d338332011-02-12 11:57:43 +00001664 break;
1665 }
1666
Larry Hayes455d1fe2013-01-15 01:03:58 +08001667 SSL_set_ex_data(new_wsi->ssl,
1668 openssl_websocket_private_data_index, context);
1669
Andy Green0d338332011-02-12 11:57:43 +00001670 SSL_set_fd(new_wsi->ssl, accept_fd);
1671
1672 n = SSL_accept(new_wsi->ssl);
1673 if (n != 1) {
1674 /*
1675 * browsers seem to probe with various
1676 * ssl params which fail then retry
1677 * and succeed
1678 */
Andy Green43db0452013-01-10 19:50:35 +08001679 lwsl_debug("SSL_accept failed skt %u: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001680 pollfd->fd,
1681 ERR_error_string(SSL_get_error(
1682 new_wsi->ssl, n), NULL));
1683 SSL_free(
1684 new_wsi->ssl);
1685 free(new_wsi);
Andy Green3fc2c652013-01-14 15:35:02 +08001686 compatible_close(accept_fd);
Andy Green0d338332011-02-12 11:57:43 +00001687 break;
1688 }
Andy Green6ee372f2012-04-09 15:09:01 +08001689
Andy Green43db0452013-01-10 19:50:35 +08001690 lwsl_debug("accepted new SSL conn "
Andy Green0d338332011-02-12 11:57:43 +00001691 "port %u on fd=%d SSL ver %s\n",
1692 ntohs(cli_addr.sin_port), accept_fd,
1693 SSL_get_version(new_wsi->ssl));
1694
1695 } else
1696#endif
Andy Green43db0452013-01-10 19:50:35 +08001697 lwsl_debug("accepted new conn port %u on fd=%d\n",
Andy Green0d338332011-02-12 11:57:43 +00001698 ntohs(cli_addr.sin_port), accept_fd);
1699
Peter Hinz56885f32011-03-02 22:03:47 +00001700 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001701
Andy Green0d338332011-02-12 11:57:43 +00001702 /*
1703 * make sure NO events are seen yet on this new socket
1704 * (otherwise we inherit old fds[client].revents from
1705 * previous socket there and die mysteriously! )
1706 */
Peter Hinz56885f32011-03-02 22:03:47 +00001707 context->fds[context->fds_count].revents = 0;
Andy Green0d338332011-02-12 11:57:43 +00001708
Peter Hinz56885f32011-03-02 22:03:47 +00001709 context->fds[context->fds_count].events = POLLIN;
1710 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001711
Andy Green3221f922011-02-12 13:14:11 +00001712 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001713 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001714 LWS_CALLBACK_ADD_POLL_FD,
1715 (void *)(long)accept_fd, NULL, POLLIN);
1716
Andy Green0d338332011-02-12 11:57:43 +00001717 break;
1718
1719 case LWS_CONNMODE_BROADCAST_PROXY_LISTENER:
1720
1721 /* as we are listening, POLLIN means accept() is needed */
Andy Green6ee372f2012-04-09 15:09:01 +08001722
David Galeanob88e0962013-01-10 09:54:10 +08001723 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001724 break;
1725
1726 /* listen socket got an unencrypted connection... */
1727
1728 clilen = sizeof(cli_addr);
1729 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1730 &clilen);
1731 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001732 lwsl_warn("ERROR on accept %d\n", accept_fd);
Andy Green3928f612012-07-20 12:58:38 +08001733 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001734 }
1735
Peter Hinz56885f32011-03-02 22:03:47 +00001736 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001737 lwsl_err("too busy to accept new broadcast "
Andy Green3221f922011-02-12 13:14:11 +00001738 "proxy client\n");
Andy Green41c58032013-01-12 13:21:08 +08001739 goto bail_prox_listener;
Andy Green0d338332011-02-12 11:57:43 +00001740 }
1741
1742 /* create a dummy wsi for the connection and add it */
1743
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001744 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08001745 if (new_wsi == NULL) {
1746 lwsl_err("Out of mem\n");
1747 goto bail_prox_listener;
1748 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001749 memset(new_wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00001750 new_wsi->sock = accept_fd;
1751 new_wsi->mode = LWS_CONNMODE_BROADCAST_PROXY;
1752 new_wsi->state = WSI_STATE_ESTABLISHED;
Andy Greend6e09112011-03-05 16:12:15 +00001753 new_wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00001754 /* note which protocol we are proxying */
1755 new_wsi->protocol_index_for_broadcast_proxy =
1756 wsi->protocol_index_for_broadcast_proxy;
Peter Hinz56885f32011-03-02 22:03:47 +00001757 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001758
1759 /* add connected socket to internal poll array */
1760
Peter Hinz56885f32011-03-02 22:03:47 +00001761 context->fds[context->fds_count].revents = 0;
1762 context->fds[context->fds_count].events = POLLIN;
1763 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001764
Andy Green3221f922011-02-12 13:14:11 +00001765 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001766 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001767 LWS_CALLBACK_ADD_POLL_FD,
1768 (void *)(long)accept_fd, NULL, POLLIN);
1769
Andy Green0d338332011-02-12 11:57:43 +00001770 break;
1771
Andy Green41c58032013-01-12 13:21:08 +08001772bail_prox_listener:
Andy Green3fc2c652013-01-14 15:35:02 +08001773 compatible_close(accept_fd);
Andy Green41c58032013-01-12 13:21:08 +08001774 break;
1775
Andy Green0d338332011-02-12 11:57:43 +00001776 case LWS_CONNMODE_BROADCAST_PROXY:
Andy Green8f037e42010-12-19 22:13:26 +00001777
Andy Greenb45993c2010-12-18 15:13:50 +00001778 /* handle session socket closed */
Andy Green8f037e42010-12-19 22:13:26 +00001779
Andy Green0d338332011-02-12 11:57:43 +00001780 if (pollfd->revents & (POLLERR | POLLHUP)) {
Andy Green8f037e42010-12-19 22:13:26 +00001781
Andy Green43db0452013-01-10 19:50:35 +08001782 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Timothy J Fontaineb86d64e2011-02-14 17:55:27 +00001783 (void *)wsi, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001784
Peter Hinz56885f32011-03-02 22:03:47 +00001785 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001786 LWS_CLOSE_STATUS_NORMAL);
Andy Green4b6fbe12011-02-14 08:03:48 +00001787 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00001788 }
Andy Green8f037e42010-12-19 22:13:26 +00001789
Andy Green3b84c002011-03-06 13:14:42 +00001790 /*
1791 * either extension code with stuff to spill, or the user code,
1792 * requested a callback when it was OK to write
1793 */
Andy Green90c7cbc2011-01-27 06:26:52 +00001794
Andy Green3b84c002011-03-06 13:14:42 +00001795 if (pollfd->revents & POLLOUT)
Andy Green6ee372f2012-04-09 15:09:01 +08001796 if (lws_handle_POLLOUT_event(context, wsi,
1797 pollfd) < 0) {
1798 libwebsocket_close_and_free_session(
1799 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00001800 return 1;
1801 }
Andy Green90c7cbc2011-01-27 06:26:52 +00001802
Andy Greenb45993c2010-12-18 15:13:50 +00001803 /* any incoming data ready? */
1804
Andy Green0d338332011-02-12 11:57:43 +00001805 if (!(pollfd->revents & POLLIN))
1806 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001807
Andy Green0d338332011-02-12 11:57:43 +00001808 /* get the issued broadcast payload from the socket */
Andy Greenb45993c2010-12-18 15:13:50 +00001809
Andy Green0d338332011-02-12 11:57:43 +00001810 len = read(pollfd->fd, buf + LWS_SEND_BUFFER_PRE_PADDING,
1811 MAX_BROADCAST_PAYLOAD);
1812 if (len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001813 lwsl_err("Error reading broadcast payload\n");
Andy Green4b6fbe12011-02-14 08:03:48 +00001814 break;
Andy Green0d338332011-02-12 11:57:43 +00001815 }
Andy Greenb45993c2010-12-18 15:13:50 +00001816
Andy Green0d338332011-02-12 11:57:43 +00001817 /* broadcast it to all guys with this protocol index */
Andy Green8f037e42010-12-19 22:13:26 +00001818
Andy Green0d338332011-02-12 11:57:43 +00001819 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Green8f037e42010-12-19 22:13:26 +00001820
Peter Hinz56885f32011-03-02 22:03:47 +00001821 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00001822
Peter Hinz56885f32011-03-02 22:03:47 +00001823 new_wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00001824
Andy Green0d338332011-02-12 11:57:43 +00001825 /* only to clients we are serving to */
Andy Greenb45993c2010-12-18 15:13:50 +00001826
Andy Green0d338332011-02-12 11:57:43 +00001827 if (new_wsi->mode != LWS_CONNMODE_WS_SERVING)
Andy Greenb45993c2010-12-18 15:13:50 +00001828 continue;
1829
1830 /*
1831 * never broadcast to non-established
1832 * connection
1833 */
1834
Andy Green0d338332011-02-12 11:57:43 +00001835 if (new_wsi->state != WSI_STATE_ESTABLISHED)
Andy Green4739e5c2011-01-22 12:51:57 +00001836 continue;
1837
Andy Greenb45993c2010-12-18 15:13:50 +00001838 /*
1839 * only broadcast to connections using
1840 * the requested protocol
1841 */
1842
Andy Green0d338332011-02-12 11:57:43 +00001843 if (new_wsi->protocol->protocol_index !=
1844 wsi->protocol_index_for_broadcast_proxy)
Andy Greenb45993c2010-12-18 15:13:50 +00001845 continue;
1846
Andy Green8f037e42010-12-19 22:13:26 +00001847 /* broadcast it to this connection */
1848
Peter Hinz56885f32011-03-02 22:03:47 +00001849 new_wsi->protocol->callback(context, new_wsi,
Andy Green8f037e42010-12-19 22:13:26 +00001850 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00001851 new_wsi->user_space,
Andy Green0ca6a172010-12-19 20:50:01 +00001852 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
Andy Greenb45993c2010-12-18 15:13:50 +00001853 }
Andy Green0d338332011-02-12 11:57:43 +00001854 }
1855 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001856
Andy Greenbe93fef2011-02-14 20:25:43 +00001857 case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
1858
1859 /* handle proxy hung up on us */
1860
1861 if (pollfd->revents & (POLLERR | POLLHUP)) {
1862
Andy Green43db0452013-01-10 19:50:35 +08001863 lwsl_warn("Proxy connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00001864 (void *)wsi, pollfd->fd);
1865
Peter Hinz56885f32011-03-02 22:03:47 +00001866 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001867 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001868 return 1;
1869 }
1870
Andy Green72c34322011-04-16 10:46:21 +01001871 n = recv(wsi->sock, pkt, sizeof pkt, 0);
Andy Greenbe93fef2011-02-14 20:25:43 +00001872 if (n < 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001873 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001874 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001875 lwsl_err("ERROR reading from proxy socket\n");
Andy Greenbe93fef2011-02-14 20:25:43 +00001876 return 1;
1877 }
1878
1879 pkt[13] = '\0';
1880 if (strcmp(pkt, "HTTP/1.0 200 ") != 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001881 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001882 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001883 lwsl_err("ERROR from proxy: %s\n", pkt);
Andy Greenbe93fef2011-02-14 20:25:43 +00001884 return 1;
1885 }
1886
1887 /* clear his proxy connection timeout */
1888
1889 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1890
1891 /* fallthru */
1892
1893 case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
1894
Andy Green73abc252013-01-13 11:05:30 +08001895 /*
1896 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
1897 * timeout protection set in client-handshake.c
1898 */
1899
Andy Greenbe93fef2011-02-14 20:25:43 +00001900 #ifdef LWS_OPENSSL_SUPPORT
Andy Green73abc252013-01-13 11:05:30 +08001901
1902 /*
1903 * take care of our libwebsocket_callback_on_writable
1904 * happening at a time when there's no real connection yet
1905 */
1906
1907 pollfd->events &= ~POLLOUT;
1908
1909 /* external POLL support via protocol 0 */
1910 context->protocols[0].callback(context, wsi,
1911 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
1912 (void *)(long)wsi->sock, NULL, POLLOUT);
1913
1914 /* we can retry this... so just cook the SSL BIO the first time */
1915
Ken Atherton8360a472012-05-03 11:45:04 +08001916 if (wsi->use_ssl && !wsi->ssl) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001917
Peter Hinz56885f32011-03-02 22:03:47 +00001918 wsi->ssl = SSL_new(context->ssl_client_ctx);
1919 wsi->client_bio = BIO_new_socket(wsi->sock,
1920 BIO_NOCLOSE);
Andy Greenbe93fef2011-02-14 20:25:43 +00001921 SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
1922
Andy Green6901cb32011-02-21 08:06:47 +00001923 SSL_set_ex_data(wsi->ssl,
Andy Green2e24da02011-03-05 16:12:04 +00001924 openssl_websocket_private_data_index,
Peter Hinz56885f32011-03-02 22:03:47 +00001925 context);
Ken Atherton8360a472012-05-03 11:45:04 +08001926 }
Andy Green6901cb32011-02-21 08:06:47 +00001927
Ken Atherton8360a472012-05-03 11:45:04 +08001928 if (wsi->use_ssl) {
Andy Green73abc252013-01-13 11:05:30 +08001929 n = SSL_connect(wsi->ssl);
Ken Atherton8360a472012-05-03 11:45:04 +08001930
Andy Green73abc252013-01-13 11:05:30 +08001931 if (n < 0) {
1932 n = SSL_get_error(wsi->ssl, n);
1933
1934 if (n == SSL_ERROR_WANT_READ ||
1935 n == SSL_ERROR_WANT_WRITE) {
1936 /*
1937 * wants us to retry connect due to state of the
1938 * underlying ssl layer... but since it may be
1939 * stalled on blocked write, no incoming data may
1940 * arrive to trigger the retry. Force (possibly
1941 * many if the SSL state persists in returning the
1942 * condition code, but other sockets are getting
1943 * serviced inbetweentimes) us to get called back
1944 * when writable.
1945 */
1946
1947 lwsl_info("SSL_connect -> SSL_ERROR_WANT_... retrying\n");
1948 libwebsocket_callback_on_writable(context, wsi);
1949
1950 return 0; /* no error */
1951 }
1952 n = -1;
1953 }
1954
1955 if (n <= 0) {
Ken Atherton8360a472012-05-03 11:45:04 +08001956 /*
1957 * retry if new data comes until we
1958 * run into the connection timeout or win
1959 */
1960
Andy Green43db0452013-01-10 19:50:35 +08001961 lwsl_err("SSL connect error %s\n",
Andy Green687b0182011-02-26 11:04:01 +00001962 ERR_error_string(ERR_get_error(),
1963 ssl_err_buf));
Ken Atherton8360a472012-05-03 11:45:04 +08001964 return 0;
Andy Greenbe93fef2011-02-14 20:25:43 +00001965 }
1966
1967 n = SSL_get_verify_result(wsi->ssl);
Andy Green2e24da02011-03-05 16:12:04 +00001968 if ((n != X509_V_OK) && (
Andy Green687b0182011-02-26 11:04:01 +00001969 n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
1970 wsi->use_ssl != 2)) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001971
Andy Green43db0452013-01-10 19:50:35 +08001972 lwsl_err("server's cert didn't "
Andy Green687b0182011-02-26 11:04:01 +00001973 "look good %d\n", n);
Peter Hinz56885f32011-03-02 22:03:47 +00001974 libwebsocket_close_and_free_session(context,
1975 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Green687b0182011-02-26 11:04:01 +00001976 return 1;
Andy Greenbe93fef2011-02-14 20:25:43 +00001977 }
Ken Atherton8360a472012-05-03 11:45:04 +08001978 } else
Andy Greenbe93fef2011-02-14 20:25:43 +00001979 wsi->ssl = NULL;
1980 #endif
1981
Andy Greena41314f2011-05-23 10:00:03 +01001982 p = libwebsockets_generate_client_handshake(context, wsi, p);
Andy Green6ee372f2012-04-09 15:09:01 +08001983 if (p == NULL)
Andy Greenbe93fef2011-02-14 20:25:43 +00001984 return 1;
Andy Greeneeaacb32011-03-01 20:44:24 +00001985
Andy Greenbe93fef2011-02-14 20:25:43 +00001986 /* send our request to the server */
1987
1988 #ifdef LWS_OPENSSL_SUPPORT
1989 if (wsi->use_ssl)
1990 n = SSL_write(wsi->ssl, pkt, p - pkt);
1991 else
1992 #endif
1993 n = send(wsi->sock, pkt, p - pkt, 0);
1994
1995 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001996 lwsl_debug("ERROR writing to client socket\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001997 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001998 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001999 return 1;
2000 }
2001
2002 wsi->parser_state = WSI_TOKEN_NAME_PART;
2003 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
2004 libwebsocket_set_timeout(wsi,
David Galeanoc9f1ff82013-01-09 18:01:23 +08002005 PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, AWAITING_TIMEOUT);
Andy Greenbe93fef2011-02-14 20:25:43 +00002006
2007 break;
2008
2009 case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
2010
2011 /* handle server hung up on us */
2012
2013 if (pollfd->revents & (POLLERR | POLLHUP)) {
2014
Andy Green43db0452013-01-10 19:50:35 +08002015 lwsl_debug("Server connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00002016 (void *)wsi, pollfd->fd);
2017
2018 goto bail3;
2019 }
2020
2021
2022 /* interpret the server response */
2023
2024 /*
2025 * HTTP/1.1 101 Switching Protocols
2026 * Upgrade: websocket
2027 * Connection: Upgrade
2028 * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
2029 * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
2030 * Sec-WebSocket-Protocol: chat
2031 */
2032
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08002033 /*
2034 * we have to take some care here to only take from the
2035 * socket bytewise. The browser may (and has been seen to
2036 * in the case that onopen() performs websocket traffic)
2037 * coalesce both handshake response and websocket traffic
2038 * in one packet, since at that point the connection is
2039 * definitively ready from browser pov.
2040 */
Andy Greenbe93fef2011-02-14 20:25:43 +00002041
Andy Green7b5af9a2012-04-09 15:23:47 +08002042 len = 1;
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08002043 while (wsi->parser_state != WSI_PARSING_COMPLETE && len > 0) {
2044#ifdef LWS_OPENSSL_SUPPORT
2045 if (wsi->use_ssl)
2046 len = SSL_read(wsi->ssl, &c, 1);
2047 else
2048#endif
2049 len = recv(wsi->sock, &c, 1, 0);
2050
2051 libwebsocket_parse(wsi, c);
Andy Greenbe93fef2011-02-14 20:25:43 +00002052 }
2053
Andy Green27a0b912011-04-16 10:54:28 +01002054 /*
Andy Green6ee372f2012-04-09 15:09:01 +08002055 * hs may also be coming in multiple packets, there is a 5-sec
Andy Green27a0b912011-04-16 10:54:28 +01002056 * libwebsocket timeout still active here too, so if parsing did
2057 * not complete just wait for next packet coming in this state
2058 */
2059
2060 if (wsi->parser_state != WSI_PARSING_COMPLETE)
2061 break;
Andy Greenbe93fef2011-02-14 20:25:43 +00002062
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08002063 /*
2064 * otherwise deal with the handshake. If there's any
2065 * packet traffic already arrived we'll trigger poll() again
2066 * right away and deal with it that way
2067 */
2068
Andy Greena41314f2011-05-23 10:00:03 +01002069 return lws_client_interpret_server_handshake(context, wsi);
Andy Greenbe93fef2011-02-14 20:25:43 +00002070
2071bail3:
2072 if (wsi->c_protocol)
2073 free(wsi->c_protocol);
Peter Hinz56885f32011-03-02 22:03:47 +00002074 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002075 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00002076 return 1;
Andy Greena41314f2011-05-23 10:00:03 +01002077
2078 case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
Andy Green43db0452013-01-10 19:50:35 +08002079 lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
Andy Greena41314f2011-05-23 10:00:03 +01002080 break;
2081
2082 case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
Andy Green43db0452013-01-10 19:50:35 +08002083 lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
Andy Greena41314f2011-05-23 10:00:03 +01002084 break;
2085
Andy Greenbe93fef2011-02-14 20:25:43 +00002086
Andy Green0d338332011-02-12 11:57:43 +00002087 case LWS_CONNMODE_WS_SERVING:
2088 case LWS_CONNMODE_WS_CLIENT:
2089
2090 /* handle session socket closed */
2091
2092 if (pollfd->revents & (POLLERR | POLLHUP)) {
2093
Andy Green43db0452013-01-10 19:50:35 +08002094 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Andy Green0d338332011-02-12 11:57:43 +00002095 (void *)wsi, pollfd->fd);
2096
Peter Hinz56885f32011-03-02 22:03:47 +00002097 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002098 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green4b6fbe12011-02-14 08:03:48 +00002099 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002100 }
2101
Andy Green0d338332011-02-12 11:57:43 +00002102 /* the guy requested a callback when it was OK to write */
2103
Andy Greenda527df2011-03-07 07:08:12 +00002104 if ((pollfd->revents & POLLOUT) &&
2105 wsi->state == WSI_STATE_ESTABLISHED)
2106 if (lws_handle_POLLOUT_event(context, wsi,
2107 pollfd) < 0) {
2108 libwebsocket_close_and_free_session(
2109 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00002110 return 1;
2111 }
Andy Green0d338332011-02-12 11:57:43 +00002112
Andy Green0d338332011-02-12 11:57:43 +00002113
2114 /* any incoming data ready? */
2115
2116 if (!(pollfd->revents & POLLIN))
2117 break;
2118
Andy Greenb45993c2010-12-18 15:13:50 +00002119#ifdef LWS_OPENSSL_SUPPORT
David Galeano7ffbe1b2013-01-10 10:35:32 +08002120read_pending:
Andy Green0d338332011-02-12 11:57:43 +00002121 if (wsi->ssl)
Andy Green98a717c2011-03-06 13:14:15 +00002122 eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);
Andy Greenb45993c2010-12-18 15:13:50 +00002123 else
2124#endif
Andy Green98a717c2011-03-06 13:14:15 +00002125 eff_buf.token_len =
Andy Green72c34322011-04-16 10:46:21 +01002126 recv(pollfd->fd, buf, sizeof buf, 0);
Andy Greenb45993c2010-12-18 15:13:50 +00002127
Andy Green98a717c2011-03-06 13:14:15 +00002128 if (eff_buf.token_len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002129 lwsl_debug("Socket read returned %d\n",
Andy Green98a717c2011-03-06 13:14:15 +00002130 eff_buf.token_len);
Alon Levydc93b7f2012-10-19 11:21:57 +02002131 if (errno != EINTR && errno != EAGAIN)
Andy Green6ee372f2012-04-09 15:09:01 +08002132 libwebsocket_close_and_free_session(context,
2133 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Nick Dowellc04c1932012-04-05 10:29:39 +08002134 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002135 }
Andy Green98a717c2011-03-06 13:14:15 +00002136 if (!eff_buf.token_len) {
Peter Hinz56885f32011-03-02 22:03:47 +00002137 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002138 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenfa3f4052012-10-07 20:40:35 +08002139 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00002140 }
2141
Andy Green98a717c2011-03-06 13:14:15 +00002142 /*
2143 * give any active extensions a chance to munge the buffer
2144 * before parse. We pass in a pointer to an lws_tokens struct
2145 * prepared with the default buffer and content length that's in
2146 * there. Rather than rewrite the default buffer, extensions
2147 * that expect to grow the buffer can adapt .token to
2148 * point to their own per-connection buffer in the extension
2149 * user allocation. By default with no extensions or no
2150 * extension callback handling, just the normal input buffer is
2151 * used then so it is efficient.
2152 */
Andy Greenb45993c2010-12-18 15:13:50 +00002153
Andy Green98a717c2011-03-06 13:14:15 +00002154 eff_buf.token = (char *)buf;
Andy Greenb45993c2010-12-18 15:13:50 +00002155
Andy Green98a717c2011-03-06 13:14:15 +00002156 more = 1;
2157 while (more) {
Andy Green0d338332011-02-12 11:57:43 +00002158
Andy Green98a717c2011-03-06 13:14:15 +00002159 more = 0;
2160
2161 for (n = 0; n < wsi->count_active_extensions; n++) {
Andy Green46c2ea02011-03-22 09:04:01 +00002162 m = wsi->active_extensions[n]->callback(context,
2163 wsi->active_extensions[n], wsi,
Andy Green98a717c2011-03-06 13:14:15 +00002164 LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
Andy Green46c2ea02011-03-22 09:04:01 +00002165 wsi->active_extensions_user[n],
2166 &eff_buf, 0);
Andy Green98a717c2011-03-06 13:14:15 +00002167 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002168 lwsl_ext(
Andy Green6ee372f2012-04-09 15:09:01 +08002169 "Extension reports fatal error\n");
2170 libwebsocket_close_and_free_session(
2171 context, wsi,
2172 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green98a717c2011-03-06 13:14:15 +00002173 return 1;
2174 }
2175 if (m)
2176 more = 1;
2177 }
2178
2179 /* service incoming data */
2180
2181 if (eff_buf.token_len) {
2182 n = libwebsocket_read(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002183 (unsigned char *)eff_buf.token,
2184 eff_buf.token_len);
Andy Green98a717c2011-03-06 13:14:15 +00002185 if (n < 0)
2186 /* we closed wsi */
2187 return 1;
2188 }
2189
2190 eff_buf.token = NULL;
2191 eff_buf.token_len = 0;
2192 }
David Galeano7ffbe1b2013-01-10 10:35:32 +08002193
2194#ifdef LWS_OPENSSL_SUPPORT
2195 if (wsi->ssl && SSL_pending(wsi->ssl))
2196 goto read_pending;
2197#endif
Andy Green98a717c2011-03-06 13:14:15 +00002198 break;
Andy Greenb45993c2010-12-18 15:13:50 +00002199 }
2200
2201 return 0;
2202}
2203
Andy Green0d338332011-02-12 11:57:43 +00002204
Andy Green6964bb52011-01-23 16:50:33 +00002205/**
2206 * libwebsocket_context_destroy() - Destroy the websocket context
Peter Hinz56885f32011-03-02 22:03:47 +00002207 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002208 *
2209 * This function closes any active connections and then frees the
2210 * context. After calling this, any further use of the context is
2211 * undefined.
2212 */
2213void
Peter Hinz56885f32011-03-02 22:03:47 +00002214libwebsocket_context_destroy(struct libwebsocket_context *context)
Andy Green6964bb52011-01-23 16:50:33 +00002215{
Andy Green0d338332011-02-12 11:57:43 +00002216 int n;
2217 int m;
2218 struct libwebsocket *wsi;
Andy Greena41314f2011-05-23 10:00:03 +01002219 struct libwebsocket_extension *ext;
Andy Green6964bb52011-01-23 16:50:33 +00002220
Andy Green4b6fbe12011-02-14 08:03:48 +00002221 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002222 for (m = 0; m < context->fd_hashtable[n].length; m++) {
2223 wsi = context->fd_hashtable[n].wsi[m];
2224 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002225 LWS_CLOSE_STATUS_GOINGAWAY);
Andy Greenf3d3b402011-02-09 07:16:34 +00002226 }
Andy Green6964bb52011-01-23 16:50:33 +00002227
Andy Greena41314f2011-05-23 10:00:03 +01002228 /*
2229 * give all extensions a chance to clean up any per-context
2230 * allocations they might have made
2231 */
2232
2233 ext = context->extensions;
2234 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
2235 if (context->listen_port)
2236 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
Paulo Roberto Urio1f680ab2012-06-04 08:40:28 +08002237 while (ext && ext->callback) {
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002238 ext->callback(context, ext, NULL, (enum libwebsocket_extension_callback_reasons)m, NULL, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01002239 ext++;
2240 }
2241
Peter Hinz56885f32011-03-02 22:03:47 +00002242#ifdef WIN32
2243#else
2244 close(context->fd_random);
Andy Green6964bb52011-01-23 16:50:33 +00002245#endif
2246
Peter Hinz56885f32011-03-02 22:03:47 +00002247#ifdef LWS_OPENSSL_SUPPORT
2248 if (context->ssl_ctx)
2249 SSL_CTX_free(context->ssl_ctx);
2250 if (context->ssl_client_ctx)
2251 SSL_CTX_free(context->ssl_client_ctx);
2252#endif
2253
2254 free(context);
2255
2256#ifdef WIN32
2257 WSACleanup();
2258#endif
Andy Green6964bb52011-01-23 16:50:33 +00002259}
2260
Alon Levy0291eb32012-10-19 11:21:56 +02002261LWS_EXTERN void *
2262libwebsocket_context_user(struct libwebsocket_context *context)
2263{
2264 return context->user_space;
2265}
2266
Andy Green6964bb52011-01-23 16:50:33 +00002267/**
2268 * libwebsocket_service() - Service any pending websocket activity
Peter Hinz56885f32011-03-02 22:03:47 +00002269 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002270 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
2271 * service otherwise block and service immediately, returning
2272 * after the timeout if nothing needed service.
2273 *
2274 * This function deals with any pending websocket traffic, for three
2275 * kinds of event. It handles these events on both server and client
2276 * types of connection the same.
2277 *
2278 * 1) Accept new connections to our context's server
2279 *
2280 * 2) Perform pending broadcast writes initiated from other forked
2281 * processes (effectively serializing asynchronous broadcasts)
2282 *
2283 * 3) Call the receive callback for incoming frame data received by
2284 * server or client connections.
2285 *
2286 * You need to call this service function periodically to all the above
2287 * functions to happen; if your application is single-threaded you can
2288 * just call it in your main event loop.
2289 *
2290 * Alternatively you can fork a new process that asynchronously handles
2291 * calling this service in a loop. In that case you are happy if this
2292 * call blocks your thread until it needs to take care of something and
2293 * would call it with a large nonzero timeout. Your loop then takes no
2294 * CPU while there is nothing happening.
2295 *
2296 * If you are calling it in a single-threaded app, you don't want it to
2297 * wait around blocking other things in your loop from happening, so you
2298 * would call it with a timeout_ms of 0, so it returns immediately if
2299 * nothing is pending, or as soon as it services whatever was pending.
2300 */
2301
Andy Greenb45993c2010-12-18 15:13:50 +00002302
Andy Greene92cd172011-01-19 13:11:55 +00002303int
Peter Hinz56885f32011-03-02 22:03:47 +00002304libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
Andy Greene92cd172011-01-19 13:11:55 +00002305{
2306 int n;
Andy Greene92cd172011-01-19 13:11:55 +00002307
2308 /* stay dead once we are dead */
2309
Peter Hinz56885f32011-03-02 22:03:47 +00002310 if (context == NULL)
Andy Greene92cd172011-01-19 13:11:55 +00002311 return 1;
2312
Andy Green0d338332011-02-12 11:57:43 +00002313 /* wait for something to need service */
Andy Green4739e5c2011-01-22 12:51:57 +00002314
Peter Hinz56885f32011-03-02 22:03:47 +00002315 n = poll(context->fds, context->fds_count, timeout_ms);
Andy Green3221f922011-02-12 13:14:11 +00002316 if (n == 0) /* poll timeout */
2317 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002318
Andy Greend280b6e2013-01-15 13:40:23 +08002319
2320
Andy Green62c54d22011-02-14 09:14:25 +00002321 if (n < 0) {
Andy Green5e1fa172011-02-10 09:07:05 +00002322 /*
Andy Green43db0452013-01-10 19:50:35 +08002323 lwsl_err("Listen Socket dead\n");
Andy Green5e1fa172011-02-10 09:07:05 +00002324 */
Andy Green3928f612012-07-20 12:58:38 +08002325 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002326 }
Andy Greene92cd172011-01-19 13:11:55 +00002327
2328 /* handle accept on listening socket? */
2329
Peter Hinz56885f32011-03-02 22:03:47 +00002330 for (n = 0; n < context->fds_count; n++)
2331 if (context->fds[n].revents)
Andy Green3928f612012-07-20 12:58:38 +08002332 if (libwebsocket_service_fd(context,
2333 &context->fds[n]) < 0)
2334 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002335 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002336}
2337
Andy Greena41314f2011-05-23 10:00:03 +01002338int
2339lws_any_extension_handled(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002340 struct libwebsocket *wsi,
2341 enum libwebsocket_extension_callback_reasons r,
Andy Greena41314f2011-05-23 10:00:03 +01002342 void *v, size_t len)
2343{
2344 int n;
2345 int handled = 0;
2346
2347 /* maybe an extension will take care of it for us */
2348
2349 for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
2350 if (!wsi->active_extensions[n]->callback)
2351 continue;
2352
2353 handled |= wsi->active_extensions[n]->callback(context,
2354 wsi->active_extensions[n], wsi,
2355 r, wsi->active_extensions_user[n], v, len);
2356 }
2357
2358 return handled;
2359}
2360
2361
2362void *
2363lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002364 struct libwebsocket_extension *ext)
Andy Greena41314f2011-05-23 10:00:03 +01002365{
2366 int n = 0;
2367
Andy Green68b45042011-05-25 21:41:57 +01002368 if (wsi == NULL)
2369 return NULL;
2370
Andy Greena41314f2011-05-23 10:00:03 +01002371 while (n < wsi->count_active_extensions) {
2372 if (wsi->active_extensions[n] != ext) {
2373 n++;
2374 continue;
2375 }
2376 return wsi->active_extensions_user[n];
2377 }
2378
2379 return NULL;
2380}
2381
Andy Green90c7cbc2011-01-27 06:26:52 +00002382/**
2383 * libwebsocket_callback_on_writable() - Request a callback when this socket
2384 * becomes able to be written to without
2385 * blocking
Andy Green32375b72011-02-19 08:32:53 +00002386 *
Peter Hinz56885f32011-03-02 22:03:47 +00002387 * @context: libwebsockets context
Andy Green90c7cbc2011-01-27 06:26:52 +00002388 * @wsi: Websocket connection instance to get callback for
2389 */
2390
2391int
Peter Hinz56885f32011-03-02 22:03:47 +00002392libwebsocket_callback_on_writable(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002393 struct libwebsocket *wsi)
Andy Green90c7cbc2011-01-27 06:26:52 +00002394{
Andy Green90c7cbc2011-01-27 06:26:52 +00002395 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002396 int handled = 0;
2397
2398 /* maybe an extension will take care of it for us */
2399
2400 for (n = 0; n < wsi->count_active_extensions; n++) {
2401 if (!wsi->active_extensions[n]->callback)
2402 continue;
2403
2404 handled |= wsi->active_extensions[n]->callback(context,
2405 wsi->active_extensions[n], wsi,
2406 LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
2407 wsi->active_extensions_user[n], NULL, 0);
2408 }
2409
2410 if (handled)
2411 return 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002412
Peter Hinz56885f32011-03-02 22:03:47 +00002413 for (n = 0; n < context->fds_count; n++)
2414 if (context->fds[n].fd == wsi->sock) {
2415 context->fds[n].events |= POLLOUT;
Andy Greena41314f2011-05-23 10:00:03 +01002416 n = context->fds_count + 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002417 }
2418
Andy Greena41314f2011-05-23 10:00:03 +01002419 if (n == context->fds_count)
Andy Green43db0452013-01-10 19:50:35 +08002420 lwsl_err("libwebsocket_callback_on_writable: "
Andy Green6ee372f2012-04-09 15:09:01 +08002421 "failed to find socket %d\n", wsi->sock);
Andy Greena41314f2011-05-23 10:00:03 +01002422
Andy Green3221f922011-02-12 13:14:11 +00002423 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002424 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002425 LWS_CALLBACK_SET_MODE_POLL_FD,
2426 (void *)(long)wsi->sock, NULL, POLLOUT);
2427
Andy Green90c7cbc2011-01-27 06:26:52 +00002428 return 1;
2429}
2430
2431/**
2432 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
2433 * all connections using the given protocol when it
2434 * becomes possible to write to each socket without
2435 * blocking in turn.
2436 *
2437 * @protocol: Protocol whose connections will get callbacks
2438 */
2439
2440int
2441libwebsocket_callback_on_writable_all_protocol(
2442 const struct libwebsocket_protocols *protocol)
2443{
Peter Hinz56885f32011-03-02 22:03:47 +00002444 struct libwebsocket_context *context = protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002445 int n;
Andy Green0d338332011-02-12 11:57:43 +00002446 int m;
2447 struct libwebsocket *wsi;
Andy Green90c7cbc2011-01-27 06:26:52 +00002448
Andy Green0d338332011-02-12 11:57:43 +00002449 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
2450
Peter Hinz56885f32011-03-02 22:03:47 +00002451 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Green0d338332011-02-12 11:57:43 +00002452
Peter Hinz56885f32011-03-02 22:03:47 +00002453 wsi = context->fd_hashtable[n].wsi[m];
Andy Green0d338332011-02-12 11:57:43 +00002454
2455 if (wsi->protocol == protocol)
Peter Hinz56885f32011-03-02 22:03:47 +00002456 libwebsocket_callback_on_writable(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002457 }
2458 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002459
2460 return 0;
2461}
2462
Andy Greenbe93fef2011-02-14 20:25:43 +00002463/**
2464 * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
2465 *
2466 * You will not need this unless you are doing something special
2467 *
2468 * @wsi: Websocket connection instance
2469 * @reason: timeout reason
2470 * @secs: how many seconds
2471 */
2472
2473void
2474libwebsocket_set_timeout(struct libwebsocket *wsi,
2475 enum pending_timeout reason, int secs)
2476{
2477 struct timeval tv;
2478
2479 gettimeofday(&tv, NULL);
2480
2481 wsi->pending_timeout_limit = tv.tv_sec + secs;
2482 wsi->pending_timeout = reason;
2483}
2484
Andy Greena6cbece2011-01-27 20:06:03 +00002485
2486/**
2487 * libwebsocket_get_socket_fd() - returns the socket file descriptor
2488 *
2489 * You will not need this unless you are doing something special
2490 *
2491 * @wsi: Websocket connection instance
2492 */
2493
2494int
2495libwebsocket_get_socket_fd(struct libwebsocket *wsi)
2496{
2497 return wsi->sock;
2498}
2499
Andy Green90c7cbc2011-01-27 06:26:52 +00002500/**
2501 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
2502 * receieved packets.
2503 *
2504 * If the output side of a server process becomes choked, this allows flow
2505 * control for the input side.
2506 *
2507 * @wsi: Websocket connection instance to get callback for
2508 * @enable: 0 = disable read servicing for this connection, 1 = enable
2509 */
2510
2511int
2512libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
2513{
Peter Hinz56885f32011-03-02 22:03:47 +00002514 struct libwebsocket_context *context = wsi->protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002515 int n;
2516
Peter Hinz56885f32011-03-02 22:03:47 +00002517 for (n = 0; n < context->fds_count; n++)
2518 if (context->fds[n].fd == wsi->sock) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002519 if (enable)
Peter Hinz56885f32011-03-02 22:03:47 +00002520 context->fds[n].events |= POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002521 else
Peter Hinz56885f32011-03-02 22:03:47 +00002522 context->fds[n].events &= ~POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002523
2524 return 0;
2525 }
2526
Andy Green3221f922011-02-12 13:14:11 +00002527 if (enable)
2528 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002529 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002530 LWS_CALLBACK_SET_MODE_POLL_FD,
2531 (void *)(long)wsi->sock, NULL, POLLIN);
2532 else
2533 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002534 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002535 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
2536 (void *)(long)wsi->sock, NULL, POLLIN);
2537
Andy Greena41314f2011-05-23 10:00:03 +01002538#if 0
Andy Green43db0452013-01-10 19:50:35 +08002539 lwsl_err("libwebsocket_rx_flow_control unable to find socket\n");
Andy Greena41314f2011-05-23 10:00:03 +01002540#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002541 return 1;
2542}
2543
Andy Green2ac5a6f2011-01-28 10:00:18 +00002544/**
2545 * libwebsocket_canonical_hostname() - returns this host's hostname
2546 *
2547 * This is typically used by client code to fill in the host parameter
2548 * when making a client connection. You can only call it after the context
2549 * has been created.
2550 *
Peter Hinz56885f32011-03-02 22:03:47 +00002551 * @context: Websocket context
Andy Green2ac5a6f2011-01-28 10:00:18 +00002552 */
2553
2554
2555extern const char *
Peter Hinz56885f32011-03-02 22:03:47 +00002556libwebsocket_canonical_hostname(struct libwebsocket_context *context)
Andy Green2ac5a6f2011-01-28 10:00:18 +00002557{
Peter Hinz56885f32011-03-02 22:03:47 +00002558 return (const char *)context->canonical_hostname;
Andy Green2ac5a6f2011-01-28 10:00:18 +00002559}
2560
2561
Andy Green90c7cbc2011-01-27 06:26:52 +00002562static void sigpipe_handler(int x)
2563{
2564}
2565
Andy Green6901cb32011-02-21 08:06:47 +00002566#ifdef LWS_OPENSSL_SUPPORT
2567static int
2568OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
2569{
2570
2571 SSL *ssl;
2572 int n;
Andy Green2e24da02011-03-05 16:12:04 +00002573 struct libwebsocket_context *context;
Andy Green6901cb32011-02-21 08:06:47 +00002574
2575 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
2576 SSL_get_ex_data_X509_STORE_CTX_idx());
2577
2578 /*
Andy Green2e24da02011-03-05 16:12:04 +00002579 * !!! nasty openssl requires the index to come as a library-scope
2580 * static
Andy Green6901cb32011-02-21 08:06:47 +00002581 */
Andy Green2e24da02011-03-05 16:12:04 +00002582 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
Andy Green6ee372f2012-04-09 15:09:01 +08002583
Peter Hinz56885f32011-03-02 22:03:47 +00002584 n = context->protocols[0].callback(NULL, NULL,
Andy Green6901cb32011-02-21 08:06:47 +00002585 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
2586 x509_ctx, ssl, preverify_ok);
2587
2588 /* convert return code from 0 = OK to 1 = OK */
2589
2590 if (!n)
2591 n = 1;
2592 else
2593 n = 0;
2594
2595 return n;
2596}
2597#endif
2598
Andy Greenb45993c2010-12-18 15:13:50 +00002599
Andy Greenab990e42010-10-31 12:42:52 +00002600/**
Andy Green4739e5c2011-01-22 12:51:57 +00002601 * libwebsocket_create_context() - Create the websocket handler
2602 * @port: Port to listen on... you can use 0 to suppress listening on
Andy Green6964bb52011-01-23 16:50:33 +00002603 * any port, that's what you want if you are not running a
2604 * websocket server at all but just using it as a client
Peter Hinz56885f32011-03-02 22:03:47 +00002605 * @interf: NULL to bind the listen socket to all interfaces, or the
Andy Green32375b72011-02-19 08:32:53 +00002606 * interface name, eg, "eth2"
Andy Green4f3943a2010-11-12 10:44:16 +00002607 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +00002608 * specific callback for each one. The list is ended with an
2609 * entry that has a NULL callback pointer.
Andy Green6964bb52011-01-23 16:50:33 +00002610 * It's not const because we write the owning_server member
Andy Greenc5114822011-03-06 10:29:35 +00002611 * @extensions: NULL or array of libwebsocket_extension structs listing the
Andy Green6ee372f2012-04-09 15:09:01 +08002612 * extensions this context supports
Andy Green3faa9c72010-11-08 17:03:03 +00002613 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +00002614 * to listen using SSL, set to the filepath to fetch the
2615 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +00002616 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +00002617 * else ignored
David Galeano2f82be82013-01-09 16:25:54 +08002618 * @ssl_ca_filepath: CA certificate filepath or NULL
Andy Green3faa9c72010-11-08 17:03:03 +00002619 * @gid: group id to change to after setting listen socket, or -1.
2620 * @uid: user id to change to after setting listen socket, or -1.
Andy Greenbfb051f2011-02-09 08:49:14 +00002621 * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
Andy Green15e31f32012-10-19 18:36:28 +08002622 * @user: optional user pointer that can be recovered via the context
2623 * pointer using libwebsocket_context_user
Andy Green05464c62010-11-12 10:44:18 +00002624 *
Andy Green8f037e42010-12-19 22:13:26 +00002625 * This function creates the listening socket and takes care
2626 * of all initialization in one step.
2627 *
Andy Greene92cd172011-01-19 13:11:55 +00002628 * After initialization, it returns a struct libwebsocket_context * that
2629 * represents this server. After calling, user code needs to take care
2630 * of calling libwebsocket_service() with the context pointer to get the
2631 * server's sockets serviced. This can be done in the same process context
2632 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +00002633 *
Andy Green8f037e42010-12-19 22:13:26 +00002634 * The protocol callback functions are called for a handful of events
2635 * including http requests coming in, websocket connections becoming
2636 * established, and data arriving; it's also called periodically to allow
2637 * async transmission.
2638 *
2639 * HTTP requests are sent always to the FIRST protocol in @protocol, since
2640 * at that time websocket protocol has not been negotiated. Other
2641 * protocols after the first one never see any HTTP callack activity.
2642 *
2643 * The server created is a simple http server by default; part of the
2644 * websocket standard is upgrading this http connection to a websocket one.
2645 *
2646 * This allows the same server to provide files like scripts and favicon /
2647 * images or whatever over http and dynamic data over websockets all in
2648 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +00002649 */
Andy Green4ea60062010-10-30 12:15:07 +01002650
Andy Greene92cd172011-01-19 13:11:55 +00002651struct libwebsocket_context *
Peter Hinz56885f32011-03-02 22:03:47 +00002652libwebsocket_create_context(int port, const char *interf,
Andy Greenb45993c2010-12-18 15:13:50 +00002653 struct libwebsocket_protocols *protocols,
Andy Greend6e09112011-03-05 16:12:15 +00002654 struct libwebsocket_extension *extensions,
Andy Green8f037e42010-12-19 22:13:26 +00002655 const char *ssl_cert_filepath,
2656 const char *ssl_private_key_filepath,
David Galeano2f82be82013-01-09 16:25:54 +08002657 const char *ssl_ca_filepath,
Alon Levy0291eb32012-10-19 11:21:56 +02002658 int gid, int uid, unsigned int options,
David Galeano2f82be82013-01-09 16:25:54 +08002659 void *user)
Andy Greenff95d7a2010-10-28 22:36:01 +01002660{
2661 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002662 int m;
Andy Green4739e5c2011-01-22 12:51:57 +00002663 int sockfd = 0;
Andy Green251f6fa2010-11-03 11:13:06 +00002664 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +01002665 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +00002666 int opt = 1;
Peter Hinz56885f32011-03-02 22:03:47 +00002667 struct libwebsocket_context *context = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002668 unsigned int slen;
Andy Green9659f372011-01-27 22:01:43 +00002669 char *p;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002670 char hostname[1024] = "";
Andy Greena69f0512012-05-03 12:32:38 +08002671// struct hostent *he;
Andy Green0d338332011-02-12 11:57:43 +00002672 struct libwebsocket *wsi;
Andy Greena69f0512012-05-03 12:32:38 +08002673 struct sockaddr sa;
Andy Greenff95d7a2010-10-28 22:36:01 +01002674
Andy Green3faa9c72010-11-08 17:03:03 +00002675#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +00002676 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +00002677 char ssl_err_buf[512];
Andy Green3faa9c72010-11-08 17:03:03 +00002678#endif
2679
Andy Green43db0452013-01-10 19:50:35 +08002680 lwsl_info("Initial logging level %d\n", log_level);
Andy Greenc0d6b632013-01-12 23:42:17 +08002681 lwsl_info(" FD_HASHTABLE_MODULUS: %u\n", FD_HASHTABLE_MODULUS);
2682 lwsl_info(" MAX_CLIENTS: %u\n", MAX_CLIENTS);
2683 lwsl_info(" LWS_MAX_HEADER_NAME_LENGTH: %u\n", LWS_MAX_HEADER_NAME_LENGTH);
2684 lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
2685 lwsl_info(" LWS_INITIAL_HDR_ALLOC: %u\n", LWS_INITIAL_HDR_ALLOC);
2686 lwsl_info(" LWS_ADDITIONAL_HDR_ALLOC: %u\n", LWS_ADDITIONAL_HDR_ALLOC);
2687 lwsl_info(" MAX_USER_RX_BUFFER: %u\n", MAX_USER_RX_BUFFER);
2688 lwsl_info(" MAX_BROADCAST_PAYLOAD: %u\n", MAX_BROADCAST_PAYLOAD);
2689 lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
2690 lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE);
2691 lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED);
2692 lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT);
2693 lwsl_info(" CIPHERS_LIST_STRING: '%s'\n", CIPHERS_LIST_STRING);
2694 lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
2695 lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER);
Andy Green43db0452013-01-10 19:50:35 +08002696
Peter Hinz56885f32011-03-02 22:03:47 +00002697#ifdef _WIN32
2698 {
2699 WORD wVersionRequested;
2700 WSADATA wsaData;
2701 int err;
Andy Green6ee372f2012-04-09 15:09:01 +08002702 HMODULE wsdll;
Peter Hinz56885f32011-03-02 22:03:47 +00002703
2704 /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
2705 wVersionRequested = MAKEWORD(2, 2);
2706
2707 err = WSAStartup(wVersionRequested, &wsaData);
2708 if (err != 0) {
2709 /* Tell the user that we could not find a usable */
2710 /* Winsock DLL. */
Andy Green43db0452013-01-10 19:50:35 +08002711 lwsl_err("WSAStartup failed with error: %d\n", err);
Peter Hinz56885f32011-03-02 22:03:47 +00002712 return NULL;
2713 }
David Galeano7b11fec2011-10-04 19:55:18 +08002714
Andy Green6ee372f2012-04-09 15:09:01 +08002715 /* default to a poll() made out of select() */
2716 poll = emulated_poll;
David Galeano7b11fec2011-10-04 19:55:18 +08002717
Andy Green6ee372f2012-04-09 15:09:01 +08002718 /* if windows socket lib available, use his WSAPoll */
David Galeanocb193682013-01-09 15:29:00 +08002719 wsdll = GetModuleHandle(_T("Ws2_32.dll"));
Andy Green6ee372f2012-04-09 15:09:01 +08002720 if (wsdll)
2721 poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
Peter Hinz56885f32011-03-02 22:03:47 +00002722 }
2723#endif
2724
2725
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002726 context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context));
Peter Hinz56885f32011-03-02 22:03:47 +00002727 if (!context) {
Andy Green43db0452013-01-10 19:50:35 +08002728 lwsl_err("No memory for websocket context\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002729 return NULL;
2730 }
Peter Hinz56885f32011-03-02 22:03:47 +00002731 context->protocols = protocols;
2732 context->listen_port = port;
2733 context->http_proxy_port = 0;
2734 context->http_proxy_address[0] = '\0';
2735 context->options = options;
2736 context->fds_count = 0;
Andy Greend6e09112011-03-05 16:12:15 +00002737 context->extensions = extensions;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002738 context->last_timeout_check_s = 0;
Alon Levy0291eb32012-10-19 11:21:56 +02002739 context->user_space = user;
Andy Green9659f372011-01-27 22:01:43 +00002740
Peter Hinz56885f32011-03-02 22:03:47 +00002741#ifdef WIN32
2742 context->fd_random = 0;
2743#else
2744 context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
2745 if (context->fd_random < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002746 lwsl_err("Unable to open random device %s %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002747 SYSTEM_RANDOM_FILEPATH, context->fd_random);
Andy Green44eee682011-02-10 09:32:24 +00002748 return NULL;
2749 }
Peter Hinz56885f32011-03-02 22:03:47 +00002750#endif
Andy Green44eee682011-02-10 09:32:24 +00002751
Peter Hinz56885f32011-03-02 22:03:47 +00002752#ifdef LWS_OPENSSL_SUPPORT
2753 context->use_ssl = 0;
2754 context->ssl_ctx = NULL;
2755 context->ssl_client_ctx = NULL;
Andy Green2e24da02011-03-05 16:12:04 +00002756 openssl_websocket_private_data_index = 0;
Peter Hinz56885f32011-03-02 22:03:47 +00002757#endif
Andy Green2ac5a6f2011-01-28 10:00:18 +00002758
Andy Green788c4a82012-10-22 12:29:57 +01002759 if (options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME) {
Andy Greena69f0512012-05-03 12:32:38 +08002760
Andy Green788c4a82012-10-22 12:29:57 +01002761 strcpy(context->canonical_hostname, "unknown");
Andy Greena69f0512012-05-03 12:32:38 +08002762
Andy Green788c4a82012-10-22 12:29:57 +01002763 } else {
2764
2765 /* find canonical hostname */
2766
2767 hostname[(sizeof hostname) - 1] = '\0';
2768 memset(&sa, 0, sizeof(sa));
2769 sa.sa_family = AF_INET;
2770 sa.sa_data[(sizeof sa.sa_data) - 1] = '\0';
2771 gethostname(hostname, (sizeof hostname) - 1);
2772
2773 n = 0;
2774
David Galeanoed3c8402013-01-10 10:45:24 +08002775 if (strlen(hostname) < sizeof(sa.sa_data) - 1) {
Andy Green788c4a82012-10-22 12:29:57 +01002776 strcpy(sa.sa_data, hostname);
Andy Green43db0452013-01-10 19:50:35 +08002777 // lwsl_debug("my host name is %s\n", sa.sa_data);
Andy Green788c4a82012-10-22 12:29:57 +01002778 n = getnameinfo(&sa, sizeof(sa), hostname,
2779 (sizeof hostname) - 1, NULL, 0, 0);
2780 }
2781
2782 if (!n) {
2783 strncpy(context->canonical_hostname, hostname,
2784 sizeof context->canonical_hostname - 1);
2785 context->canonical_hostname[
2786 sizeof context->canonical_hostname - 1] = '\0';
2787 } else
2788 strncpy(context->canonical_hostname, hostname,
2789 sizeof context->canonical_hostname - 1);
2790
Andy Green43db0452013-01-10 19:50:35 +08002791 // lwsl_debug("context->canonical_hostname = %s\n",
Andy Green788c4a82012-10-22 12:29:57 +01002792 // context->canonical_hostname);
Andy Greena69f0512012-05-03 12:32:38 +08002793 }
2794
Andy Green9659f372011-01-27 22:01:43 +00002795 /* split the proxy ads:port if given */
2796
2797 p = getenv("http_proxy");
2798 if (p) {
Peter Hinz56885f32011-03-02 22:03:47 +00002799 strncpy(context->http_proxy_address, p,
Andy Green6ee372f2012-04-09 15:09:01 +08002800 sizeof context->http_proxy_address - 1);
Peter Hinz56885f32011-03-02 22:03:47 +00002801 context->http_proxy_address[
2802 sizeof context->http_proxy_address - 1] = '\0';
Andy Green9659f372011-01-27 22:01:43 +00002803
Peter Hinz56885f32011-03-02 22:03:47 +00002804 p = strchr(context->http_proxy_address, ':');
Andy Green9659f372011-01-27 22:01:43 +00002805 if (p == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002806 lwsl_err("http_proxy needs to be ads:port\n");
Andy Green9659f372011-01-27 22:01:43 +00002807 return NULL;
2808 }
2809 *p = '\0';
Peter Hinz56885f32011-03-02 22:03:47 +00002810 context->http_proxy_port = atoi(p + 1);
Andy Green9659f372011-01-27 22:01:43 +00002811
Andy Green43db0452013-01-10 19:50:35 +08002812 lwsl_debug("Using proxy %s:%u\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002813 context->http_proxy_address,
2814 context->http_proxy_port);
Andy Green9659f372011-01-27 22:01:43 +00002815 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002816
2817 if (port) {
2818
Andy Green3faa9c72010-11-08 17:03:03 +00002819#ifdef LWS_OPENSSL_SUPPORT
Peter Hinz56885f32011-03-02 22:03:47 +00002820 context->use_ssl = ssl_cert_filepath != NULL &&
Andy Green90c7cbc2011-01-27 06:26:52 +00002821 ssl_private_key_filepath != NULL;
Peter Hinz56885f32011-03-02 22:03:47 +00002822 if (context->use_ssl)
Andy Green43db0452013-01-10 19:50:35 +08002823 lwsl_info(" Compiled with SSL support, using it\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002824 else
Andy Green43db0452013-01-10 19:50:35 +08002825 lwsl_info(" Compiled with SSL support, not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +00002826
Andy Green90c7cbc2011-01-27 06:26:52 +00002827#else
2828 if (ssl_cert_filepath != NULL &&
2829 ssl_private_key_filepath != NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002830 lwsl_info(" Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +00002831 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002832 }
Andy Green43db0452013-01-10 19:50:35 +08002833 lwsl_info(" Compiled without SSL support, "
Andy Green90c7cbc2011-01-27 06:26:52 +00002834 "serving unencrypted\n");
2835#endif
2836 }
2837
2838 /* ignore SIGPIPE */
Peter Hinz56885f32011-03-02 22:03:47 +00002839#ifdef WIN32
2840#else
Andy Green90c7cbc2011-01-27 06:26:52 +00002841 signal(SIGPIPE, sigpipe_handler);
Peter Hinz56885f32011-03-02 22:03:47 +00002842#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002843
2844
2845#ifdef LWS_OPENSSL_SUPPORT
2846
2847 /* basic openssl init */
2848
2849 SSL_library_init();
2850
2851 OpenSSL_add_all_algorithms();
2852 SSL_load_error_strings();
2853
Andy Green2e24da02011-03-05 16:12:04 +00002854 openssl_websocket_private_data_index =
Andy Green6901cb32011-02-21 08:06:47 +00002855 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
2856
Andy Green90c7cbc2011-01-27 06:26:52 +00002857 /*
2858 * Firefox insists on SSLv23 not SSLv3
2859 * Konq disables SSLv2 by default now, SSLv23 works
2860 */
2861
2862 method = (SSL_METHOD *)SSLv23_server_method();
2863 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002864 lwsl_err("problem creating ssl method: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002865 ERR_error_string(ERR_get_error(), ssl_err_buf));
2866 return NULL;
2867 }
Peter Hinz56885f32011-03-02 22:03:47 +00002868 context->ssl_ctx = SSL_CTX_new(method); /* create context */
2869 if (!context->ssl_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002870 lwsl_err("problem creating ssl context: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002871 ERR_error_string(ERR_get_error(), ssl_err_buf));
2872 return NULL;
2873 }
2874
David Galeanocc148e42013-01-10 10:18:59 +08002875#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002876 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002877#endif
David Galeano77a677c2013-01-10 10:14:12 +08002878 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002879 SSL_CTX_set_cipher_list(context->ssl_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002880
Andy Green90c7cbc2011-01-27 06:26:52 +00002881 /* client context */
Andy Green6ee372f2012-04-09 15:09:01 +08002882
2883 if (port == CONTEXT_PORT_NO_LISTEN) {
Peter Hinz56885f32011-03-02 22:03:47 +00002884 method = (SSL_METHOD *)SSLv23_client_method();
2885 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002886 lwsl_err("problem creating ssl method: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002887 ERR_error_string(ERR_get_error(), ssl_err_buf));
2888 return NULL;
2889 }
2890 /* create context */
2891 context->ssl_client_ctx = SSL_CTX_new(method);
2892 if (!context->ssl_client_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002893 lwsl_err("problem creating ssl context: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002894 ERR_error_string(ERR_get_error(), ssl_err_buf));
2895 return NULL;
2896 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002897
David Galeanocc148e42013-01-10 10:18:59 +08002898#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002899 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002900#endif
David Galeano77a677c2013-01-10 10:14:12 +08002901 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002902 SSL_CTX_set_cipher_list(context->ssl_client_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002903
Peter Hinz56885f32011-03-02 22:03:47 +00002904 /* openssl init for cert verification (for client sockets) */
David Galeano2f82be82013-01-09 16:25:54 +08002905 if (!ssl_ca_filepath) {
2906 if (!SSL_CTX_load_verify_locations(
2907 context->ssl_client_ctx, NULL,
2908 LWS_OPENSSL_CLIENT_CERTS))
Andy Green43db0452013-01-10 19:50:35 +08002909 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002910 "Unable to load SSL Client certs from %s "
2911 "(set by --with-client-cert-dir= in configure) -- "
2912 " client ssl isn't going to work",
2913 LWS_OPENSSL_CLIENT_CERTS);
2914 } else
2915 if (!SSL_CTX_load_verify_locations(
2916 context->ssl_client_ctx, ssl_ca_filepath,
2917 NULL))
Andy Green43db0452013-01-10 19:50:35 +08002918 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002919 "Unable to load SSL Client certs "
2920 "file from %s -- client ssl isn't "
2921 "going to work", ssl_ca_filepath);
Peter Hinz56885f32011-03-02 22:03:47 +00002922
2923 /*
2924 * callback allowing user code to load extra verification certs
2925 * helping the client to verify server identity
2926 */
2927
2928 context->protocols[0].callback(context, NULL,
2929 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
2930 context->ssl_client_ctx, NULL, 0);
Andy Green90c7cbc2011-01-27 06:26:52 +00002931 }
Andy Green6ee372f2012-04-09 15:09:01 +08002932
Andy Greenc6bf2c22011-02-20 11:10:47 +00002933 /* as a server, are we requiring clients to identify themselves? */
2934
2935 if (options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
2936
2937 /* absolutely require the client cert */
Andy Green6ee372f2012-04-09 15:09:01 +08002938
Peter Hinz56885f32011-03-02 22:03:47 +00002939 SSL_CTX_set_verify(context->ssl_ctx,
Andy Green6901cb32011-02-21 08:06:47 +00002940 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2941 OpenSSL_verify_callback);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002942
2943 /*
2944 * give user code a chance to load certs into the server
2945 * allowing it to verify incoming client certs
2946 */
2947
Peter Hinz56885f32011-03-02 22:03:47 +00002948 context->protocols[0].callback(context, NULL,
Andy Greenc6bf2c22011-02-20 11:10:47 +00002949 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
Peter Hinz56885f32011-03-02 22:03:47 +00002950 context->ssl_ctx, NULL, 0);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002951 }
2952
Peter Hinz56885f32011-03-02 22:03:47 +00002953 if (context->use_ssl) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002954
2955 /* openssl init for server sockets */
2956
Andy Green3faa9c72010-11-08 17:03:03 +00002957 /* set the local certificate from CertFile */
David Galeano9b3d4b22013-01-10 10:11:21 +08002958 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
2959 ssl_cert_filepath);
Andy Green3faa9c72010-11-08 17:03:03 +00002960 if (n != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002961 lwsl_err("problem getting cert '%s': %s\n",
Andy Green3faa9c72010-11-08 17:03:03 +00002962 ssl_cert_filepath,
2963 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002964 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002965 }
2966 /* set the private key from KeyFile */
Peter Hinz56885f32011-03-02 22:03:47 +00002967 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
2968 ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002969 lwsl_err("ssl problem getting key '%s': %s\n",
Andy Green018d8eb2010-11-08 21:04:23 +00002970 ssl_private_key_filepath,
2971 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002972 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002973 }
2974 /* verify private key */
Peter Hinz56885f32011-03-02 22:03:47 +00002975 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
Andy Green43db0452013-01-10 19:50:35 +08002976 lwsl_err("Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +00002977 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002978 }
2979
2980 /* SSL is happy and has a cert it's content with */
2981 }
2982#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002983
Andy Greendf736162011-01-18 15:39:02 +00002984 /* selftest */
2985
2986 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +00002987 return NULL;
Andy Greendf736162011-01-18 15:39:02 +00002988
Andy Green0d338332011-02-12 11:57:43 +00002989 /* fd hashtable init */
2990
2991 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002992 context->fd_hashtable[n].length = 0;
Andy Green0d338332011-02-12 11:57:43 +00002993
Andy Greenb45993c2010-12-18 15:13:50 +00002994 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +00002995
Andy Green4739e5c2011-01-22 12:51:57 +00002996 if (port) {
Andy Green8f037e42010-12-19 22:13:26 +00002997
Andy Green4739e5c2011-01-22 12:51:57 +00002998 sockfd = socket(AF_INET, SOCK_STREAM, 0);
2999 if (sockfd < 0) {
Andy Greenf7609e92013-01-14 13:10:55 +08003000 lwsl_err("ERROR opening socket\n");
Andy Green4739e5c2011-01-22 12:51:57 +00003001 return NULL;
3002 }
Andy Green775c0dd2010-10-29 14:15:22 +01003003
Andy Green4739e5c2011-01-22 12:51:57 +00003004 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08003005 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
3006 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00003007
3008 /* Disable Nagle */
3009 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08003010 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
3011 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00003012
Andy Green4739e5c2011-01-22 12:51:57 +00003013 bzero((char *) &serv_addr, sizeof(serv_addr));
3014 serv_addr.sin_family = AF_INET;
Peter Hinz56885f32011-03-02 22:03:47 +00003015 if (interf == NULL)
Andy Green32375b72011-02-19 08:32:53 +00003016 serv_addr.sin_addr.s_addr = INADDR_ANY;
3017 else
Peter Hinz56885f32011-03-02 22:03:47 +00003018 interface_to_sa(interf, &serv_addr,
Andy Green32375b72011-02-19 08:32:53 +00003019 sizeof(serv_addr));
Andy Green4739e5c2011-01-22 12:51:57 +00003020 serv_addr.sin_port = htons(port);
3021
3022 n = bind(sockfd, (struct sockaddr *) &serv_addr,
3023 sizeof(serv_addr));
3024 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003025 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Green8f037e42010-12-19 22:13:26 +00003026 port, n, errno);
Andy Green41c58032013-01-12 13:21:08 +08003027 close(sockfd);
Andy Green4739e5c2011-01-22 12:51:57 +00003028 return NULL;
3029 }
Andy Green0d338332011-02-12 11:57:43 +00003030
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003031 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08003032 if (wsi == NULL) {
3033 lwsl_err("Out of mem\n");
3034 close(sockfd);
3035 return NULL;
3036 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003037 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00003038 wsi->sock = sockfd;
Andy Greend6e09112011-03-05 16:12:15 +00003039 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00003040 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
Peter Hinz56885f32011-03-02 22:03:47 +00003041 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00003042
Andy Greena824d182013-01-15 20:52:29 +08003043 listen(sockfd, LWS_SOMAXCONN);
Andy Green43db0452013-01-10 19:50:35 +08003044 lwsl_info(" Listening on port %d\n", port);
Andy Green0d338332011-02-12 11:57:43 +00003045
3046 /* list in the internal poll array */
Andy Green6ee372f2012-04-09 15:09:01 +08003047
Peter Hinz56885f32011-03-02 22:03:47 +00003048 context->fds[context->fds_count].fd = sockfd;
3049 context->fds[context->fds_count++].events = POLLIN;
Andy Green3221f922011-02-12 13:14:11 +00003050
3051 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00003052 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00003053 LWS_CALLBACK_ADD_POLL_FD,
3054 (void *)(long)sockfd, NULL, POLLIN);
3055
Andy Green8f037e42010-12-19 22:13:26 +00003056 }
Andy Greenb45993c2010-12-18 15:13:50 +00003057
Andy Green6ee372f2012-04-09 15:09:01 +08003058 /*
3059 * drop any root privs for this process
3060 * to listen on port < 1023 we would have needed root, but now we are
3061 * listening, we don't want the power for anything else
3062 */
Peter Hinz56885f32011-03-02 22:03:47 +00003063#ifdef WIN32
3064#else
Andy Green3faa9c72010-11-08 17:03:03 +00003065 if (gid != -1)
3066 if (setgid(gid))
Andy Green43db0452013-01-10 19:50:35 +08003067 lwsl_warn("setgid: %s\n", strerror(errno));
Andy Green3faa9c72010-11-08 17:03:03 +00003068 if (uid != -1)
3069 if (setuid(uid))
Andy Green43db0452013-01-10 19:50:35 +08003070 lwsl_warn("setuid: %s\n", strerror(errno));
Peter Hinz56885f32011-03-02 22:03:47 +00003071#endif
Andy Greenb45993c2010-12-18 15:13:50 +00003072
3073 /* set up our internal broadcast trigger sockets per-protocol */
3074
Peter Hinz56885f32011-03-02 22:03:47 +00003075 for (context->count_protocols = 0;
3076 protocols[context->count_protocols].callback;
3077 context->count_protocols++) {
Andy Green2d1301e2011-05-24 10:14:41 +01003078
Andy Green43db0452013-01-10 19:50:35 +08003079 lwsl_parser(" Protocol: %s\n",
3080 protocols[context->count_protocols].name);
Andy Green2d1301e2011-05-24 10:14:41 +01003081
Peter Hinz56885f32011-03-02 22:03:47 +00003082 protocols[context->count_protocols].owning_server = context;
3083 protocols[context->count_protocols].protocol_index =
3084 context->count_protocols;
Andy Greenb45993c2010-12-18 15:13:50 +00003085
3086 fd = socket(AF_INET, SOCK_STREAM, 0);
3087 if (fd < 0) {
Andy Greenf7609e92013-01-14 13:10:55 +08003088 lwsl_err("ERROR opening socket\n");
Andy Greene92cd172011-01-19 13:11:55 +00003089 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003090 }
Andy Green8f037e42010-12-19 22:13:26 +00003091
Andy Greenb45993c2010-12-18 15:13:50 +00003092 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08003093 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt,
3094 sizeof(opt));
Andy Greenb45993c2010-12-18 15:13:50 +00003095
3096 bzero((char *) &serv_addr, sizeof(serv_addr));
3097 serv_addr.sin_family = AF_INET;
3098 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3099 serv_addr.sin_port = 0; /* pick the port for us */
3100
3101 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
3102 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003103 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Greenb45993c2010-12-18 15:13:50 +00003104 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +00003105 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003106 }
3107
3108 slen = sizeof cli_addr;
3109 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
3110 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003111 lwsl_err("getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +00003112 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003113 }
Peter Hinz56885f32011-03-02 22:03:47 +00003114 protocols[context->count_protocols].broadcast_socket_port =
Andy Greenb45993c2010-12-18 15:13:50 +00003115 ntohs(cli_addr.sin_port);
3116 listen(fd, 5);
3117
Andy Green43db0452013-01-10 19:50:35 +08003118 lwsl_debug(" Protocol %s broadcast socket %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00003119 protocols[context->count_protocols].name,
Andy Greenb45993c2010-12-18 15:13:50 +00003120 ntohs(cli_addr.sin_port));
3121
Andy Green0d338332011-02-12 11:57:43 +00003122 /* dummy wsi per broadcast proxy socket */
3123
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003124 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08003125 if (wsi == NULL) {
3126 lwsl_err("Out of mem\n");
3127 close(fd);
3128 return NULL;
3129 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003130 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00003131 wsi->sock = fd;
3132 wsi->mode = LWS_CONNMODE_BROADCAST_PROXY_LISTENER;
Andy Greend6e09112011-03-05 16:12:15 +00003133 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00003134 /* note which protocol we are proxying */
Peter Hinz56885f32011-03-02 22:03:47 +00003135 wsi->protocol_index_for_broadcast_proxy =
3136 context->count_protocols;
3137 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00003138
3139 /* list in internal poll array */
3140
Peter Hinz56885f32011-03-02 22:03:47 +00003141 context->fds[context->fds_count].fd = fd;
3142 context->fds[context->fds_count].events = POLLIN;
3143 context->fds[context->fds_count].revents = 0;
3144 context->fds_count++;
Andy Green3221f922011-02-12 13:14:11 +00003145
3146 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00003147 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00003148 LWS_CALLBACK_ADD_POLL_FD,
3149 (void *)(long)fd, NULL, POLLIN);
Andy Greenb45993c2010-12-18 15:13:50 +00003150 }
3151
Andy Greena41314f2011-05-23 10:00:03 +01003152 /*
3153 * give all extensions a chance to create any per-context
3154 * allocations they need
3155 */
3156
3157 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
3158 if (port)
3159 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
Andrew Chambersd5512172012-05-20 08:17:09 +08003160
3161 if (extensions) {
3162 while (extensions->callback) {
Andy Green43db0452013-01-10 19:50:35 +08003163 lwsl_ext(" Extension: %s\n", extensions->name);
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003164 extensions->callback(context, extensions, NULL,
3165 (enum libwebsocket_extension_callback_reasons)m,
3166 NULL, NULL, 0);
Andrew Chambersd5512172012-05-20 08:17:09 +08003167 extensions++;
3168 }
Andy Greena41314f2011-05-23 10:00:03 +01003169 }
3170
Peter Hinz56885f32011-03-02 22:03:47 +00003171 return context;
Andy Greene92cd172011-01-19 13:11:55 +00003172}
Andy Greenb45993c2010-12-18 15:13:50 +00003173
Andy Green4739e5c2011-01-22 12:51:57 +00003174
Andy Greened11a022011-01-20 10:23:50 +00003175#ifndef LWS_NO_FORK
3176
Andy Greene92cd172011-01-19 13:11:55 +00003177/**
3178 * libwebsockets_fork_service_loop() - Optional helper function forks off
3179 * a process for the websocket server loop.
Andy Green6964bb52011-01-23 16:50:33 +00003180 * You don't have to use this but if not, you
3181 * have to make sure you are calling
3182 * libwebsocket_service periodically to service
3183 * the websocket traffic
Peter Hinz56885f32011-03-02 22:03:47 +00003184 * @context: server context returned by creation function
Andy Greene92cd172011-01-19 13:11:55 +00003185 */
Andy Greenb45993c2010-12-18 15:13:50 +00003186
Andy Greene92cd172011-01-19 13:11:55 +00003187int
Peter Hinz56885f32011-03-02 22:03:47 +00003188libwebsockets_fork_service_loop(struct libwebsocket_context *context)
Andy Greene92cd172011-01-19 13:11:55 +00003189{
Andy Greene92cd172011-01-19 13:11:55 +00003190 int fd;
3191 struct sockaddr_in cli_addr;
3192 int n;
Andy Green3221f922011-02-12 13:14:11 +00003193 int p;
Andy Greenb45993c2010-12-18 15:13:50 +00003194
Andy Greened11a022011-01-20 10:23:50 +00003195 n = fork();
3196 if (n < 0)
3197 return n;
3198
3199 if (!n) {
3200
3201 /* main process context */
3202
Andy Green3221f922011-02-12 13:14:11 +00003203 /*
3204 * set up the proxy sockets to allow broadcast from
3205 * service process context
3206 */
3207
Peter Hinz56885f32011-03-02 22:03:47 +00003208 for (p = 0; p < context->count_protocols; p++) {
Andy Greened11a022011-01-20 10:23:50 +00003209 fd = socket(AF_INET, SOCK_STREAM, 0);
3210 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003211 lwsl_err("Unable to create socket\n");
Andy Greened11a022011-01-20 10:23:50 +00003212 return -1;
3213 }
3214 cli_addr.sin_family = AF_INET;
3215 cli_addr.sin_port = htons(
Peter Hinz56885f32011-03-02 22:03:47 +00003216 context->protocols[p].broadcast_socket_port);
Andy Greened11a022011-01-20 10:23:50 +00003217 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3218 n = connect(fd, (struct sockaddr *)&cli_addr,
3219 sizeof cli_addr);
3220 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003221 lwsl_err("Unable to connect to "
Andy Greened11a022011-01-20 10:23:50 +00003222 "broadcast socket %d, %s\n",
Andy Green3221f922011-02-12 13:14:11 +00003223 n, strerror(errno));
Andy Greened11a022011-01-20 10:23:50 +00003224 return -1;
3225 }
3226
Peter Hinz56885f32011-03-02 22:03:47 +00003227 context->protocols[p].broadcast_socket_user_fd = fd;
Andy Greened11a022011-01-20 10:23:50 +00003228 }
3229
Andy Greene92cd172011-01-19 13:11:55 +00003230 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00003231 }
3232
Artem Baguinski91531662011-12-14 22:14:03 +01003233#ifdef HAVE_SYS_PRCTL_H
Andy Greenb45993c2010-12-18 15:13:50 +00003234 /* we want a SIGHUP when our parent goes down */
3235 prctl(PR_SET_PDEATHSIG, SIGHUP);
Artem Baguinski91531662011-12-14 22:14:03 +01003236#endif
Andy Greenb45993c2010-12-18 15:13:50 +00003237
3238 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +00003239
Artem Baguinski91531662011-12-14 22:14:03 +01003240 while (1) {
Peter Hinz56885f32011-03-02 22:03:47 +00003241 if (libwebsocket_service(context, 1000))
Andy Green3928f612012-07-20 12:58:38 +08003242 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003243//#ifndef HAVE_SYS_PRCTL_H
Artem Baguinski91531662011-12-14 22:14:03 +01003244/*
3245 * on systems without prctl() (i.e. anything but linux) we can notice that our
3246 * parent is dead if getppid() returns 1. FIXME apparently this is not true for
3247 * solaris, could remember ppid right after fork and wait for it to change.
3248 */
3249
3250 if (getppid() == 1)
3251 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003252//#endif
Artem Baguinski91531662011-12-14 22:14:03 +01003253 }
3254
Andy Green8f037e42010-12-19 22:13:26 +00003255
Andy Green3928f612012-07-20 12:58:38 +08003256 return 1;
Andy Greenff95d7a2010-10-28 22:36:01 +01003257}
3258
Andy Greened11a022011-01-20 10:23:50 +00003259#endif
3260
Andy Greenb45993c2010-12-18 15:13:50 +00003261/**
3262 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +00003263 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +00003264 * @wsi: pointer to struct websocket you want to know the protocol of
3265 *
Andy Green8f037e42010-12-19 22:13:26 +00003266 *
3267 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +00003268 * the callback.
3269 */
Andy Greenab990e42010-10-31 12:42:52 +00003270
Andy Greenb45993c2010-12-18 15:13:50 +00003271const struct libwebsocket_protocols *
3272libwebsockets_get_protocol(struct libwebsocket *wsi)
3273{
3274 return wsi->protocol;
3275}
3276
3277/**
Andy Greene92cd172011-01-19 13:11:55 +00003278 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +00003279 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +00003280 * @protocol: pointer to the protocol you will broadcast to all members of
3281 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +00003282 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
3283 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
3284 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +00003285 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +00003286 *
3287 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +00003288 * the given protocol. It does not send the data directly; instead it calls
3289 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
3290 * wants to actually send the data for that connection, the callback itself
3291 * should call libwebsocket_write().
3292 *
3293 * libwebsockets_broadcast() can be called from another fork context without
3294 * having to take any care about data visibility between the processes, it'll
3295 * "just work".
3296 */
3297
3298
3299int
Andy Green8f037e42010-12-19 22:13:26 +00003300libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +00003301 unsigned char *buf, size_t len)
3302{
Peter Hinz56885f32011-03-02 22:03:47 +00003303 struct libwebsocket_context *context = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +00003304 int n;
Andy Green0d338332011-02-12 11:57:43 +00003305 int m;
Andy Green6ee372f2012-04-09 15:09:01 +08003306 struct libwebsocket *wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00003307
3308 if (!protocol->broadcast_socket_user_fd) {
3309 /*
Andy Greene92cd172011-01-19 13:11:55 +00003310 * We are either running unforked / flat, or we are being
3311 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +00003312 * eg, from a callback. In that case don't use sockets for
3313 * broadcast IPC (since we can't open a socket connection to
3314 * a socket listening on our own thread) but directly do the
3315 * send action.
3316 *
3317 * Locking is not needed because we are by definition being
3318 * called in the poll thread context and are serialized.
3319 */
3320
Andy Green0d338332011-02-12 11:57:43 +00003321 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003322
Peter Hinz56885f32011-03-02 22:03:47 +00003323 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003324
Peter Hinz56885f32011-03-02 22:03:47 +00003325 wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00003326
Andy Green0d338332011-02-12 11:57:43 +00003327 if (wsi->mode != LWS_CONNMODE_WS_SERVING)
3328 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00003329
Andy Green0d338332011-02-12 11:57:43 +00003330 /*
3331 * never broadcast to
3332 * non-established connections
3333 */
3334 if (wsi->state != WSI_STATE_ESTABLISHED)
3335 continue;
3336
3337 /* only broadcast to guys using
3338 * requested protocol
3339 */
3340 if (wsi->protocol != protocol)
3341 continue;
3342
Peter Hinz56885f32011-03-02 22:03:47 +00003343 wsi->protocol->callback(context, wsi,
Andy Green8f037e42010-12-19 22:13:26 +00003344 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00003345 wsi->user_space,
Andy Greenb45993c2010-12-18 15:13:50 +00003346 buf, len);
Andy Green0d338332011-02-12 11:57:43 +00003347 }
Andy Greenb45993c2010-12-18 15:13:50 +00003348 }
3349
3350 return 0;
3351 }
3352
Andy Green0ca6a172010-12-19 20:50:01 +00003353 /*
3354 * We're being called from a different process context than the server
3355 * loop. Instead of broadcasting directly, we send our
3356 * payload on a socket to do the IPC; the server process will serialize
3357 * the broadcast action in its main poll() loop.
3358 *
3359 * There's one broadcast socket listening for each protocol supported
3360 * set up when the websocket server initializes
3361 */
3362
Andy Green6964bb52011-01-23 16:50:33 +00003363 n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
Andy Greenb45993c2010-12-18 15:13:50 +00003364
3365 return n;
3366}
Andy Green82c3d542011-03-07 21:16:31 +00003367
3368int
3369libwebsocket_is_final_fragment(struct libwebsocket *wsi)
3370{
3371 return wsi->final;
3372}
Alex Bligh49146db2011-11-07 17:19:25 +08003373
David Galeanoe2cf9922013-01-09 18:06:55 +08003374unsigned char
3375libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
3376{
3377 return wsi->rsv;
3378}
3379
Alex Bligh49146db2011-11-07 17:19:25 +08003380void *
3381libwebsocket_ensure_user_space(struct libwebsocket *wsi)
3382{
3383 /* allocate the per-connection user memory (if any) */
3384
3385 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
3386 wsi->user_space = malloc(
3387 wsi->protocol->per_session_data_size);
3388 if (wsi->user_space == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08003389 lwsl_err("Out of memory for conn user space\n");
Alex Bligh49146db2011-11-07 17:19:25 +08003390 return NULL;
3391 }
Andy Green6ee372f2012-04-09 15:09:01 +08003392 memset(wsi->user_space, 0,
3393 wsi->protocol->per_session_data_size);
Alex Bligh49146db2011-11-07 17:19:25 +08003394 }
3395 return wsi->user_space;
3396}
Andy Green43db0452013-01-10 19:50:35 +08003397
Andy Greende8f27a2013-01-12 09:17:42 +08003398
3399static void lwsl_emit_stderr(const char *line)
3400{
3401 fprintf(stderr, "%s", line);
3402}
3403
Andy Green43db0452013-01-10 19:50:35 +08003404void _lws_log(int filter, const char *format, ...)
3405{
Andy Greende8f27a2013-01-12 09:17:42 +08003406 char buf[256];
Andy Green43db0452013-01-10 19:50:35 +08003407 va_list ap;
3408 int n;
Andy Greende8f27a2013-01-12 09:17:42 +08003409 int pos = 0;
Andy Green8a265092013-01-12 09:25:07 +08003410 struct timeval tv;
Andy Green43db0452013-01-10 19:50:35 +08003411
3412 if (!(log_level & filter))
3413 return;
3414
Andy Green8a265092013-01-12 09:25:07 +08003415 gettimeofday(&tv, NULL);
3416
Andy Green43db0452013-01-10 19:50:35 +08003417 for (n = 0; n < LLL_COUNT; n++)
3418 if (filter == (1 << n)) {
Andy Green8a265092013-01-12 09:25:07 +08003419 pos = sprintf(buf, "[%ld:%04ld] %s: ", tv.tv_sec,
3420 tv.tv_usec / 100, log_level_names[n]);
Andy Green43db0452013-01-10 19:50:35 +08003421 break;
3422 }
3423
3424 va_start(ap, format);
Andy Greende8f27a2013-01-12 09:17:42 +08003425 vsnprintf(buf + pos, (sizeof buf) - pos, format, ap);
3426 buf[(sizeof buf) - 1] = '\0';
3427 va_end(ap);
3428
3429 lwsl_emit(buf);
Andy Green43db0452013-01-10 19:50:35 +08003430}
3431
3432/**
3433 * lws_set_log_level() - Set the logging bitfield
3434 * @level: OR together the LLL_ debug contexts you want output from
Andy Greende8f27a2013-01-12 09:17:42 +08003435 * @log_emit_function: NULL to leave it as it is, or a user-supplied
3436 * function to perform log string emission instead of
3437 * the default stderr one.
Andy Green43db0452013-01-10 19:50:35 +08003438 *
Andy Greende8f27a2013-01-12 09:17:42 +08003439 * log level defaults to "err" and "warn" contexts enabled only and
3440 * emission on stderr.
Andy Green43db0452013-01-10 19:50:35 +08003441 */
3442
Andy Greende8f27a2013-01-12 09:17:42 +08003443void lws_set_log_level(int level, void (*log_emit_function)(const char *line))
Andy Green43db0452013-01-10 19:50:35 +08003444{
3445 log_level = level;
Andy Greende8f27a2013-01-12 09:17:42 +08003446 if (log_emit_function)
3447 lwsl_emit = log_emit_function;
Andy Green43db0452013-01-10 19:50:35 +08003448}