blob: 242bc729e2b059368d6e5e8145f116e1bf340889 [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);
Peter Hinz56885f32011-03-02 22:03:47 +0000395#ifdef WIN32
396 closesocket(n);
397#else
Andy Green3faa9c72010-11-08 17:03:03 +0000398 close(n);
Peter Hinz56885f32011-03-02 22:03:47 +0000399#endif
Andy Green3faa9c72010-11-08 17:03:03 +0000400 SSL_free(wsi->ssl);
401 } else {
402#endif
403 shutdown(wsi->sock, SHUT_RDWR);
Peter Hinz56885f32011-03-02 22:03:47 +0000404#ifdef WIN32
Andy Green66a16f32011-05-24 22:07:45 +0100405 if (wsi->sock)
406 closesocket(wsi->sock);
Peter Hinz56885f32011-03-02 22:03:47 +0000407#else
Andy Green66a16f32011-05-24 22:07:45 +0100408 if (wsi->sock)
409 close(wsi->sock);
Peter Hinz56885f32011-03-02 22:03:47 +0000410#endif
Andy Green3faa9c72010-11-08 17:03:03 +0000411#ifdef LWS_OPENSSL_SUPPORT
412 }
413#endif
David Brooks2c60d952012-04-20 12:19:01 +0800414 if (wsi->protocol && wsi->protocol->per_session_data_size && wsi->user_space) /* user code may own */
Andy Green4f3943a2010-11-12 10:44:16 +0000415 free(wsi->user_space);
416
Andy Green251f6fa2010-11-03 11:13:06 +0000417 free(wsi);
418}
419
Andy Green07034092011-02-13 08:37:12 +0000420/**
Andy Greenf7ee5492011-02-13 09:04:21 +0000421 * libwebsockets_hangup_on_client() - Server calls to terminate client
Andy Green6ee372f2012-04-09 15:09:01 +0800422 * connection
Peter Hinz56885f32011-03-02 22:03:47 +0000423 * @context: libwebsockets context
Andy Greenf7ee5492011-02-13 09:04:21 +0000424 * @fd: Connection socket descriptor
425 */
426
427void
Peter Hinz56885f32011-03-02 22:03:47 +0000428libwebsockets_hangup_on_client(struct libwebsocket_context *context, int fd)
Andy Greenf7ee5492011-02-13 09:04:21 +0000429{
Peter Hinz56885f32011-03-02 22:03:47 +0000430 struct libwebsocket *wsi = wsi_from_fd(context, fd);
Andy Greenf7ee5492011-02-13 09:04:21 +0000431
432 if (wsi == NULL)
433 return;
434
Peter Hinz56885f32011-03-02 22:03:47 +0000435 libwebsocket_close_and_free_session(context, wsi,
Andy Green6da560c2011-02-26 11:06:27 +0000436 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenf7ee5492011-02-13 09:04:21 +0000437}
438
439
440/**
Andy Green07034092011-02-13 08:37:12 +0000441 * libwebsockets_get_peer_addresses() - Get client address information
442 * @fd: Connection socket descriptor
443 * @name: Buffer to take client address name
444 * @name_len: Length of client address name buffer
445 * @rip: Buffer to take client address IP qotted quad
446 * @rip_len: Length of client address IP buffer
447 *
448 * This function fills in @name and @rip with the name and IP of
Andy Green6ee372f2012-04-09 15:09:01 +0800449 * the client connected with socket descriptor @fd. Names may be
450 * truncated if there is not enough room. If either cannot be
451 * determined, they will be returned as valid zero-length strings.
Andy Green07034092011-02-13 08:37:12 +0000452 */
453
454void
455libwebsockets_get_peer_addresses(int fd, char *name, int name_len,
456 char *rip, int rip_len)
457{
458 unsigned int len;
459 struct sockaddr_in sin;
460 struct hostent *host;
461 struct hostent *host1;
462 char ip[128];
Andy Greenf92def72011-03-09 15:02:20 +0000463 unsigned char *p;
Andy Green07034092011-02-13 08:37:12 +0000464 int n;
David Galeanocb193682013-01-09 15:29:00 +0800465#ifdef AF_LOCAL
466 struct sockaddr_un *un;
467#endif
Andy Green07034092011-02-13 08:37:12 +0000468
469 rip[0] = '\0';
470 name[0] = '\0';
471
472 len = sizeof sin;
473 if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
474 perror("getpeername");
475 return;
476 }
Andy Green6ee372f2012-04-09 15:09:01 +0800477
Andy Green07034092011-02-13 08:37:12 +0000478 host = gethostbyaddr((char *) &sin.sin_addr, sizeof sin.sin_addr,
479 AF_INET);
480 if (host == NULL) {
481 perror("gethostbyaddr");
482 return;
483 }
484
485 strncpy(name, host->h_name, name_len);
486 name[name_len - 1] = '\0';
487
488 host1 = gethostbyname(host->h_name);
489 if (host1 == NULL)
490 return;
Andy Greenf92def72011-03-09 15:02:20 +0000491 p = (unsigned char *)host1;
Andy Green07034092011-02-13 08:37:12 +0000492 n = 0;
493 while (p != NULL) {
Andy Greenf92def72011-03-09 15:02:20 +0000494 p = (unsigned char *)host1->h_addr_list[n++];
Andy Green07034092011-02-13 08:37:12 +0000495 if (p == NULL)
496 continue;
Peter Hinzbb45a902011-03-10 18:14:01 +0000497 if ((host1->h_addrtype != AF_INET)
498#ifdef AF_LOCAL
499 && (host1->h_addrtype != AF_LOCAL)
500#endif
501 )
Andy Green07034092011-02-13 08:37:12 +0000502 continue;
503
Andy Green7627af52011-03-09 15:13:52 +0000504 if (host1->h_addrtype == AF_INET)
505 sprintf(ip, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
Peter Hinzbb45a902011-03-10 18:14:01 +0000506#ifdef AF_LOCAL
Andy Green7627af52011-03-09 15:13:52 +0000507 else {
508 un = (struct sockaddr_un *)p;
Andy Green6ee372f2012-04-09 15:09:01 +0800509 strncpy(ip, un->sun_path, sizeof(ip) - 1);
Andy Green7627af52011-03-09 15:13:52 +0000510 ip[sizeof(ip) - 1] = '\0';
511 }
Peter Hinzbb45a902011-03-10 18:14:01 +0000512#endif
Andy Green07034092011-02-13 08:37:12 +0000513 p = NULL;
514 strncpy(rip, ip, rip_len);
515 rip[rip_len - 1] = '\0';
516 }
517}
Andy Green9f990342011-02-12 11:57:45 +0000518
Peter Hinz56885f32011-03-02 22:03:47 +0000519int libwebsockets_get_random(struct libwebsocket_context *context,
520 void *buf, int len)
521{
522 int n;
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800523 char *p = (char *)buf;
Peter Hinz56885f32011-03-02 22:03:47 +0000524
525#ifdef WIN32
526 for (n = 0; n < len; n++)
527 p[n] = (unsigned char)rand();
528#else
529 n = read(context->fd_random, p, len);
530#endif
531
532 return n;
533}
534
Andy Green2836c642011-03-07 20:47:41 +0000535unsigned char *
536libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md)
537{
538 return SHA1(d, n, md);
539}
540
Andy Greeneeaacb32011-03-01 20:44:24 +0000541void libwebsockets_00_spaceout(char *key, int spaces, int seed)
542{
543 char *p;
Andy Green6ee372f2012-04-09 15:09:01 +0800544
Andy Greeneeaacb32011-03-01 20:44:24 +0000545 key++;
546 while (spaces--) {
547 if (*key && (seed & 1))
548 key++;
549 seed >>= 1;
Andy Green6ee372f2012-04-09 15:09:01 +0800550
Andy Greeneeaacb32011-03-01 20:44:24 +0000551 p = key + strlen(key);
552 while (p >= key) {
553 p[1] = p[0];
554 p--;
555 }
556 *key++ = ' ';
557 }
558}
559
560void libwebsockets_00_spam(char *key, int count, int seed)
561{
562 char *p;
563
564 key++;
565 while (count--) {
Andy Green6ee372f2012-04-09 15:09:01 +0800566
Andy Greeneeaacb32011-03-01 20:44:24 +0000567 if (*key && (seed & 1))
568 key++;
569 seed >>= 1;
570
571 p = key + strlen(key);
572 while (p >= key) {
573 p[1] = p[0];
574 p--;
575 }
576 *key++ = 0x21 + ((seed & 0xffff) % 15);
577 /* 4 would use it up too fast.. not like it matters */
578 seed >>= 1;
579 }
580}
581
Andy Green95a7b5d2011-03-06 10:29:39 +0000582int lws_send_pipe_choked(struct libwebsocket *wsi)
583{
584 struct pollfd fds;
585
586 fds.fd = wsi->sock;
587 fds.events = POLLOUT;
588 fds.revents = 0;
589
590 if (poll(&fds, 1, 0) != 1)
591 return 1;
592
593 if ((fds.revents & POLLOUT) == 0)
594 return 1;
595
596 /* okay to send another packet without blocking */
597
598 return 0;
599}
600
Andy Greena41314f2011-05-23 10:00:03 +0100601int
Andy Green3b84c002011-03-06 13:14:42 +0000602lws_handle_POLLOUT_event(struct libwebsocket_context *context,
603 struct libwebsocket *wsi, struct pollfd *pollfd)
604{
605 struct lws_tokens eff_buf;
606 int n;
607 int ret;
608 int m;
Andy Greena41314f2011-05-23 10:00:03 +0100609 int handled = 0;
Andy Green3b84c002011-03-06 13:14:42 +0000610
Andy Greena41314f2011-05-23 10:00:03 +0100611 for (n = 0; n < wsi->count_active_extensions; n++) {
612 if (!wsi->active_extensions[n]->callback)
613 continue;
614
615 m = wsi->active_extensions[n]->callback(context,
616 wsi->active_extensions[n], wsi,
617 LWS_EXT_CALLBACK_IS_WRITEABLE,
618 wsi->active_extensions_user[n], NULL, 0);
619 if (m > handled)
620 handled = m;
621 }
622
623 if (handled == 1)
624 goto notify_action;
625
626 if (!wsi->extension_data_pending || handled == 2)
Andy Green3b84c002011-03-06 13:14:42 +0000627 goto user_service;
628
629 /*
630 * check in on the active extensions, see if they
631 * had pending stuff to spill... they need to get the
632 * first look-in otherwise sequence will be disordered
633 *
634 * NULL, zero-length eff_buf means just spill pending
635 */
636
637 ret = 1;
638 while (ret == 1) {
639
640 /* default to nobody has more to spill */
641
642 ret = 0;
643 eff_buf.token = NULL;
644 eff_buf.token_len = 0;
645
646 /* give every extension a chance to spill */
647
648 for (n = 0; n < wsi->count_active_extensions; n++) {
649 m = wsi->active_extensions[n]->callback(
Andy Green46c2ea02011-03-22 09:04:01 +0000650 wsi->protocol->owning_server,
651 wsi->active_extensions[n], wsi,
Andy Green3b84c002011-03-06 13:14:42 +0000652 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
653 wsi->active_extensions_user[n], &eff_buf, 0);
654 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +0800655 lwsl_err("ext reports fatal error\n");
Andy Green3b84c002011-03-06 13:14:42 +0000656 return -1;
657 }
658 if (m)
659 /*
660 * at least one extension told us he has more
661 * to spill, so we will go around again after
662 */
663 ret = 1;
664 }
665
666 /* assuming they gave us something to send, send it */
667
668 if (eff_buf.token_len) {
669 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
670 eff_buf.token_len))
671 return -1;
672 } else
673 continue;
674
675 /* no extension has more to spill */
676
677 if (!ret)
678 continue;
679
680 /*
681 * There's more to spill from an extension, but we just sent
682 * something... did that leave the pipe choked?
683 */
684
685 if (!lws_send_pipe_choked(wsi))
686 /* no we could add more */
687 continue;
688
Andy Green43db0452013-01-10 19:50:35 +0800689 lwsl_info("choked in POLLOUT service\n");
Andy Green3b84c002011-03-06 13:14:42 +0000690
691 /*
692 * Yes, he's choked. Leave the POLLOUT masked on so we will
693 * come back here when he is unchoked. Don't call the user
694 * callback to enforce ordering of spilling, he'll get called
695 * when we come back here and there's nothing more to spill.
696 */
697
698 return 0;
699 }
700
701 wsi->extension_data_pending = 0;
702
703user_service:
704 /* one shot */
705
Andy Greena41314f2011-05-23 10:00:03 +0100706 if (pollfd) {
707 pollfd->events &= ~POLLOUT;
Andy Green3b84c002011-03-06 13:14:42 +0000708
Andy Greena41314f2011-05-23 10:00:03 +0100709 /* external POLL support via protocol 0 */
710 context->protocols[0].callback(context, wsi,
711 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
712 (void *)(long)wsi->sock, NULL, POLLOUT);
713 }
714
715notify_action:
Andy Green3b84c002011-03-06 13:14:42 +0000716
Andy Green9e4c2b62011-03-07 20:47:39 +0000717 if (wsi->mode == LWS_CONNMODE_WS_CLIENT)
718 n = LWS_CALLBACK_CLIENT_WRITEABLE;
719 else
720 n = LWS_CALLBACK_SERVER_WRITEABLE;
721
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800722 wsi->protocol->callback(context, wsi, (enum libwebsocket_callback_reasons) n, wsi->user_space, NULL, 0);
Andy Green3b84c002011-03-06 13:14:42 +0000723
724 return 0;
725}
726
727
728
Andy Greena41314f2011-05-23 10:00:03 +0100729void
730libwebsocket_service_timeout_check(struct libwebsocket_context *context,
731 struct libwebsocket *wsi, unsigned int sec)
732{
733 int n;
734
735 /*
736 * if extensions want in on it (eg, we are a mux parent)
737 * give them a chance to service child timeouts
738 */
739
740 for (n = 0; n < wsi->count_active_extensions; n++)
741 wsi->active_extensions[n]->callback(
742 context, wsi->active_extensions[n],
743 wsi, LWS_EXT_CALLBACK_1HZ,
744 wsi->active_extensions_user[n], NULL, sec);
745
746 if (!wsi->pending_timeout)
747 return;
Andy Green6ee372f2012-04-09 15:09:01 +0800748
Andy Greena41314f2011-05-23 10:00:03 +0100749 /*
750 * if we went beyond the allowed time, kill the
751 * connection
752 */
753
754 if (sec > wsi->pending_timeout_limit) {
Andy Green43db0452013-01-10 19:50:35 +0800755 lwsl_info("TIMEDOUT WAITING\n");
Andy Greena41314f2011-05-23 10:00:03 +0100756 libwebsocket_close_and_free_session(context,
757 wsi, LWS_CLOSE_STATUS_NOSTATUS);
758 }
759}
760
761struct libwebsocket *
762libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
763{
764 struct libwebsocket *new_wsi;
765 int n;
766
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800767 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Greena41314f2011-05-23 10:00:03 +0100768 if (new_wsi == NULL) {
Andy Green43db0452013-01-10 19:50:35 +0800769 lwsl_err("Out of memory for new connection\n");
Andy Greena41314f2011-05-23 10:00:03 +0100770 return NULL;
771 }
772
Andy Green6ee372f2012-04-09 15:09:01 +0800773 memset(new_wsi, 0, sizeof(struct libwebsocket));
Andy Greena41314f2011-05-23 10:00:03 +0100774 new_wsi->count_active_extensions = 0;
775 new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
776
777 /* intialize the instance struct */
778
779 new_wsi->state = WSI_STATE_HTTP;
780 new_wsi->name_buffer_pos = 0;
781 new_wsi->mode = LWS_CONNMODE_WS_SERVING;
782
783 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
784 new_wsi->utf8_token[n].token = NULL;
785 new_wsi->utf8_token[n].token_len = 0;
786 }
787
788 /*
789 * these can only be set once the protocol is known
790 * we set an unestablished connection's protocol pointer
791 * to the start of the supported list, so it can look
792 * for matching ones during the handshake
793 */
794 new_wsi->protocol = context->protocols;
795 new_wsi->user_space = NULL;
796
797 /*
798 * Default protocol is 76 / 00
799 * After 76, there's a header specified to inform which
800 * draft the client wants, when that's seen we modify
801 * the individual connection's spec revision accordingly
802 */
803 new_wsi->ietf_spec_revision = 0;
804
805 return new_wsi;
806}
807
808char *
809libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
810 struct libwebsocket *wsi, char *pkt)
811{
812 char hash[20];
813 char *p = pkt;
814 int n;
815 struct libwebsocket_extension *ext;
Andy Green09226502011-05-28 10:19:19 +0100816 struct libwebsocket_extension *ext1;
Andy Greena41314f2011-05-23 10:00:03 +0100817 int ext_count = 0;
Andy Green6ee372f2012-04-09 15:09:01 +0800818 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
819 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena41314f2011-05-23 10:00:03 +0100820 static const char magic_websocket_guid[] =
821 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
822
823 /*
824 * create the random key
825 */
826
827 n = libwebsockets_get_random(context, hash, 16);
828 if (n != 16) {
Andy Green43db0452013-01-10 19:50:35 +0800829 lwsl_err("Unable to read from random dev %s\n",
Andy Greena41314f2011-05-23 10:00:03 +0100830 SYSTEM_RANDOM_FILEPATH);
831 free(wsi->c_path);
832 free(wsi->c_host);
833 if (wsi->c_origin)
834 free(wsi->c_origin);
835 if (wsi->c_protocol)
836 free(wsi->c_protocol);
837 libwebsocket_close_and_free_session(context, wsi,
838 LWS_CLOSE_STATUS_NOSTATUS);
839 return NULL;
840 }
841
842 lws_b64_encode_string(hash, 16, wsi->key_b64,
843 sizeof wsi->key_b64);
844
845 /*
846 * 00 example client handshake
847 *
848 * GET /socket.io/websocket HTTP/1.1
849 * Upgrade: WebSocket
850 * Connection: Upgrade
851 * Host: 127.0.0.1:9999
852 * Origin: http://127.0.0.1
853 * Sec-WebSocket-Key1: 1 0 2#0W 9 89 7 92 ^
854 * Sec-WebSocket-Key2: 7 7Y 4328 B2v[8(z1
855 * Cookie: socketio=websocket
856 *
857 * (Á®Ä0¶†≥
858 *
859 * 04 example client handshake
860 *
861 * GET /chat HTTP/1.1
862 * Host: server.example.com
863 * Upgrade: websocket
864 * Connection: Upgrade
865 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
866 * Sec-WebSocket-Origin: http://example.com
867 * Sec-WebSocket-Protocol: chat, superchat
868 * Sec-WebSocket-Version: 4
869 */
870
871 p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a", wsi->c_path);
872
David Galeano4fbc40c2013-01-10 10:26:05 +0800873 p += sprintf(p, "Pragma: no-cache\x0d\x0a"
874 "Cache-Control: no-cache\x0d\x0a");
875
Andy Greena41314f2011-05-23 10:00:03 +0100876 if (wsi->ietf_spec_revision == 0) {
877 unsigned char spaces_1, spaces_2;
878 unsigned int max_1, max_2;
879 unsigned int num_1, num_2;
880 unsigned long product_1, product_2;
881 char key_1[40];
882 char key_2[40];
883 unsigned int seed;
884 unsigned int count;
885 char challenge[16];
886
Andy Green6ee372f2012-04-09 15:09:01 +0800887 libwebsockets_get_random(context, &spaces_1, sizeof(char));
888 libwebsockets_get_random(context, &spaces_2, sizeof(char));
Andy Greena41314f2011-05-23 10:00:03 +0100889
890 spaces_1 = (spaces_1 % 12) + 1;
891 spaces_2 = (spaces_2 % 12) + 1;
892
893 max_1 = 4294967295 / spaces_1;
894 max_2 = 4294967295 / spaces_2;
895
896 libwebsockets_get_random(context, &num_1, sizeof(int));
897 libwebsockets_get_random(context, &num_2, sizeof(int));
898
899 num_1 = (num_1 % max_1);
900 num_2 = (num_2 % max_2);
901
902 challenge[0] = num_1 >> 24;
903 challenge[1] = num_1 >> 16;
904 challenge[2] = num_1 >> 8;
905 challenge[3] = num_1;
906 challenge[4] = num_2 >> 24;
907 challenge[5] = num_2 >> 16;
908 challenge[6] = num_2 >> 8;
909 challenge[7] = num_2;
910
911 product_1 = num_1 * spaces_1;
912 product_2 = num_2 * spaces_2;
913
914 sprintf(key_1, "%lu", product_1);
915 sprintf(key_2, "%lu", product_2);
916
917 libwebsockets_get_random(context, &seed, sizeof(int));
918 libwebsockets_get_random(context, &count, sizeof(int));
919
920 libwebsockets_00_spam(key_1, (count % 12) + 1, seed);
921
922 libwebsockets_get_random(context, &seed, sizeof(int));
923 libwebsockets_get_random(context, &count, sizeof(int));
924
925 libwebsockets_00_spam(key_2, (count % 12) + 1, seed);
926
927 libwebsockets_get_random(context, &seed, sizeof(int));
928
929 libwebsockets_00_spaceout(key_1, spaces_1, seed);
930 libwebsockets_00_spaceout(key_2, spaces_2, seed >> 16);
931
932 p += sprintf(p, "Upgrade: WebSocket\x0d\x0a"
933 "Connection: Upgrade\x0d\x0aHost: %s\x0d\x0a",
934 wsi->c_host);
935 if (wsi->c_origin)
Andy Green6ee372f2012-04-09 15:09:01 +0800936 p += sprintf(p, "Origin: %s\x0d\x0a", wsi->c_origin);
Andy Greena41314f2011-05-23 10:00:03 +0100937
938 if (wsi->c_protocol)
939 p += sprintf(p, "Sec-WebSocket-Protocol: %s"
940 "\x0d\x0a", wsi->c_protocol);
941
Andy Green6ee372f2012-04-09 15:09:01 +0800942 p += sprintf(p, "Sec-WebSocket-Key1: %s\x0d\x0a", key_1);
943 p += sprintf(p, "Sec-WebSocket-Key2: %s\x0d\x0a", key_2);
Andy Greena41314f2011-05-23 10:00:03 +0100944
945 /* give userland a chance to append, eg, cookies */
946
947 context->protocols[0].callback(context, wsi,
948 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
949 NULL, &p, (pkt + sizeof(pkt)) - p - 12);
950
951 p += sprintf(p, "\x0d\x0a");
952
953 if (libwebsockets_get_random(context, p, 8) != 8)
954 return NULL;
955 memcpy(&challenge[8], p, 8);
956 p += 8;
957
958 /* precompute what we want to see from the server */
959
960 MD5((unsigned char *)challenge, 16,
961 (unsigned char *)wsi->initial_handshake_hash_base64);
962
963 goto issue_hdr;
964 }
965
966 p += sprintf(p, "Host: %s\x0d\x0a", wsi->c_host);
David Galeano4fbc40c2013-01-10 10:26:05 +0800967 p += sprintf(p, "Upgrade: websocket\x0d\x0a"
968 "Connection: Upgrade\x0d\x0a"
969 "Sec-WebSocket-Key: ");
Andy Greena41314f2011-05-23 10:00:03 +0100970 strcpy(p, wsi->key_b64);
971 p += strlen(wsi->key_b64);
972 p += sprintf(p, "\x0d\x0a");
David Galeanoaa0bc862013-01-09 15:31:46 +0800973 if (wsi->c_origin) {
974 if (wsi->ietf_spec_revision == 13) {
975 p += sprintf(p, "Origin: %s\x0d\x0a",
976 wsi->c_origin);
977 }
978 else {
David Galeanocb193682013-01-09 15:29:00 +0800979 p += sprintf(p, "Sec-WebSocket-Origin: %s\x0d\x0a",
Andy Greena41314f2011-05-23 10:00:03 +0100980 wsi->c_origin);
David Galeanoaa0bc862013-01-09 15:31:46 +0800981 }
982 }
Andy Greena41314f2011-05-23 10:00:03 +0100983 if (wsi->c_protocol)
984 p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
985 wsi->c_protocol);
986
987 /* tell the server what extensions we could support */
988
989 p += sprintf(p, "Sec-WebSocket-Extensions: ");
990
Andy Green6ee372f2012-04-09 15:09:01 +0800991 ext = context->extensions;
Andy Greena41314f2011-05-23 10:00:03 +0100992 while (ext && ext->callback) {
993
994 n = 0;
Andy Green09226502011-05-28 10:19:19 +0100995 ext1 = context->extensions;
Andy Green09226502011-05-28 10:19:19 +0100996
Andy Green6ee372f2012-04-09 15:09:01 +0800997 while (ext1 && ext1->callback) {
Andy Green09226502011-05-28 10:19:19 +0100998 n |= ext1->callback(context, ext1, wsi,
999 LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
1000 NULL, (char *)ext->name, 0);
1001
1002 ext1++;
1003 }
1004
Andy Green6ee372f2012-04-09 15:09:01 +08001005 if (n) { /* an extension vetos us */
Andy Green43db0452013-01-10 19:50:35 +08001006 lwsl_ext("ext %s vetoed\n", (char *)ext->name);
Andy Green09226502011-05-28 10:19:19 +01001007 ext++;
1008 continue;
1009 }
1010
Andy Greena41314f2011-05-23 10:00:03 +01001011 n = context->protocols[0].callback(context, wsi,
1012 LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
1013 wsi->user_space, (char *)ext->name, 0);
1014
1015 /*
1016 * zero return from callback means
1017 * go ahead and allow the extension,
1018 * it's what we get if the callback is
1019 * unhandled
1020 */
1021
1022 if (n) {
1023 ext++;
1024 continue;
1025 }
1026
1027 /* apply it */
1028
1029 if (ext_count)
1030 *p++ = ',';
1031 p += sprintf(p, "%s", ext->name);
1032 ext_count++;
1033
1034 ext++;
1035 }
1036
1037 p += sprintf(p, "\x0d\x0a");
1038
1039 if (wsi->ietf_spec_revision)
1040 p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
1041 wsi->ietf_spec_revision);
1042
1043 /* give userland a chance to append, eg, cookies */
1044
1045 context->protocols[0].callback(context, wsi,
1046 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
1047 NULL, &p, (pkt + sizeof(pkt)) - p - 12);
1048
1049 p += sprintf(p, "\x0d\x0a");
1050
1051 /* prepare the expected server accept response */
1052
1053 strcpy((char *)buf, wsi->key_b64);
1054 strcpy((char *)&buf[strlen((char *)buf)], magic_websocket_guid);
1055
1056 SHA1(buf, strlen((char *)buf), (unsigned char *)hash);
1057
1058 lws_b64_encode_string(hash, 20,
1059 wsi->initial_handshake_hash_base64,
1060 sizeof wsi->initial_handshake_hash_base64);
1061
1062issue_hdr:
1063
Andy Green6ee372f2012-04-09 15:09:01 +08001064#if 0
1065 puts(pkt);
1066#endif
Andy Green09226502011-05-28 10:19:19 +01001067
Andy Greena41314f2011-05-23 10:00:03 +01001068 /* done with these now */
1069
1070 free(wsi->c_path);
1071 free(wsi->c_host);
1072 if (wsi->c_origin)
1073 free(wsi->c_origin);
1074
1075 return p;
1076}
1077
1078int
1079lws_client_interpret_server_handshake(struct libwebsocket_context *context,
1080 struct libwebsocket *wsi)
1081{
Andy Green6ee372f2012-04-09 15:09:01 +08001082 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
1083 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena41314f2011-05-23 10:00:03 +01001084 char pkt[1024];
1085 char *p = &pkt[0];
1086 const char *pc;
1087 const char *c;
1088 int more = 1;
1089 int okay = 0;
1090 char ext_name[128];
1091 struct libwebsocket_extension *ext;
1092 void *v;
Andy Greenc15cb382011-06-26 10:27:28 +01001093 int len = 0;
Andy Greena41314f2011-05-23 10:00:03 +01001094 int n;
1095 static const char magic_websocket_04_masking_guid[] =
1096 "61AC5F19-FBBA-4540-B96F-6561F1AB40A8";
1097
1098 /*
1099 * 00 / 76 -->
1100 *
1101 * HTTP/1.1 101 WebSocket Protocol Handshake
1102 * Upgrade: WebSocket
1103 * Connection: Upgrade
1104 * Sec-WebSocket-Origin: http://127.0.0.1
1105 * Sec-WebSocket-Location: ws://127.0.0.1:9999/socket.io/websocket
1106 *
1107 * xxxxxxxxxxxxxxxx
1108 */
1109
1110 if (wsi->ietf_spec_revision == 0) {
1111 if (!wsi->utf8_token[WSI_TOKEN_HTTP].token_len ||
1112 !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
1113 !wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len ||
1114 !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len ||
1115 (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len &&
1116 wsi->c_protocol != NULL)) {
Andy Green43db0452013-01-10 19:50:35 +08001117 lwsl_parser("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001118 "missing required header(s)\n");
1119 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001120 lwsl_parser("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001121 goto bail3;
1122 }
1123
1124 strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token);
Andy Green6ee372f2012-04-09 15:09:01 +08001125 if (strncmp(wsi->utf8_token[WSI_TOKEN_HTTP].token, "101", 3)) {
Andy Green43db0452013-01-10 19:50:35 +08001126 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001127 "server sent bad HTTP response '%s'\n",
1128 wsi->utf8_token[WSI_TOKEN_HTTP].token);
1129 goto bail3;
1130 }
1131
Andy Green6ee372f2012-04-09 15:09:01 +08001132 if (wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len < 16) {
Andy Green43db0452013-01-10 19:50:35 +08001133 lwsl_parser("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001134 "challenge reply too short %d\n",
1135 wsi->utf8_token[
1136 WSI_TOKEN_CHALLENGE].token_len);
1137 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001138 lwsl_parser("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001139 goto bail3;
1140
1141 }
1142
1143 goto select_protocol;
1144 }
1145
1146 /*
1147 * well, what the server sent looked reasonable for syntax.
1148 * Now let's confirm it sent all the necessary headers
1149 */
1150#if 0
Andy Green43db0452013-01-10 19:50:35 +08001151 lwsl_parser("WSI_TOKEN_HTTP: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001152 wsi->utf8_token[WSI_TOKEN_HTTP].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001153 lwsl_parser("WSI_TOKEN_UPGRADE: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001154 wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001155 lwsl_parser("WSI_TOKEN_CONNECTION: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001156 wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001157 lwsl_parser("WSI_TOKEN_ACCEPT: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001158 wsi->utf8_token[WSI_TOKEN_ACCEPT].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001159 lwsl_parser("WSI_TOKEN_NONCE: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001160 wsi->utf8_token[WSI_TOKEN_NONCE].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001161 lwsl_parser("WSI_TOKEN_PROTOCOL: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001162 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len);
Andy Greena41314f2011-05-23 10:00:03 +01001163#endif
Andy Green6ee372f2012-04-09 15:09:01 +08001164 if (!wsi->utf8_token[WSI_TOKEN_HTTP].token_len ||
1165 !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
1166 !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len ||
1167 !wsi->utf8_token[WSI_TOKEN_ACCEPT].token_len ||
1168 (!wsi->utf8_token[WSI_TOKEN_NONCE].token_len &&
Andy Greena41314f2011-05-23 10:00:03 +01001169 wsi->ietf_spec_revision == 4) ||
Andy Green6ee372f2012-04-09 15:09:01 +08001170 (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len &&
1171 wsi->c_protocol != NULL)) {
Andy Green43db0452013-01-10 19:50:35 +08001172 lwsl_parser("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001173 "missing required header(s)\n");
1174 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001175 lwsl_parser("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001176 goto bail3;
1177 }
1178
1179 /*
1180 * Everything seems to be there, now take a closer look at what
1181 * is in each header
1182 */
1183
1184 strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token);
Artem Egorkined515ddd2011-11-23 10:46:24 +02001185 if (strncmp(wsi->utf8_token[WSI_TOKEN_HTTP].token, "101", 3)) {
Andy Green43db0452013-01-10 19:50:35 +08001186 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001187 "server sent bad HTTP response '%s'\n",
1188 wsi->utf8_token[WSI_TOKEN_HTTP].token);
1189 goto bail3;
1190 }
1191
1192 strtolower(wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
1193 if (strcmp(wsi->utf8_token[WSI_TOKEN_UPGRADE].token,
1194 "websocket")) {
Andy Green43db0452013-01-10 19:50:35 +08001195 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001196 "sent bad Upgrade header '%s'\n",
1197 wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
1198 goto bail3;
1199 }
1200
1201 strtolower(wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
1202 if (strcmp(wsi->utf8_token[WSI_TOKEN_CONNECTION].token,
1203 "upgrade")) {
Andy Green43db0452013-01-10 19:50:35 +08001204 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001205 "sent bad Connection hdr '%s'\n",
1206 wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
1207 goto bail3;
1208 }
1209
1210select_protocol:
1211 pc = wsi->c_protocol;
1212 if (pc == NULL)
Andy Green43db0452013-01-10 19:50:35 +08001213 lwsl_parser("lws_client_interpret_server_handshake: "
Andy Green6ee372f2012-04-09 15:09:01 +08001214 "NULL c_protocol\n");
Andy Greena41314f2011-05-23 10:00:03 +01001215 else
Andy Green43db0452013-01-10 19:50:35 +08001216 lwsl_parser("lws_client_interpret_server_handshake: "
Andy Green6ee372f2012-04-09 15:09:01 +08001217 "cPprotocol='%s'\n", pc);
Andy Greena41314f2011-05-23 10:00:03 +01001218
1219 /*
1220 * confirm the protocol the server wants to talk was in the list
1221 * of protocols we offered
1222 */
1223
1224 if (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len) {
1225
Andy Green43db0452013-01-10 19:50:35 +08001226 lwsl_warn("lws_client_interpret_server_handshake "
Andy Green6ee372f2012-04-09 15:09:01 +08001227 "WSI_TOKEN_PROTOCOL is null\n");
Andy Greena41314f2011-05-23 10:00:03 +01001228 /*
1229 * no protocol name to work from,
1230 * default to first protocol
1231 */
1232 wsi->protocol = &context->protocols[0];
David Brooks2c60d952012-04-20 12:19:01 +08001233 wsi->c_callback = wsi->protocol->callback;
Andy Greena41314f2011-05-23 10:00:03 +01001234 free(wsi->c_protocol);
1235
David Galeano4c38f142013-01-09 19:49:50 +08001236 goto check_extensions;
Andy Greena41314f2011-05-23 10:00:03 +01001237 }
1238
1239 while (*pc && !okay) {
Andy Green6ee372f2012-04-09 15:09:01 +08001240 if ((!strncmp(pc, wsi->utf8_token[WSI_TOKEN_PROTOCOL].token,
1241 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len)) &&
1242 (pc[wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len] == ',' ||
1243 pc[wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len] == '\0')) {
Andy Greena41314f2011-05-23 10:00:03 +01001244 okay = 1;
1245 continue;
1246 }
1247 while (*pc && *pc != ',')
1248 pc++;
1249 while (*pc && *pc != ' ')
1250 pc++;
1251 }
1252
1253 /* done with him now */
1254
1255 if (wsi->c_protocol)
1256 free(wsi->c_protocol);
1257
Andy Greena41314f2011-05-23 10:00:03 +01001258 if (!okay) {
Andy Green43db0452013-01-10 19:50:35 +08001259 lwsl_err("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001260 "sent bad protocol '%s'\n",
1261 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
1262 goto bail2;
1263 }
1264
1265 /*
1266 * identify the selected protocol struct and set it
1267 */
1268 n = 0;
1269 wsi->protocol = NULL;
David Brooks2c60d952012-04-20 12:19:01 +08001270 while (context->protocols[n].callback && !wsi->protocol) { /* Stop after finding first one?? */
Andy Greena41314f2011-05-23 10:00:03 +01001271 if (strcmp(wsi->utf8_token[WSI_TOKEN_PROTOCOL].token,
David Brooks2c60d952012-04-20 12:19:01 +08001272 context->protocols[n].name) == 0) {
Andy Greena41314f2011-05-23 10:00:03 +01001273 wsi->protocol = &context->protocols[n];
David Brooks2c60d952012-04-20 12:19:01 +08001274 wsi->c_callback = wsi->protocol->callback;
1275 }
Andy Greena41314f2011-05-23 10:00:03 +01001276 n++;
1277 }
1278
1279 if (wsi->protocol == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08001280 lwsl_err("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001281 "requested protocol '%s', which we "
1282 "said we supported but we don't!\n",
1283 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
1284 goto bail2;
1285 }
1286
1287
David Galeano4c38f142013-01-09 19:49:50 +08001288check_extensions:
1289
Andy Greena41314f2011-05-23 10:00:03 +01001290 /* instantiate the accepted extensions */
1291
1292 if (!wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token_len) {
Andy Green43db0452013-01-10 19:50:35 +08001293 lwsl_ext("no client extenstions allowed by server\n");
Andy Greena41314f2011-05-23 10:00:03 +01001294 goto check_accept;
1295 }
1296
1297 /*
1298 * break down the list of server accepted extensions
1299 * and go through matching them or identifying bogons
1300 */
1301
1302 c = wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token;
1303 n = 0;
1304 while (more) {
1305
1306 if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
1307 ext_name[n] = *c++;
1308 if (n < sizeof(ext_name) - 1)
1309 n++;
1310 continue;
1311 }
1312 ext_name[n] = '\0';
1313 if (!*c)
1314 more = 0;
1315 else {
1316 c++;
1317 if (!n)
1318 continue;
1319 }
1320
1321 /* check we actually support it */
1322
Andy Green43db0452013-01-10 19:50:35 +08001323 lwsl_ext("checking client ext %s\n", ext_name);
Andy Greena41314f2011-05-23 10:00:03 +01001324
1325 n = 0;
1326 ext = wsi->protocol->owning_server->extensions;
1327 while (ext && ext->callback) {
1328
1329 if (strcmp(ext_name, ext->name)) {
1330 ext++;
1331 continue;
1332 }
1333
1334 n = 1;
1335
Andy Green43db0452013-01-10 19:50:35 +08001336 lwsl_ext("instantiating client ext %s\n", ext_name);
Andy Greena41314f2011-05-23 10:00:03 +01001337
1338 /* instantiate the extension on this conn */
1339
1340 wsi->active_extensions_user[
1341 wsi->count_active_extensions] =
1342 malloc(ext->per_session_data_size);
Andy Green41c58032013-01-12 13:21:08 +08001343 if (wsi->active_extensions_user[
1344 wsi->count_active_extensions] == NULL) {
1345 lwsl_err("Out of mem\n");
1346 goto bail2;
1347 }
Andy Greenf6652412011-05-25 20:46:18 +01001348 memset(wsi->active_extensions_user[
1349 wsi->count_active_extensions], 0,
1350 ext->per_session_data_size);
Andy Greena41314f2011-05-23 10:00:03 +01001351 wsi->active_extensions[
1352 wsi->count_active_extensions] = ext;
1353
1354 /* allow him to construct his context */
1355
1356 ext->callback(wsi->protocol->owning_server,
1357 ext, wsi,
1358 LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
1359 wsi->active_extensions_user[
1360 wsi->count_active_extensions],
1361 NULL, 0);
1362
1363 wsi->count_active_extensions++;
1364
1365 ext++;
1366 }
1367
1368 if (n == 0) {
Andy Green43db0452013-01-10 19:50:35 +08001369 lwsl_warn("Server said we should use"
Andy Greena41314f2011-05-23 10:00:03 +01001370 "an unknown extension '%s'!\n", ext_name);
1371 goto bail2;
1372 }
1373
1374 n = 0;
1375 }
1376
1377
1378check_accept:
1379
1380 if (wsi->ietf_spec_revision == 0) {
1381
1382 if (memcmp(wsi->initial_handshake_hash_base64,
1383 wsi->utf8_token[WSI_TOKEN_CHALLENGE].token, 16)) {
Andy Green43db0452013-01-10 19:50:35 +08001384 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001385 "failed 00 challenge compare\n");
1386 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001387 lwsl_warn("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001388 goto bail2;
1389 }
1390
1391 goto accept_ok;
1392 }
1393
1394 /*
1395 * Confirm his accept token is the one we precomputed
1396 */
1397
1398 if (strcmp(wsi->utf8_token[WSI_TOKEN_ACCEPT].token,
1399 wsi->initial_handshake_hash_base64)) {
Andy Green43db0452013-01-10 19:50:35 +08001400 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001401 "sent bad ACCEPT '%s' vs computed '%s'\n",
1402 wsi->utf8_token[WSI_TOKEN_ACCEPT].token,
1403 wsi->initial_handshake_hash_base64);
1404 goto bail2;
1405 }
1406
1407 if (wsi->ietf_spec_revision == 4) {
1408 /*
1409 * Calculate the 04 masking key to use when
1410 * sending data to server
1411 */
1412
1413 strcpy((char *)buf, wsi->key_b64);
1414 p = (char *)buf + strlen(wsi->key_b64);
1415 strcpy(p, wsi->utf8_token[WSI_TOKEN_NONCE].token);
1416 p += wsi->utf8_token[WSI_TOKEN_NONCE].token_len;
1417 strcpy(p, magic_websocket_04_masking_guid);
1418 SHA1(buf, strlen((char *)buf), wsi->masking_key_04);
1419 }
Andy Green6ee372f2012-04-09 15:09:01 +08001420accept_ok:
Andy Greena41314f2011-05-23 10:00:03 +01001421
1422 /* allocate the per-connection user memory (if any) */
Andy Green6ee372f2012-04-09 15:09:01 +08001423 if (wsi->protocol->per_session_data_size &&
1424 !libwebsocket_ensure_user_space(wsi))
1425 goto bail2;
Andy Greena41314f2011-05-23 10:00:03 +01001426
1427 /* clear his proxy connection timeout */
1428
1429 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1430
1431 /* mark him as being alive */
1432
1433 wsi->state = WSI_STATE_ESTABLISHED;
1434 wsi->mode = LWS_CONNMODE_WS_CLIENT;
1435
Andy Green43db0452013-01-10 19:50:35 +08001436 lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
Andy Greena41314f2011-05-23 10:00:03 +01001437
1438 /* call him back to inform him he is up */
1439
1440 wsi->protocol->callback(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08001441 LWS_CALLBACK_CLIENT_ESTABLISHED,
1442 wsi->user_space, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01001443
1444 /*
1445 * inform all extensions, not just active ones since they
1446 * already know
1447 */
1448
1449 ext = context->extensions;
1450
1451 while (ext && ext->callback) {
1452 v = NULL;
1453 for (n = 0; n < wsi->count_active_extensions; n++)
1454 if (wsi->active_extensions[n] == ext)
1455 v = wsi->active_extensions_user[n];
1456
1457 ext->callback(context, ext, wsi,
1458 LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED, v, NULL, 0);
1459 ext++;
1460 }
1461
1462 return 0;
1463
1464bail3:
1465 if (wsi->c_protocol)
1466 free(wsi->c_protocol);
1467
1468bail2:
David Brooks80a44972012-04-20 12:18:47 +08001469 if (wsi->c_callback) wsi->c_callback(context, wsi,
1470 LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
1471 wsi->user_space,
1472 NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01001473 libwebsocket_close_and_free_session(context, wsi,
David Brooks80a44972012-04-20 12:18:47 +08001474 LWS_CLOSE_STATUS_NOSTATUS); // But this should be LWS_CLOSE_STATUS_PROTOCOL_ERR
1475
Andy Greena41314f2011-05-23 10:00:03 +01001476 return 1;
1477}
1478
1479
1480
Andy Green9f990342011-02-12 11:57:45 +00001481/**
1482 * libwebsocket_service_fd() - Service polled socket with something waiting
Peter Hinz56885f32011-03-02 22:03:47 +00001483 * @context: Websocket context
Andy Green9f990342011-02-12 11:57:45 +00001484 * @pollfd: The pollfd entry describing the socket fd and which events
Andy Green6ee372f2012-04-09 15:09:01 +08001485 * happened.
Andy Green9f990342011-02-12 11:57:45 +00001486 *
1487 * This function closes any active connections and then frees the
1488 * context. After calling this, any further use of the context is
1489 * undefined.
1490 */
1491
1492int
Peter Hinz56885f32011-03-02 22:03:47 +00001493libwebsocket_service_fd(struct libwebsocket_context *context,
Andy Green0d338332011-02-12 11:57:43 +00001494 struct pollfd *pollfd)
Andy Greenb45993c2010-12-18 15:13:50 +00001495{
Andy Green6ee372f2012-04-09 15:09:01 +08001496 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
1497 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena71eafc2011-02-14 17:59:43 +00001498 struct libwebsocket *wsi;
Andy Green0d338332011-02-12 11:57:43 +00001499 struct libwebsocket *new_wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00001500 int n;
Andy Green0d338332011-02-12 11:57:43 +00001501 int m;
Tobias Maiere8c9b562012-04-05 11:57:12 +02001502 ssize_t len;
Andy Green0d338332011-02-12 11:57:43 +00001503 int accept_fd;
1504 unsigned int clilen;
1505 struct sockaddr_in cli_addr;
Andy Greena71eafc2011-02-14 17:59:43 +00001506 struct timeval tv;
Andy Greenbe93fef2011-02-14 20:25:43 +00001507 char pkt[1024];
1508 char *p = &pkt[0];
Andy Green2366b1c2011-03-06 13:15:31 +00001509 int more = 1;
Andy Green98a717c2011-03-06 13:14:15 +00001510 struct lws_tokens eff_buf;
Andy Green6c939552011-03-08 08:56:57 +00001511 int opt = 1;
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001512 char c;
Andy Greenc6517fa2011-03-06 13:15:29 +00001513
Andy Greenbe93fef2011-02-14 20:25:43 +00001514#ifdef LWS_OPENSSL_SUPPORT
1515 char ssl_err_buf[512];
1516#endif
Andy Greena71eafc2011-02-14 17:59:43 +00001517 /*
1518 * you can call us with pollfd = NULL to just allow the once-per-second
1519 * global timeout checks; if less than a second since the last check
1520 * it returns immediately then.
1521 */
1522
1523 gettimeofday(&tv, NULL);
1524
Peter Hinz56885f32011-03-02 22:03:47 +00001525 if (context->last_timeout_check_s != tv.tv_sec) {
1526 context->last_timeout_check_s = tv.tv_sec;
Andy Greena71eafc2011-02-14 17:59:43 +00001527
1528 /* global timeout check once per second */
1529
Peter Hinz56885f32011-03-02 22:03:47 +00001530 for (n = 0; n < context->fds_count; n++) {
1531 wsi = wsi_from_fd(context, context->fds[n].fd);
Andy Greena71eafc2011-02-14 17:59:43 +00001532
Andy Greena41314f2011-05-23 10:00:03 +01001533 libwebsocket_service_timeout_check(context, wsi,
1534 tv.tv_sec);
Andy Greena71eafc2011-02-14 17:59:43 +00001535 }
1536 }
1537
1538 /* just here for timeout management? */
1539
1540 if (pollfd == NULL)
1541 return 0;
1542
1543 /* no, here to service a socket descriptor */
1544
Peter Hinz56885f32011-03-02 22:03:47 +00001545 wsi = wsi_from_fd(context, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001546
Andy Green0d338332011-02-12 11:57:43 +00001547 if (wsi == NULL)
Andy Greenfa3f4052012-10-07 20:40:35 +08001548 return 0;
Andy Green8f037e42010-12-19 22:13:26 +00001549
Andy Green0d338332011-02-12 11:57:43 +00001550 switch (wsi->mode) {
1551 case LWS_CONNMODE_SERVER_LISTENER:
1552
1553 /* pollin means a client has connected to us then */
1554
David Galeanob88e0962013-01-10 09:54:10 +08001555 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001556 break;
1557
David Galeanof7009352011-09-26 12:09:54 +01001558 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001559 lwsl_warn("too busy to accept new client\n");
David Galeanof7009352011-09-26 12:09:54 +01001560 break;
1561 }
1562
Andy Green0d338332011-02-12 11:57:43 +00001563 /* listen socket got an unencrypted connection... */
1564
1565 clilen = sizeof(cli_addr);
1566 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1567 &clilen);
1568 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001569 lwsl_warn("ERROR on accept: %d\n", strerror(errno));
Andy Green3928f612012-07-20 12:58:38 +08001570 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001571 }
1572
Andy Green6c939552011-03-08 08:56:57 +00001573 /* Disable Nagle */
1574 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08001575 setsockopt(accept_fd, IPPROTO_TCP, TCP_NODELAY,
1576 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00001577
Andy Green07034092011-02-13 08:37:12 +00001578 /*
1579 * look at who we connected to and give user code a chance
1580 * to reject based on client IP. There's no protocol selected
1581 * yet so we issue this to protocols[0]
1582 */
1583
Peter Hinz56885f32011-03-02 22:03:47 +00001584 if ((context->protocols[0].callback)(context, wsi,
Andy Green07034092011-02-13 08:37:12 +00001585 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
Andy Green6ee372f2012-04-09 15:09:01 +08001586 (void *)(long)accept_fd, NULL, 0)) {
Andy Green43db0452013-01-10 19:50:35 +08001587 lwsl_debug("Callback denied network connection\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001588#ifdef WIN32
1589 closesocket(accept_fd);
1590#else
Andy Green07034092011-02-13 08:37:12 +00001591 close(accept_fd);
Peter Hinz56885f32011-03-02 22:03:47 +00001592#endif
Andy Green07034092011-02-13 08:37:12 +00001593 break;
1594 }
1595
Andy Green0d338332011-02-12 11:57:43 +00001596 /* accepting connection to main listener */
1597
Andy Greena41314f2011-05-23 10:00:03 +01001598 new_wsi = libwebsocket_create_new_server_wsi(context);
David Galeanoed3c8402013-01-10 10:45:24 +08001599 if (new_wsi == NULL) {
1600#ifdef WIN32
1601 closesocket(accept_fd);
1602#else
1603 close(accept_fd);
1604#endif
Andy Green0d338332011-02-12 11:57:43 +00001605 break;
David Galeanoed3c8402013-01-10 10:45:24 +08001606 }
Andy Green0d338332011-02-12 11:57:43 +00001607
Andy Green0d338332011-02-12 11:57:43 +00001608 new_wsi->sock = accept_fd;
Andy Greena41314f2011-05-23 10:00:03 +01001609
Andy Green0d338332011-02-12 11:57:43 +00001610
1611#ifdef LWS_OPENSSL_SUPPORT
1612 new_wsi->ssl = NULL;
Andy Green0d338332011-02-12 11:57:43 +00001613
Peter Hinz56885f32011-03-02 22:03:47 +00001614 if (context->use_ssl) {
Andy Green0d338332011-02-12 11:57:43 +00001615
Peter Hinz56885f32011-03-02 22:03:47 +00001616 new_wsi->ssl = SSL_new(context->ssl_ctx);
Andy Green0d338332011-02-12 11:57:43 +00001617 if (new_wsi->ssl == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08001618 lwsl_err("SSL_new failed: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001619 ERR_error_string(SSL_get_error(
1620 new_wsi->ssl, 0), NULL));
Andy Green1f9bf522011-02-14 21:14:37 +00001621 libwebsockets_decode_ssl_error();
Andy Green0d338332011-02-12 11:57:43 +00001622 free(new_wsi);
David Galeanoed3c8402013-01-10 10:45:24 +08001623#ifdef WIN32
1624 closesocket(accept_fd);
1625#else
1626 close(accept_fd);
1627#endif
Andy Green0d338332011-02-12 11:57:43 +00001628 break;
1629 }
1630
1631 SSL_set_fd(new_wsi->ssl, accept_fd);
1632
1633 n = SSL_accept(new_wsi->ssl);
1634 if (n != 1) {
1635 /*
1636 * browsers seem to probe with various
1637 * ssl params which fail then retry
1638 * and succeed
1639 */
Andy Green43db0452013-01-10 19:50:35 +08001640 lwsl_debug("SSL_accept failed skt %u: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001641 pollfd->fd,
1642 ERR_error_string(SSL_get_error(
1643 new_wsi->ssl, n), NULL));
1644 SSL_free(
1645 new_wsi->ssl);
1646 free(new_wsi);
David Galeanoed3c8402013-01-10 10:45:24 +08001647#ifdef WIN32
1648 closesocket(accept_fd);
1649#else
1650 close(accept_fd);
1651#endif
Andy Green0d338332011-02-12 11:57:43 +00001652 break;
1653 }
Andy Green6ee372f2012-04-09 15:09:01 +08001654
Andy Green43db0452013-01-10 19:50:35 +08001655 lwsl_debug("accepted new SSL conn "
Andy Green0d338332011-02-12 11:57:43 +00001656 "port %u on fd=%d SSL ver %s\n",
1657 ntohs(cli_addr.sin_port), accept_fd,
1658 SSL_get_version(new_wsi->ssl));
1659
1660 } else
1661#endif
Andy Green43db0452013-01-10 19:50:35 +08001662 lwsl_debug("accepted new conn port %u on fd=%d\n",
Andy Green0d338332011-02-12 11:57:43 +00001663 ntohs(cli_addr.sin_port), accept_fd);
1664
Peter Hinz56885f32011-03-02 22:03:47 +00001665 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001666
Andy Green0d338332011-02-12 11:57:43 +00001667 /*
1668 * make sure NO events are seen yet on this new socket
1669 * (otherwise we inherit old fds[client].revents from
1670 * previous socket there and die mysteriously! )
1671 */
Peter Hinz56885f32011-03-02 22:03:47 +00001672 context->fds[context->fds_count].revents = 0;
Andy Green0d338332011-02-12 11:57:43 +00001673
Peter Hinz56885f32011-03-02 22:03:47 +00001674 context->fds[context->fds_count].events = POLLIN;
1675 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001676
Andy Green3221f922011-02-12 13:14:11 +00001677 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001678 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001679 LWS_CALLBACK_ADD_POLL_FD,
1680 (void *)(long)accept_fd, NULL, POLLIN);
1681
Andy Green0d338332011-02-12 11:57:43 +00001682 break;
1683
1684 case LWS_CONNMODE_BROADCAST_PROXY_LISTENER:
1685
1686 /* as we are listening, POLLIN means accept() is needed */
Andy Green6ee372f2012-04-09 15:09:01 +08001687
David Galeanob88e0962013-01-10 09:54:10 +08001688 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001689 break;
1690
1691 /* listen socket got an unencrypted connection... */
1692
1693 clilen = sizeof(cli_addr);
1694 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1695 &clilen);
1696 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001697 lwsl_warn("ERROR on accept %d\n", accept_fd);
Andy Green3928f612012-07-20 12:58:38 +08001698 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001699 }
1700
Peter Hinz56885f32011-03-02 22:03:47 +00001701 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001702 lwsl_err("too busy to accept new broadcast "
Andy Green3221f922011-02-12 13:14:11 +00001703 "proxy client\n");
Andy Green41c58032013-01-12 13:21:08 +08001704 goto bail_prox_listener;
Andy Green0d338332011-02-12 11:57:43 +00001705 }
1706
1707 /* create a dummy wsi for the connection and add it */
1708
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001709 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08001710 if (new_wsi == NULL) {
1711 lwsl_err("Out of mem\n");
1712 goto bail_prox_listener;
1713 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001714 memset(new_wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00001715 new_wsi->sock = accept_fd;
1716 new_wsi->mode = LWS_CONNMODE_BROADCAST_PROXY;
1717 new_wsi->state = WSI_STATE_ESTABLISHED;
Andy Greend6e09112011-03-05 16:12:15 +00001718 new_wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00001719 /* note which protocol we are proxying */
1720 new_wsi->protocol_index_for_broadcast_proxy =
1721 wsi->protocol_index_for_broadcast_proxy;
Peter Hinz56885f32011-03-02 22:03:47 +00001722 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001723
1724 /* add connected socket to internal poll array */
1725
Peter Hinz56885f32011-03-02 22:03:47 +00001726 context->fds[context->fds_count].revents = 0;
1727 context->fds[context->fds_count].events = POLLIN;
1728 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001729
Andy Green3221f922011-02-12 13:14:11 +00001730 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001731 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001732 LWS_CALLBACK_ADD_POLL_FD,
1733 (void *)(long)accept_fd, NULL, POLLIN);
1734
Andy Green0d338332011-02-12 11:57:43 +00001735 break;
1736
Andy Green41c58032013-01-12 13:21:08 +08001737bail_prox_listener:
1738#ifdef WIN32
1739 closesocket(accept_fd);
1740#else
1741 close(accept_fd);
1742#endif
1743 break;
1744
Andy Green0d338332011-02-12 11:57:43 +00001745 case LWS_CONNMODE_BROADCAST_PROXY:
Andy Green8f037e42010-12-19 22:13:26 +00001746
Andy Greenb45993c2010-12-18 15:13:50 +00001747 /* handle session socket closed */
Andy Green8f037e42010-12-19 22:13:26 +00001748
Andy Green0d338332011-02-12 11:57:43 +00001749 if (pollfd->revents & (POLLERR | POLLHUP)) {
Andy Green8f037e42010-12-19 22:13:26 +00001750
Andy Green43db0452013-01-10 19:50:35 +08001751 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Timothy J Fontaineb86d64e2011-02-14 17:55:27 +00001752 (void *)wsi, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001753
Peter Hinz56885f32011-03-02 22:03:47 +00001754 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001755 LWS_CLOSE_STATUS_NORMAL);
Andy Green4b6fbe12011-02-14 08:03:48 +00001756 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00001757 }
Andy Green8f037e42010-12-19 22:13:26 +00001758
Andy Green3b84c002011-03-06 13:14:42 +00001759 /*
1760 * either extension code with stuff to spill, or the user code,
1761 * requested a callback when it was OK to write
1762 */
Andy Green90c7cbc2011-01-27 06:26:52 +00001763
Andy Green3b84c002011-03-06 13:14:42 +00001764 if (pollfd->revents & POLLOUT)
Andy Green6ee372f2012-04-09 15:09:01 +08001765 if (lws_handle_POLLOUT_event(context, wsi,
1766 pollfd) < 0) {
1767 libwebsocket_close_and_free_session(
1768 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00001769 return 1;
1770 }
Andy Green90c7cbc2011-01-27 06:26:52 +00001771
Andy Greenb45993c2010-12-18 15:13:50 +00001772 /* any incoming data ready? */
1773
Andy Green0d338332011-02-12 11:57:43 +00001774 if (!(pollfd->revents & POLLIN))
1775 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001776
Andy Green0d338332011-02-12 11:57:43 +00001777 /* get the issued broadcast payload from the socket */
Andy Greenb45993c2010-12-18 15:13:50 +00001778
Andy Green0d338332011-02-12 11:57:43 +00001779 len = read(pollfd->fd, buf + LWS_SEND_BUFFER_PRE_PADDING,
1780 MAX_BROADCAST_PAYLOAD);
1781 if (len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001782 lwsl_err("Error reading broadcast payload\n");
Andy Green4b6fbe12011-02-14 08:03:48 +00001783 break;
Andy Green0d338332011-02-12 11:57:43 +00001784 }
Andy Greenb45993c2010-12-18 15:13:50 +00001785
Andy Green0d338332011-02-12 11:57:43 +00001786 /* broadcast it to all guys with this protocol index */
Andy Green8f037e42010-12-19 22:13:26 +00001787
Andy Green0d338332011-02-12 11:57:43 +00001788 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Green8f037e42010-12-19 22:13:26 +00001789
Peter Hinz56885f32011-03-02 22:03:47 +00001790 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00001791
Peter Hinz56885f32011-03-02 22:03:47 +00001792 new_wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00001793
Andy Green0d338332011-02-12 11:57:43 +00001794 /* only to clients we are serving to */
Andy Greenb45993c2010-12-18 15:13:50 +00001795
Andy Green0d338332011-02-12 11:57:43 +00001796 if (new_wsi->mode != LWS_CONNMODE_WS_SERVING)
Andy Greenb45993c2010-12-18 15:13:50 +00001797 continue;
1798
1799 /*
1800 * never broadcast to non-established
1801 * connection
1802 */
1803
Andy Green0d338332011-02-12 11:57:43 +00001804 if (new_wsi->state != WSI_STATE_ESTABLISHED)
Andy Green4739e5c2011-01-22 12:51:57 +00001805 continue;
1806
Andy Greenb45993c2010-12-18 15:13:50 +00001807 /*
1808 * only broadcast to connections using
1809 * the requested protocol
1810 */
1811
Andy Green0d338332011-02-12 11:57:43 +00001812 if (new_wsi->protocol->protocol_index !=
1813 wsi->protocol_index_for_broadcast_proxy)
Andy Greenb45993c2010-12-18 15:13:50 +00001814 continue;
1815
Andy Green8f037e42010-12-19 22:13:26 +00001816 /* broadcast it to this connection */
1817
Peter Hinz56885f32011-03-02 22:03:47 +00001818 new_wsi->protocol->callback(context, new_wsi,
Andy Green8f037e42010-12-19 22:13:26 +00001819 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00001820 new_wsi->user_space,
Andy Green0ca6a172010-12-19 20:50:01 +00001821 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
Andy Greenb45993c2010-12-18 15:13:50 +00001822 }
Andy Green0d338332011-02-12 11:57:43 +00001823 }
1824 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001825
Andy Greenbe93fef2011-02-14 20:25:43 +00001826 case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
1827
1828 /* handle proxy hung up on us */
1829
1830 if (pollfd->revents & (POLLERR | POLLHUP)) {
1831
Andy Green43db0452013-01-10 19:50:35 +08001832 lwsl_warn("Proxy connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00001833 (void *)wsi, pollfd->fd);
1834
Peter Hinz56885f32011-03-02 22:03:47 +00001835 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001836 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001837 return 1;
1838 }
1839
Andy Green72c34322011-04-16 10:46:21 +01001840 n = recv(wsi->sock, pkt, sizeof pkt, 0);
Andy Greenbe93fef2011-02-14 20:25:43 +00001841 if (n < 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001842 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001843 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001844 lwsl_err("ERROR reading from proxy socket\n");
Andy Greenbe93fef2011-02-14 20:25:43 +00001845 return 1;
1846 }
1847
1848 pkt[13] = '\0';
1849 if (strcmp(pkt, "HTTP/1.0 200 ") != 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001850 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001851 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001852 lwsl_err("ERROR from proxy: %s\n", pkt);
Andy Greenbe93fef2011-02-14 20:25:43 +00001853 return 1;
1854 }
1855
1856 /* clear his proxy connection timeout */
1857
1858 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1859
1860 /* fallthru */
1861
1862 case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
1863
1864 #ifdef LWS_OPENSSL_SUPPORT
Ken Atherton8360a472012-05-03 11:45:04 +08001865 if (wsi->use_ssl && !wsi->ssl) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001866
Peter Hinz56885f32011-03-02 22:03:47 +00001867 wsi->ssl = SSL_new(context->ssl_client_ctx);
1868 wsi->client_bio = BIO_new_socket(wsi->sock,
1869 BIO_NOCLOSE);
Andy Greenbe93fef2011-02-14 20:25:43 +00001870 SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
1871
Andy Green6901cb32011-02-21 08:06:47 +00001872 SSL_set_ex_data(wsi->ssl,
Andy Green2e24da02011-03-05 16:12:04 +00001873 openssl_websocket_private_data_index,
Peter Hinz56885f32011-03-02 22:03:47 +00001874 context);
Ken Atherton8360a472012-05-03 11:45:04 +08001875 }
Andy Green6901cb32011-02-21 08:06:47 +00001876
Ken Atherton8360a472012-05-03 11:45:04 +08001877 if (wsi->use_ssl) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001878 if (SSL_connect(wsi->ssl) <= 0) {
Ken Atherton8360a472012-05-03 11:45:04 +08001879
1880 /*
1881 * retry if new data comes until we
1882 * run into the connection timeout or win
1883 */
1884
Andy Green43db0452013-01-10 19:50:35 +08001885 lwsl_err("SSL connect error %s\n",
Andy Green687b0182011-02-26 11:04:01 +00001886 ERR_error_string(ERR_get_error(),
1887 ssl_err_buf));
Ken Atherton8360a472012-05-03 11:45:04 +08001888 return 0;
Andy Greenbe93fef2011-02-14 20:25:43 +00001889 }
1890
1891 n = SSL_get_verify_result(wsi->ssl);
Andy Green2e24da02011-03-05 16:12:04 +00001892 if ((n != X509_V_OK) && (
Andy Green687b0182011-02-26 11:04:01 +00001893 n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
1894 wsi->use_ssl != 2)) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001895
Andy Green43db0452013-01-10 19:50:35 +08001896 lwsl_err("server's cert didn't "
Andy Green687b0182011-02-26 11:04:01 +00001897 "look good %d\n", n);
Peter Hinz56885f32011-03-02 22:03:47 +00001898 libwebsocket_close_and_free_session(context,
1899 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Green687b0182011-02-26 11:04:01 +00001900 return 1;
Andy Greenbe93fef2011-02-14 20:25:43 +00001901 }
Ken Atherton8360a472012-05-03 11:45:04 +08001902 } else
Andy Greenbe93fef2011-02-14 20:25:43 +00001903 wsi->ssl = NULL;
1904 #endif
1905
Andy Greena41314f2011-05-23 10:00:03 +01001906 p = libwebsockets_generate_client_handshake(context, wsi, p);
Andy Green6ee372f2012-04-09 15:09:01 +08001907 if (p == NULL)
Andy Greenbe93fef2011-02-14 20:25:43 +00001908 return 1;
Andy Greeneeaacb32011-03-01 20:44:24 +00001909
Andy Greenbe93fef2011-02-14 20:25:43 +00001910 /* send our request to the server */
1911
1912 #ifdef LWS_OPENSSL_SUPPORT
1913 if (wsi->use_ssl)
1914 n = SSL_write(wsi->ssl, pkt, p - pkt);
1915 else
1916 #endif
1917 n = send(wsi->sock, pkt, p - pkt, 0);
1918
1919 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001920 lwsl_debug("ERROR writing to client socket\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001921 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001922 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001923 return 1;
1924 }
1925
1926 wsi->parser_state = WSI_TOKEN_NAME_PART;
1927 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
1928 libwebsocket_set_timeout(wsi,
David Galeanoc9f1ff82013-01-09 18:01:23 +08001929 PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, AWAITING_TIMEOUT);
Andy Greenbe93fef2011-02-14 20:25:43 +00001930
1931 break;
1932
1933 case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
1934
1935 /* handle server hung up on us */
1936
1937 if (pollfd->revents & (POLLERR | POLLHUP)) {
1938
Andy Green43db0452013-01-10 19:50:35 +08001939 lwsl_debug("Server connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00001940 (void *)wsi, pollfd->fd);
1941
1942 goto bail3;
1943 }
1944
1945
1946 /* interpret the server response */
1947
1948 /*
1949 * HTTP/1.1 101 Switching Protocols
1950 * Upgrade: websocket
1951 * Connection: Upgrade
1952 * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
1953 * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
1954 * Sec-WebSocket-Protocol: chat
1955 */
1956
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001957 /*
1958 * we have to take some care here to only take from the
1959 * socket bytewise. The browser may (and has been seen to
1960 * in the case that onopen() performs websocket traffic)
1961 * coalesce both handshake response and websocket traffic
1962 * in one packet, since at that point the connection is
1963 * definitively ready from browser pov.
1964 */
Andy Greenbe93fef2011-02-14 20:25:43 +00001965
Andy Green7b5af9a2012-04-09 15:23:47 +08001966 len = 1;
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001967 while (wsi->parser_state != WSI_PARSING_COMPLETE && len > 0) {
1968#ifdef LWS_OPENSSL_SUPPORT
1969 if (wsi->use_ssl)
1970 len = SSL_read(wsi->ssl, &c, 1);
1971 else
1972#endif
1973 len = recv(wsi->sock, &c, 1, 0);
1974
1975 libwebsocket_parse(wsi, c);
Andy Greenbe93fef2011-02-14 20:25:43 +00001976 }
1977
Andy Green27a0b912011-04-16 10:54:28 +01001978 /*
Andy Green6ee372f2012-04-09 15:09:01 +08001979 * hs may also be coming in multiple packets, there is a 5-sec
Andy Green27a0b912011-04-16 10:54:28 +01001980 * libwebsocket timeout still active here too, so if parsing did
1981 * not complete just wait for next packet coming in this state
1982 */
1983
1984 if (wsi->parser_state != WSI_PARSING_COMPLETE)
1985 break;
Andy Greenbe93fef2011-02-14 20:25:43 +00001986
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001987 /*
1988 * otherwise deal with the handshake. If there's any
1989 * packet traffic already arrived we'll trigger poll() again
1990 * right away and deal with it that way
1991 */
1992
Andy Greena41314f2011-05-23 10:00:03 +01001993 return lws_client_interpret_server_handshake(context, wsi);
Andy Greenbe93fef2011-02-14 20:25:43 +00001994
1995bail3:
1996 if (wsi->c_protocol)
1997 free(wsi->c_protocol);
Peter Hinz56885f32011-03-02 22:03:47 +00001998 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08001999 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00002000 return 1;
Andy Greena41314f2011-05-23 10:00:03 +01002001
2002 case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
Andy Green43db0452013-01-10 19:50:35 +08002003 lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
Andy Greena41314f2011-05-23 10:00:03 +01002004 break;
2005
2006 case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
Andy Green43db0452013-01-10 19:50:35 +08002007 lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
Andy Greena41314f2011-05-23 10:00:03 +01002008 break;
2009
Andy Greenbe93fef2011-02-14 20:25:43 +00002010
Andy Green0d338332011-02-12 11:57:43 +00002011 case LWS_CONNMODE_WS_SERVING:
2012 case LWS_CONNMODE_WS_CLIENT:
2013
2014 /* handle session socket closed */
2015
2016 if (pollfd->revents & (POLLERR | POLLHUP)) {
2017
Andy Green43db0452013-01-10 19:50:35 +08002018 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Andy Green0d338332011-02-12 11:57:43 +00002019 (void *)wsi, pollfd->fd);
2020
Peter Hinz56885f32011-03-02 22:03:47 +00002021 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002022 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green4b6fbe12011-02-14 08:03:48 +00002023 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002024 }
2025
Andy Green0d338332011-02-12 11:57:43 +00002026 /* the guy requested a callback when it was OK to write */
2027
Andy Greenda527df2011-03-07 07:08:12 +00002028 if ((pollfd->revents & POLLOUT) &&
2029 wsi->state == WSI_STATE_ESTABLISHED)
2030 if (lws_handle_POLLOUT_event(context, wsi,
2031 pollfd) < 0) {
2032 libwebsocket_close_and_free_session(
2033 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00002034 return 1;
2035 }
Andy Green0d338332011-02-12 11:57:43 +00002036
Andy Green0d338332011-02-12 11:57:43 +00002037
2038 /* any incoming data ready? */
2039
2040 if (!(pollfd->revents & POLLIN))
2041 break;
2042
Andy Greenb45993c2010-12-18 15:13:50 +00002043#ifdef LWS_OPENSSL_SUPPORT
David Galeano7ffbe1b2013-01-10 10:35:32 +08002044read_pending:
Andy Green0d338332011-02-12 11:57:43 +00002045 if (wsi->ssl)
Andy Green98a717c2011-03-06 13:14:15 +00002046 eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);
Andy Greenb45993c2010-12-18 15:13:50 +00002047 else
2048#endif
Andy Green98a717c2011-03-06 13:14:15 +00002049 eff_buf.token_len =
Andy Green72c34322011-04-16 10:46:21 +01002050 recv(pollfd->fd, buf, sizeof buf, 0);
Andy Greenb45993c2010-12-18 15:13:50 +00002051
Andy Green98a717c2011-03-06 13:14:15 +00002052 if (eff_buf.token_len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002053 lwsl_debug("Socket read returned %d\n",
Andy Green98a717c2011-03-06 13:14:15 +00002054 eff_buf.token_len);
Alon Levydc93b7f2012-10-19 11:21:57 +02002055 if (errno != EINTR && errno != EAGAIN)
Andy Green6ee372f2012-04-09 15:09:01 +08002056 libwebsocket_close_and_free_session(context,
2057 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Nick Dowellc04c1932012-04-05 10:29:39 +08002058 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002059 }
Andy Green98a717c2011-03-06 13:14:15 +00002060 if (!eff_buf.token_len) {
Peter Hinz56885f32011-03-02 22:03:47 +00002061 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002062 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenfa3f4052012-10-07 20:40:35 +08002063 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00002064 }
2065
Andy Green98a717c2011-03-06 13:14:15 +00002066 /*
2067 * give any active extensions a chance to munge the buffer
2068 * before parse. We pass in a pointer to an lws_tokens struct
2069 * prepared with the default buffer and content length that's in
2070 * there. Rather than rewrite the default buffer, extensions
2071 * that expect to grow the buffer can adapt .token to
2072 * point to their own per-connection buffer in the extension
2073 * user allocation. By default with no extensions or no
2074 * extension callback handling, just the normal input buffer is
2075 * used then so it is efficient.
2076 */
Andy Greenb45993c2010-12-18 15:13:50 +00002077
Andy Green98a717c2011-03-06 13:14:15 +00002078 eff_buf.token = (char *)buf;
Andy Greenb45993c2010-12-18 15:13:50 +00002079
Andy Green98a717c2011-03-06 13:14:15 +00002080 more = 1;
2081 while (more) {
Andy Green0d338332011-02-12 11:57:43 +00002082
Andy Green98a717c2011-03-06 13:14:15 +00002083 more = 0;
2084
2085 for (n = 0; n < wsi->count_active_extensions; n++) {
Andy Green46c2ea02011-03-22 09:04:01 +00002086 m = wsi->active_extensions[n]->callback(context,
2087 wsi->active_extensions[n], wsi,
Andy Green98a717c2011-03-06 13:14:15 +00002088 LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
Andy Green46c2ea02011-03-22 09:04:01 +00002089 wsi->active_extensions_user[n],
2090 &eff_buf, 0);
Andy Green98a717c2011-03-06 13:14:15 +00002091 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002092 lwsl_ext(
Andy Green6ee372f2012-04-09 15:09:01 +08002093 "Extension reports fatal error\n");
2094 libwebsocket_close_and_free_session(
2095 context, wsi,
2096 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green98a717c2011-03-06 13:14:15 +00002097 return 1;
2098 }
2099 if (m)
2100 more = 1;
2101 }
2102
2103 /* service incoming data */
2104
2105 if (eff_buf.token_len) {
2106 n = libwebsocket_read(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002107 (unsigned char *)eff_buf.token,
2108 eff_buf.token_len);
Andy Green98a717c2011-03-06 13:14:15 +00002109 if (n < 0)
2110 /* we closed wsi */
2111 return 1;
2112 }
2113
2114 eff_buf.token = NULL;
2115 eff_buf.token_len = 0;
2116 }
David Galeano7ffbe1b2013-01-10 10:35:32 +08002117
2118#ifdef LWS_OPENSSL_SUPPORT
2119 if (wsi->ssl && SSL_pending(wsi->ssl))
2120 goto read_pending;
2121#endif
Andy Green98a717c2011-03-06 13:14:15 +00002122 break;
Andy Greenb45993c2010-12-18 15:13:50 +00002123 }
2124
2125 return 0;
2126}
2127
Andy Green0d338332011-02-12 11:57:43 +00002128
Andy Green6964bb52011-01-23 16:50:33 +00002129/**
2130 * libwebsocket_context_destroy() - Destroy the websocket context
Peter Hinz56885f32011-03-02 22:03:47 +00002131 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002132 *
2133 * This function closes any active connections and then frees the
2134 * context. After calling this, any further use of the context is
2135 * undefined.
2136 */
2137void
Peter Hinz56885f32011-03-02 22:03:47 +00002138libwebsocket_context_destroy(struct libwebsocket_context *context)
Andy Green6964bb52011-01-23 16:50:33 +00002139{
Andy Green0d338332011-02-12 11:57:43 +00002140 int n;
2141 int m;
2142 struct libwebsocket *wsi;
Andy Greena41314f2011-05-23 10:00:03 +01002143 struct libwebsocket_extension *ext;
Andy Green6964bb52011-01-23 16:50:33 +00002144
Andy Green4b6fbe12011-02-14 08:03:48 +00002145 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002146 for (m = 0; m < context->fd_hashtable[n].length; m++) {
2147 wsi = context->fd_hashtable[n].wsi[m];
2148 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002149 LWS_CLOSE_STATUS_GOINGAWAY);
Andy Greenf3d3b402011-02-09 07:16:34 +00002150 }
Andy Green6964bb52011-01-23 16:50:33 +00002151
Andy Greena41314f2011-05-23 10:00:03 +01002152 /*
2153 * give all extensions a chance to clean up any per-context
2154 * allocations they might have made
2155 */
2156
2157 ext = context->extensions;
2158 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
2159 if (context->listen_port)
2160 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
Paulo Roberto Urio1f680ab2012-06-04 08:40:28 +08002161 while (ext && ext->callback) {
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002162 ext->callback(context, ext, NULL, (enum libwebsocket_extension_callback_reasons)m, NULL, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01002163 ext++;
2164 }
2165
Peter Hinz56885f32011-03-02 22:03:47 +00002166#ifdef WIN32
2167#else
2168 close(context->fd_random);
Andy Green6964bb52011-01-23 16:50:33 +00002169#endif
2170
Peter Hinz56885f32011-03-02 22:03:47 +00002171#ifdef LWS_OPENSSL_SUPPORT
2172 if (context->ssl_ctx)
2173 SSL_CTX_free(context->ssl_ctx);
2174 if (context->ssl_client_ctx)
2175 SSL_CTX_free(context->ssl_client_ctx);
2176#endif
2177
2178 free(context);
2179
2180#ifdef WIN32
2181 WSACleanup();
2182#endif
Andy Green6964bb52011-01-23 16:50:33 +00002183}
2184
Alon Levy0291eb32012-10-19 11:21:56 +02002185LWS_EXTERN void *
2186libwebsocket_context_user(struct libwebsocket_context *context)
2187{
2188 return context->user_space;
2189}
2190
Andy Green6964bb52011-01-23 16:50:33 +00002191/**
2192 * libwebsocket_service() - Service any pending websocket activity
Peter Hinz56885f32011-03-02 22:03:47 +00002193 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002194 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
2195 * service otherwise block and service immediately, returning
2196 * after the timeout if nothing needed service.
2197 *
2198 * This function deals with any pending websocket traffic, for three
2199 * kinds of event. It handles these events on both server and client
2200 * types of connection the same.
2201 *
2202 * 1) Accept new connections to our context's server
2203 *
2204 * 2) Perform pending broadcast writes initiated from other forked
2205 * processes (effectively serializing asynchronous broadcasts)
2206 *
2207 * 3) Call the receive callback for incoming frame data received by
2208 * server or client connections.
2209 *
2210 * You need to call this service function periodically to all the above
2211 * functions to happen; if your application is single-threaded you can
2212 * just call it in your main event loop.
2213 *
2214 * Alternatively you can fork a new process that asynchronously handles
2215 * calling this service in a loop. In that case you are happy if this
2216 * call blocks your thread until it needs to take care of something and
2217 * would call it with a large nonzero timeout. Your loop then takes no
2218 * CPU while there is nothing happening.
2219 *
2220 * If you are calling it in a single-threaded app, you don't want it to
2221 * wait around blocking other things in your loop from happening, so you
2222 * would call it with a timeout_ms of 0, so it returns immediately if
2223 * nothing is pending, or as soon as it services whatever was pending.
2224 */
2225
Andy Greenb45993c2010-12-18 15:13:50 +00002226
Andy Greene92cd172011-01-19 13:11:55 +00002227int
Peter Hinz56885f32011-03-02 22:03:47 +00002228libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
Andy Greene92cd172011-01-19 13:11:55 +00002229{
2230 int n;
Andy Greene92cd172011-01-19 13:11:55 +00002231
2232 /* stay dead once we are dead */
2233
Peter Hinz56885f32011-03-02 22:03:47 +00002234 if (context == NULL)
Andy Greene92cd172011-01-19 13:11:55 +00002235 return 1;
2236
Andy Green0d338332011-02-12 11:57:43 +00002237 /* wait for something to need service */
Andy Green4739e5c2011-01-22 12:51:57 +00002238
Peter Hinz56885f32011-03-02 22:03:47 +00002239 n = poll(context->fds, context->fds_count, timeout_ms);
Andy Green3221f922011-02-12 13:14:11 +00002240 if (n == 0) /* poll timeout */
2241 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002242
Andy Green62c54d22011-02-14 09:14:25 +00002243 if (n < 0) {
Andy Green5e1fa172011-02-10 09:07:05 +00002244 /*
Andy Green43db0452013-01-10 19:50:35 +08002245 lwsl_err("Listen Socket dead\n");
Andy Green5e1fa172011-02-10 09:07:05 +00002246 */
Andy Green3928f612012-07-20 12:58:38 +08002247 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002248 }
Andy Greene92cd172011-01-19 13:11:55 +00002249
2250 /* handle accept on listening socket? */
2251
Peter Hinz56885f32011-03-02 22:03:47 +00002252 for (n = 0; n < context->fds_count; n++)
2253 if (context->fds[n].revents)
Andy Green3928f612012-07-20 12:58:38 +08002254 if (libwebsocket_service_fd(context,
2255 &context->fds[n]) < 0)
2256 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002257 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002258}
2259
Andy Greena41314f2011-05-23 10:00:03 +01002260int
2261lws_any_extension_handled(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002262 struct libwebsocket *wsi,
2263 enum libwebsocket_extension_callback_reasons r,
Andy Greena41314f2011-05-23 10:00:03 +01002264 void *v, size_t len)
2265{
2266 int n;
2267 int handled = 0;
2268
2269 /* maybe an extension will take care of it for us */
2270
2271 for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
2272 if (!wsi->active_extensions[n]->callback)
2273 continue;
2274
2275 handled |= wsi->active_extensions[n]->callback(context,
2276 wsi->active_extensions[n], wsi,
2277 r, wsi->active_extensions_user[n], v, len);
2278 }
2279
2280 return handled;
2281}
2282
2283
2284void *
2285lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002286 struct libwebsocket_extension *ext)
Andy Greena41314f2011-05-23 10:00:03 +01002287{
2288 int n = 0;
2289
Andy Green68b45042011-05-25 21:41:57 +01002290 if (wsi == NULL)
2291 return NULL;
2292
Andy Greena41314f2011-05-23 10:00:03 +01002293 while (n < wsi->count_active_extensions) {
2294 if (wsi->active_extensions[n] != ext) {
2295 n++;
2296 continue;
2297 }
2298 return wsi->active_extensions_user[n];
2299 }
2300
2301 return NULL;
2302}
2303
Andy Green90c7cbc2011-01-27 06:26:52 +00002304/**
2305 * libwebsocket_callback_on_writable() - Request a callback when this socket
2306 * becomes able to be written to without
2307 * blocking
Andy Green32375b72011-02-19 08:32:53 +00002308 *
Peter Hinz56885f32011-03-02 22:03:47 +00002309 * @context: libwebsockets context
Andy Green90c7cbc2011-01-27 06:26:52 +00002310 * @wsi: Websocket connection instance to get callback for
2311 */
2312
2313int
Peter Hinz56885f32011-03-02 22:03:47 +00002314libwebsocket_callback_on_writable(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002315 struct libwebsocket *wsi)
Andy Green90c7cbc2011-01-27 06:26:52 +00002316{
Andy Green90c7cbc2011-01-27 06:26:52 +00002317 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002318 int handled = 0;
2319
2320 /* maybe an extension will take care of it for us */
2321
2322 for (n = 0; n < wsi->count_active_extensions; n++) {
2323 if (!wsi->active_extensions[n]->callback)
2324 continue;
2325
2326 handled |= wsi->active_extensions[n]->callback(context,
2327 wsi->active_extensions[n], wsi,
2328 LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
2329 wsi->active_extensions_user[n], NULL, 0);
2330 }
2331
2332 if (handled)
2333 return 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002334
Peter Hinz56885f32011-03-02 22:03:47 +00002335 for (n = 0; n < context->fds_count; n++)
2336 if (context->fds[n].fd == wsi->sock) {
2337 context->fds[n].events |= POLLOUT;
Andy Greena41314f2011-05-23 10:00:03 +01002338 n = context->fds_count + 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002339 }
2340
Andy Greena41314f2011-05-23 10:00:03 +01002341 if (n == context->fds_count)
Andy Green43db0452013-01-10 19:50:35 +08002342 lwsl_err("libwebsocket_callback_on_writable: "
Andy Green6ee372f2012-04-09 15:09:01 +08002343 "failed to find socket %d\n", wsi->sock);
Andy Greena41314f2011-05-23 10:00:03 +01002344
Andy Green3221f922011-02-12 13:14:11 +00002345 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002346 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002347 LWS_CALLBACK_SET_MODE_POLL_FD,
2348 (void *)(long)wsi->sock, NULL, POLLOUT);
2349
Andy Green90c7cbc2011-01-27 06:26:52 +00002350 return 1;
2351}
2352
2353/**
2354 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
2355 * all connections using the given protocol when it
2356 * becomes possible to write to each socket without
2357 * blocking in turn.
2358 *
2359 * @protocol: Protocol whose connections will get callbacks
2360 */
2361
2362int
2363libwebsocket_callback_on_writable_all_protocol(
2364 const struct libwebsocket_protocols *protocol)
2365{
Peter Hinz56885f32011-03-02 22:03:47 +00002366 struct libwebsocket_context *context = protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002367 int n;
Andy Green0d338332011-02-12 11:57:43 +00002368 int m;
2369 struct libwebsocket *wsi;
Andy Green90c7cbc2011-01-27 06:26:52 +00002370
Andy Green0d338332011-02-12 11:57:43 +00002371 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
2372
Peter Hinz56885f32011-03-02 22:03:47 +00002373 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Green0d338332011-02-12 11:57:43 +00002374
Peter Hinz56885f32011-03-02 22:03:47 +00002375 wsi = context->fd_hashtable[n].wsi[m];
Andy Green0d338332011-02-12 11:57:43 +00002376
2377 if (wsi->protocol == protocol)
Peter Hinz56885f32011-03-02 22:03:47 +00002378 libwebsocket_callback_on_writable(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002379 }
2380 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002381
2382 return 0;
2383}
2384
Andy Greenbe93fef2011-02-14 20:25:43 +00002385/**
2386 * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
2387 *
2388 * You will not need this unless you are doing something special
2389 *
2390 * @wsi: Websocket connection instance
2391 * @reason: timeout reason
2392 * @secs: how many seconds
2393 */
2394
2395void
2396libwebsocket_set_timeout(struct libwebsocket *wsi,
2397 enum pending_timeout reason, int secs)
2398{
2399 struct timeval tv;
2400
2401 gettimeofday(&tv, NULL);
2402
2403 wsi->pending_timeout_limit = tv.tv_sec + secs;
2404 wsi->pending_timeout = reason;
2405}
2406
Andy Greena6cbece2011-01-27 20:06:03 +00002407
2408/**
2409 * libwebsocket_get_socket_fd() - returns the socket file descriptor
2410 *
2411 * You will not need this unless you are doing something special
2412 *
2413 * @wsi: Websocket connection instance
2414 */
2415
2416int
2417libwebsocket_get_socket_fd(struct libwebsocket *wsi)
2418{
2419 return wsi->sock;
2420}
2421
Andy Green90c7cbc2011-01-27 06:26:52 +00002422/**
2423 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
2424 * receieved packets.
2425 *
2426 * If the output side of a server process becomes choked, this allows flow
2427 * control for the input side.
2428 *
2429 * @wsi: Websocket connection instance to get callback for
2430 * @enable: 0 = disable read servicing for this connection, 1 = enable
2431 */
2432
2433int
2434libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
2435{
Peter Hinz56885f32011-03-02 22:03:47 +00002436 struct libwebsocket_context *context = wsi->protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002437 int n;
2438
Peter Hinz56885f32011-03-02 22:03:47 +00002439 for (n = 0; n < context->fds_count; n++)
2440 if (context->fds[n].fd == wsi->sock) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002441 if (enable)
Peter Hinz56885f32011-03-02 22:03:47 +00002442 context->fds[n].events |= POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002443 else
Peter Hinz56885f32011-03-02 22:03:47 +00002444 context->fds[n].events &= ~POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002445
2446 return 0;
2447 }
2448
Andy Green3221f922011-02-12 13:14:11 +00002449 if (enable)
2450 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002451 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002452 LWS_CALLBACK_SET_MODE_POLL_FD,
2453 (void *)(long)wsi->sock, NULL, POLLIN);
2454 else
2455 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002456 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002457 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
2458 (void *)(long)wsi->sock, NULL, POLLIN);
2459
Andy Greena41314f2011-05-23 10:00:03 +01002460#if 0
Andy Green43db0452013-01-10 19:50:35 +08002461 lwsl_err("libwebsocket_rx_flow_control unable to find socket\n");
Andy Greena41314f2011-05-23 10:00:03 +01002462#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002463 return 1;
2464}
2465
Andy Green2ac5a6f2011-01-28 10:00:18 +00002466/**
2467 * libwebsocket_canonical_hostname() - returns this host's hostname
2468 *
2469 * This is typically used by client code to fill in the host parameter
2470 * when making a client connection. You can only call it after the context
2471 * has been created.
2472 *
Peter Hinz56885f32011-03-02 22:03:47 +00002473 * @context: Websocket context
Andy Green2ac5a6f2011-01-28 10:00:18 +00002474 */
2475
2476
2477extern const char *
Peter Hinz56885f32011-03-02 22:03:47 +00002478libwebsocket_canonical_hostname(struct libwebsocket_context *context)
Andy Green2ac5a6f2011-01-28 10:00:18 +00002479{
Peter Hinz56885f32011-03-02 22:03:47 +00002480 return (const char *)context->canonical_hostname;
Andy Green2ac5a6f2011-01-28 10:00:18 +00002481}
2482
2483
Andy Green90c7cbc2011-01-27 06:26:52 +00002484static void sigpipe_handler(int x)
2485{
2486}
2487
Andy Green6901cb32011-02-21 08:06:47 +00002488#ifdef LWS_OPENSSL_SUPPORT
2489static int
2490OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
2491{
2492
2493 SSL *ssl;
2494 int n;
Andy Green2e24da02011-03-05 16:12:04 +00002495 struct libwebsocket_context *context;
Andy Green6901cb32011-02-21 08:06:47 +00002496
2497 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
2498 SSL_get_ex_data_X509_STORE_CTX_idx());
2499
2500 /*
Andy Green2e24da02011-03-05 16:12:04 +00002501 * !!! nasty openssl requires the index to come as a library-scope
2502 * static
Andy Green6901cb32011-02-21 08:06:47 +00002503 */
Andy Green2e24da02011-03-05 16:12:04 +00002504 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
Andy Green6ee372f2012-04-09 15:09:01 +08002505
Peter Hinz56885f32011-03-02 22:03:47 +00002506 n = context->protocols[0].callback(NULL, NULL,
Andy Green6901cb32011-02-21 08:06:47 +00002507 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
2508 x509_ctx, ssl, preverify_ok);
2509
2510 /* convert return code from 0 = OK to 1 = OK */
2511
2512 if (!n)
2513 n = 1;
2514 else
2515 n = 0;
2516
2517 return n;
2518}
2519#endif
2520
Andy Greenb45993c2010-12-18 15:13:50 +00002521
Andy Greenab990e42010-10-31 12:42:52 +00002522/**
Andy Green4739e5c2011-01-22 12:51:57 +00002523 * libwebsocket_create_context() - Create the websocket handler
2524 * @port: Port to listen on... you can use 0 to suppress listening on
Andy Green6964bb52011-01-23 16:50:33 +00002525 * any port, that's what you want if you are not running a
2526 * websocket server at all but just using it as a client
Peter Hinz56885f32011-03-02 22:03:47 +00002527 * @interf: NULL to bind the listen socket to all interfaces, or the
Andy Green32375b72011-02-19 08:32:53 +00002528 * interface name, eg, "eth2"
Andy Green4f3943a2010-11-12 10:44:16 +00002529 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +00002530 * specific callback for each one. The list is ended with an
2531 * entry that has a NULL callback pointer.
Andy Green6964bb52011-01-23 16:50:33 +00002532 * It's not const because we write the owning_server member
Andy Greenc5114822011-03-06 10:29:35 +00002533 * @extensions: NULL or array of libwebsocket_extension structs listing the
Andy Green6ee372f2012-04-09 15:09:01 +08002534 * extensions this context supports
Andy Green3faa9c72010-11-08 17:03:03 +00002535 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +00002536 * to listen using SSL, set to the filepath to fetch the
2537 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +00002538 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +00002539 * else ignored
David Galeano2f82be82013-01-09 16:25:54 +08002540 * @ssl_ca_filepath: CA certificate filepath or NULL
Andy Green3faa9c72010-11-08 17:03:03 +00002541 * @gid: group id to change to after setting listen socket, or -1.
2542 * @uid: user id to change to after setting listen socket, or -1.
Andy Greenbfb051f2011-02-09 08:49:14 +00002543 * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
Andy Green15e31f32012-10-19 18:36:28 +08002544 * @user: optional user pointer that can be recovered via the context
2545 * pointer using libwebsocket_context_user
Andy Green05464c62010-11-12 10:44:18 +00002546 *
Andy Green8f037e42010-12-19 22:13:26 +00002547 * This function creates the listening socket and takes care
2548 * of all initialization in one step.
2549 *
Andy Greene92cd172011-01-19 13:11:55 +00002550 * After initialization, it returns a struct libwebsocket_context * that
2551 * represents this server. After calling, user code needs to take care
2552 * of calling libwebsocket_service() with the context pointer to get the
2553 * server's sockets serviced. This can be done in the same process context
2554 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +00002555 *
Andy Green8f037e42010-12-19 22:13:26 +00002556 * The protocol callback functions are called for a handful of events
2557 * including http requests coming in, websocket connections becoming
2558 * established, and data arriving; it's also called periodically to allow
2559 * async transmission.
2560 *
2561 * HTTP requests are sent always to the FIRST protocol in @protocol, since
2562 * at that time websocket protocol has not been negotiated. Other
2563 * protocols after the first one never see any HTTP callack activity.
2564 *
2565 * The server created is a simple http server by default; part of the
2566 * websocket standard is upgrading this http connection to a websocket one.
2567 *
2568 * This allows the same server to provide files like scripts and favicon /
2569 * images or whatever over http and dynamic data over websockets all in
2570 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +00002571 */
Andy Green4ea60062010-10-30 12:15:07 +01002572
Andy Greene92cd172011-01-19 13:11:55 +00002573struct libwebsocket_context *
Peter Hinz56885f32011-03-02 22:03:47 +00002574libwebsocket_create_context(int port, const char *interf,
Andy Greenb45993c2010-12-18 15:13:50 +00002575 struct libwebsocket_protocols *protocols,
Andy Greend6e09112011-03-05 16:12:15 +00002576 struct libwebsocket_extension *extensions,
Andy Green8f037e42010-12-19 22:13:26 +00002577 const char *ssl_cert_filepath,
2578 const char *ssl_private_key_filepath,
David Galeano2f82be82013-01-09 16:25:54 +08002579 const char *ssl_ca_filepath,
Alon Levy0291eb32012-10-19 11:21:56 +02002580 int gid, int uid, unsigned int options,
David Galeano2f82be82013-01-09 16:25:54 +08002581 void *user)
Andy Greenff95d7a2010-10-28 22:36:01 +01002582{
2583 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002584 int m;
Andy Green4739e5c2011-01-22 12:51:57 +00002585 int sockfd = 0;
Andy Green251f6fa2010-11-03 11:13:06 +00002586 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +01002587 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +00002588 int opt = 1;
Peter Hinz56885f32011-03-02 22:03:47 +00002589 struct libwebsocket_context *context = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002590 unsigned int slen;
Andy Green9659f372011-01-27 22:01:43 +00002591 char *p;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002592 char hostname[1024] = "";
Andy Greena69f0512012-05-03 12:32:38 +08002593// struct hostent *he;
Andy Green0d338332011-02-12 11:57:43 +00002594 struct libwebsocket *wsi;
Andy Greena69f0512012-05-03 12:32:38 +08002595 struct sockaddr sa;
Andy Greenff95d7a2010-10-28 22:36:01 +01002596
Andy Green3faa9c72010-11-08 17:03:03 +00002597#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +00002598 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +00002599 char ssl_err_buf[512];
Andy Green3faa9c72010-11-08 17:03:03 +00002600#endif
2601
Andy Green43db0452013-01-10 19:50:35 +08002602 lwsl_info("Initial logging level %d\n", log_level);
Andy Greenc0d6b632013-01-12 23:42:17 +08002603 lwsl_info(" FD_HASHTABLE_MODULUS: %u\n", FD_HASHTABLE_MODULUS);
2604 lwsl_info(" MAX_CLIENTS: %u\n", MAX_CLIENTS);
2605 lwsl_info(" LWS_MAX_HEADER_NAME_LENGTH: %u\n", LWS_MAX_HEADER_NAME_LENGTH);
2606 lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
2607 lwsl_info(" LWS_INITIAL_HDR_ALLOC: %u\n", LWS_INITIAL_HDR_ALLOC);
2608 lwsl_info(" LWS_ADDITIONAL_HDR_ALLOC: %u\n", LWS_ADDITIONAL_HDR_ALLOC);
2609 lwsl_info(" MAX_USER_RX_BUFFER: %u\n", MAX_USER_RX_BUFFER);
2610 lwsl_info(" MAX_BROADCAST_PAYLOAD: %u\n", MAX_BROADCAST_PAYLOAD);
2611 lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
2612 lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE);
2613 lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED);
2614 lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT);
2615 lwsl_info(" CIPHERS_LIST_STRING: '%s'\n", CIPHERS_LIST_STRING);
2616 lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
2617 lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER);
Andy Green43db0452013-01-10 19:50:35 +08002618
Peter Hinz56885f32011-03-02 22:03:47 +00002619#ifdef _WIN32
2620 {
2621 WORD wVersionRequested;
2622 WSADATA wsaData;
2623 int err;
Andy Green6ee372f2012-04-09 15:09:01 +08002624 HMODULE wsdll;
Peter Hinz56885f32011-03-02 22:03:47 +00002625
2626 /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
2627 wVersionRequested = MAKEWORD(2, 2);
2628
2629 err = WSAStartup(wVersionRequested, &wsaData);
2630 if (err != 0) {
2631 /* Tell the user that we could not find a usable */
2632 /* Winsock DLL. */
Andy Green43db0452013-01-10 19:50:35 +08002633 lwsl_err("WSAStartup failed with error: %d\n", err);
Peter Hinz56885f32011-03-02 22:03:47 +00002634 return NULL;
2635 }
David Galeano7b11fec2011-10-04 19:55:18 +08002636
Andy Green6ee372f2012-04-09 15:09:01 +08002637 /* default to a poll() made out of select() */
2638 poll = emulated_poll;
David Galeano7b11fec2011-10-04 19:55:18 +08002639
Andy Green6ee372f2012-04-09 15:09:01 +08002640 /* if windows socket lib available, use his WSAPoll */
David Galeanocb193682013-01-09 15:29:00 +08002641 wsdll = GetModuleHandle(_T("Ws2_32.dll"));
Andy Green6ee372f2012-04-09 15:09:01 +08002642 if (wsdll)
2643 poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
Peter Hinz56885f32011-03-02 22:03:47 +00002644 }
2645#endif
2646
2647
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002648 context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context));
Peter Hinz56885f32011-03-02 22:03:47 +00002649 if (!context) {
Andy Green43db0452013-01-10 19:50:35 +08002650 lwsl_err("No memory for websocket context\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002651 return NULL;
2652 }
Peter Hinz56885f32011-03-02 22:03:47 +00002653 context->protocols = protocols;
2654 context->listen_port = port;
2655 context->http_proxy_port = 0;
2656 context->http_proxy_address[0] = '\0';
2657 context->options = options;
2658 context->fds_count = 0;
Andy Greend6e09112011-03-05 16:12:15 +00002659 context->extensions = extensions;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002660 context->last_timeout_check_s = 0;
Alon Levy0291eb32012-10-19 11:21:56 +02002661 context->user_space = user;
Andy Green9659f372011-01-27 22:01:43 +00002662
Peter Hinz56885f32011-03-02 22:03:47 +00002663#ifdef WIN32
2664 context->fd_random = 0;
2665#else
2666 context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
2667 if (context->fd_random < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002668 lwsl_err("Unable to open random device %s %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002669 SYSTEM_RANDOM_FILEPATH, context->fd_random);
Andy Green44eee682011-02-10 09:32:24 +00002670 return NULL;
2671 }
Peter Hinz56885f32011-03-02 22:03:47 +00002672#endif
Andy Green44eee682011-02-10 09:32:24 +00002673
Peter Hinz56885f32011-03-02 22:03:47 +00002674#ifdef LWS_OPENSSL_SUPPORT
2675 context->use_ssl = 0;
2676 context->ssl_ctx = NULL;
2677 context->ssl_client_ctx = NULL;
Andy Green2e24da02011-03-05 16:12:04 +00002678 openssl_websocket_private_data_index = 0;
Peter Hinz56885f32011-03-02 22:03:47 +00002679#endif
Andy Green2ac5a6f2011-01-28 10:00:18 +00002680
Andy Green788c4a82012-10-22 12:29:57 +01002681 if (options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME) {
Andy Greena69f0512012-05-03 12:32:38 +08002682
Andy Green788c4a82012-10-22 12:29:57 +01002683 strcpy(context->canonical_hostname, "unknown");
Andy Greena69f0512012-05-03 12:32:38 +08002684
Andy Green788c4a82012-10-22 12:29:57 +01002685 } else {
2686
2687 /* find canonical hostname */
2688
2689 hostname[(sizeof hostname) - 1] = '\0';
2690 memset(&sa, 0, sizeof(sa));
2691 sa.sa_family = AF_INET;
2692 sa.sa_data[(sizeof sa.sa_data) - 1] = '\0';
2693 gethostname(hostname, (sizeof hostname) - 1);
2694
2695 n = 0;
2696
David Galeanoed3c8402013-01-10 10:45:24 +08002697 if (strlen(hostname) < sizeof(sa.sa_data) - 1) {
Andy Green788c4a82012-10-22 12:29:57 +01002698 strcpy(sa.sa_data, hostname);
Andy Green43db0452013-01-10 19:50:35 +08002699 // lwsl_debug("my host name is %s\n", sa.sa_data);
Andy Green788c4a82012-10-22 12:29:57 +01002700 n = getnameinfo(&sa, sizeof(sa), hostname,
2701 (sizeof hostname) - 1, NULL, 0, 0);
2702 }
2703
2704 if (!n) {
2705 strncpy(context->canonical_hostname, hostname,
2706 sizeof context->canonical_hostname - 1);
2707 context->canonical_hostname[
2708 sizeof context->canonical_hostname - 1] = '\0';
2709 } else
2710 strncpy(context->canonical_hostname, hostname,
2711 sizeof context->canonical_hostname - 1);
2712
Andy Green43db0452013-01-10 19:50:35 +08002713 // lwsl_debug("context->canonical_hostname = %s\n",
Andy Green788c4a82012-10-22 12:29:57 +01002714 // context->canonical_hostname);
Andy Greena69f0512012-05-03 12:32:38 +08002715 }
2716
Andy Green9659f372011-01-27 22:01:43 +00002717 /* split the proxy ads:port if given */
2718
2719 p = getenv("http_proxy");
2720 if (p) {
Peter Hinz56885f32011-03-02 22:03:47 +00002721 strncpy(context->http_proxy_address, p,
Andy Green6ee372f2012-04-09 15:09:01 +08002722 sizeof context->http_proxy_address - 1);
Peter Hinz56885f32011-03-02 22:03:47 +00002723 context->http_proxy_address[
2724 sizeof context->http_proxy_address - 1] = '\0';
Andy Green9659f372011-01-27 22:01:43 +00002725
Peter Hinz56885f32011-03-02 22:03:47 +00002726 p = strchr(context->http_proxy_address, ':');
Andy Green9659f372011-01-27 22:01:43 +00002727 if (p == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002728 lwsl_err("http_proxy needs to be ads:port\n");
Andy Green9659f372011-01-27 22:01:43 +00002729 return NULL;
2730 }
2731 *p = '\0';
Peter Hinz56885f32011-03-02 22:03:47 +00002732 context->http_proxy_port = atoi(p + 1);
Andy Green9659f372011-01-27 22:01:43 +00002733
Andy Green43db0452013-01-10 19:50:35 +08002734 lwsl_debug("Using proxy %s:%u\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002735 context->http_proxy_address,
2736 context->http_proxy_port);
Andy Green9659f372011-01-27 22:01:43 +00002737 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002738
2739 if (port) {
2740
Andy Green3faa9c72010-11-08 17:03:03 +00002741#ifdef LWS_OPENSSL_SUPPORT
Peter Hinz56885f32011-03-02 22:03:47 +00002742 context->use_ssl = ssl_cert_filepath != NULL &&
Andy Green90c7cbc2011-01-27 06:26:52 +00002743 ssl_private_key_filepath != NULL;
Peter Hinz56885f32011-03-02 22:03:47 +00002744 if (context->use_ssl)
Andy Green43db0452013-01-10 19:50:35 +08002745 lwsl_info(" Compiled with SSL support, using it\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002746 else
Andy Green43db0452013-01-10 19:50:35 +08002747 lwsl_info(" Compiled with SSL support, not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +00002748
Andy Green90c7cbc2011-01-27 06:26:52 +00002749#else
2750 if (ssl_cert_filepath != NULL &&
2751 ssl_private_key_filepath != NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002752 lwsl_info(" Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +00002753 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002754 }
Andy Green43db0452013-01-10 19:50:35 +08002755 lwsl_info(" Compiled without SSL support, "
Andy Green90c7cbc2011-01-27 06:26:52 +00002756 "serving unencrypted\n");
2757#endif
2758 }
2759
2760 /* ignore SIGPIPE */
Peter Hinz56885f32011-03-02 22:03:47 +00002761#ifdef WIN32
2762#else
Andy Green90c7cbc2011-01-27 06:26:52 +00002763 signal(SIGPIPE, sigpipe_handler);
Peter Hinz56885f32011-03-02 22:03:47 +00002764#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002765
2766
2767#ifdef LWS_OPENSSL_SUPPORT
2768
2769 /* basic openssl init */
2770
2771 SSL_library_init();
2772
2773 OpenSSL_add_all_algorithms();
2774 SSL_load_error_strings();
2775
Andy Green2e24da02011-03-05 16:12:04 +00002776 openssl_websocket_private_data_index =
Andy Green6901cb32011-02-21 08:06:47 +00002777 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
2778
Andy Green90c7cbc2011-01-27 06:26:52 +00002779 /*
2780 * Firefox insists on SSLv23 not SSLv3
2781 * Konq disables SSLv2 by default now, SSLv23 works
2782 */
2783
2784 method = (SSL_METHOD *)SSLv23_server_method();
2785 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002786 lwsl_err("problem creating ssl method: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002787 ERR_error_string(ERR_get_error(), ssl_err_buf));
2788 return NULL;
2789 }
Peter Hinz56885f32011-03-02 22:03:47 +00002790 context->ssl_ctx = SSL_CTX_new(method); /* create context */
2791 if (!context->ssl_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002792 lwsl_err("problem creating ssl context: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002793 ERR_error_string(ERR_get_error(), ssl_err_buf));
2794 return NULL;
2795 }
2796
David Galeanocc148e42013-01-10 10:18:59 +08002797#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002798 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002799#endif
David Galeano77a677c2013-01-10 10:14:12 +08002800 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002801 SSL_CTX_set_cipher_list(context->ssl_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002802
Andy Green90c7cbc2011-01-27 06:26:52 +00002803 /* client context */
Andy Green6ee372f2012-04-09 15:09:01 +08002804
2805 if (port == CONTEXT_PORT_NO_LISTEN) {
Peter Hinz56885f32011-03-02 22:03:47 +00002806 method = (SSL_METHOD *)SSLv23_client_method();
2807 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002808 lwsl_err("problem creating ssl method: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002809 ERR_error_string(ERR_get_error(), ssl_err_buf));
2810 return NULL;
2811 }
2812 /* create context */
2813 context->ssl_client_ctx = SSL_CTX_new(method);
2814 if (!context->ssl_client_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002815 lwsl_err("problem creating ssl context: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002816 ERR_error_string(ERR_get_error(), ssl_err_buf));
2817 return NULL;
2818 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002819
David Galeanocc148e42013-01-10 10:18:59 +08002820#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002821 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002822#endif
David Galeano77a677c2013-01-10 10:14:12 +08002823 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002824 SSL_CTX_set_cipher_list(context->ssl_client_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002825
Peter Hinz56885f32011-03-02 22:03:47 +00002826 /* openssl init for cert verification (for client sockets) */
David Galeano2f82be82013-01-09 16:25:54 +08002827 if (!ssl_ca_filepath) {
2828 if (!SSL_CTX_load_verify_locations(
2829 context->ssl_client_ctx, NULL,
2830 LWS_OPENSSL_CLIENT_CERTS))
Andy Green43db0452013-01-10 19:50:35 +08002831 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002832 "Unable to load SSL Client certs from %s "
2833 "(set by --with-client-cert-dir= in configure) -- "
2834 " client ssl isn't going to work",
2835 LWS_OPENSSL_CLIENT_CERTS);
2836 } else
2837 if (!SSL_CTX_load_verify_locations(
2838 context->ssl_client_ctx, ssl_ca_filepath,
2839 NULL))
Andy Green43db0452013-01-10 19:50:35 +08002840 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002841 "Unable to load SSL Client certs "
2842 "file from %s -- client ssl isn't "
2843 "going to work", ssl_ca_filepath);
Peter Hinz56885f32011-03-02 22:03:47 +00002844
2845 /*
2846 * callback allowing user code to load extra verification certs
2847 * helping the client to verify server identity
2848 */
2849
2850 context->protocols[0].callback(context, NULL,
2851 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
2852 context->ssl_client_ctx, NULL, 0);
Andy Green90c7cbc2011-01-27 06:26:52 +00002853 }
Andy Green6ee372f2012-04-09 15:09:01 +08002854
Andy Greenc6bf2c22011-02-20 11:10:47 +00002855 /* as a server, are we requiring clients to identify themselves? */
2856
2857 if (options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
2858
2859 /* absolutely require the client cert */
Andy Green6ee372f2012-04-09 15:09:01 +08002860
Peter Hinz56885f32011-03-02 22:03:47 +00002861 SSL_CTX_set_verify(context->ssl_ctx,
Andy Green6901cb32011-02-21 08:06:47 +00002862 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2863 OpenSSL_verify_callback);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002864
2865 /*
2866 * give user code a chance to load certs into the server
2867 * allowing it to verify incoming client certs
2868 */
2869
Peter Hinz56885f32011-03-02 22:03:47 +00002870 context->protocols[0].callback(context, NULL,
Andy Greenc6bf2c22011-02-20 11:10:47 +00002871 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
Peter Hinz56885f32011-03-02 22:03:47 +00002872 context->ssl_ctx, NULL, 0);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002873 }
2874
Peter Hinz56885f32011-03-02 22:03:47 +00002875 if (context->use_ssl) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002876
2877 /* openssl init for server sockets */
2878
Andy Green3faa9c72010-11-08 17:03:03 +00002879 /* set the local certificate from CertFile */
David Galeano9b3d4b22013-01-10 10:11:21 +08002880 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
2881 ssl_cert_filepath);
Andy Green3faa9c72010-11-08 17:03:03 +00002882 if (n != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002883 lwsl_err("problem getting cert '%s': %s\n",
Andy Green3faa9c72010-11-08 17:03:03 +00002884 ssl_cert_filepath,
2885 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002886 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002887 }
2888 /* set the private key from KeyFile */
Peter Hinz56885f32011-03-02 22:03:47 +00002889 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
2890 ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002891 lwsl_err("ssl problem getting key '%s': %s\n",
Andy Green018d8eb2010-11-08 21:04:23 +00002892 ssl_private_key_filepath,
2893 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002894 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002895 }
2896 /* verify private key */
Peter Hinz56885f32011-03-02 22:03:47 +00002897 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
Andy Green43db0452013-01-10 19:50:35 +08002898 lwsl_err("Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +00002899 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002900 }
2901
2902 /* SSL is happy and has a cert it's content with */
2903 }
2904#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002905
Andy Greendf736162011-01-18 15:39:02 +00002906 /* selftest */
2907
2908 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +00002909 return NULL;
Andy Greendf736162011-01-18 15:39:02 +00002910
Andy Green0d338332011-02-12 11:57:43 +00002911 /* fd hashtable init */
2912
2913 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002914 context->fd_hashtable[n].length = 0;
Andy Green0d338332011-02-12 11:57:43 +00002915
Andy Greenb45993c2010-12-18 15:13:50 +00002916 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +00002917
Andy Green4739e5c2011-01-22 12:51:57 +00002918 if (port) {
Andy Green8f037e42010-12-19 22:13:26 +00002919
Andy Green4739e5c2011-01-22 12:51:57 +00002920 sockfd = socket(AF_INET, SOCK_STREAM, 0);
2921 if (sockfd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002922 lwsl_err("ERROR opening socket");
Andy Green4739e5c2011-01-22 12:51:57 +00002923 return NULL;
2924 }
Andy Green775c0dd2010-10-29 14:15:22 +01002925
Andy Green4739e5c2011-01-22 12:51:57 +00002926 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08002927 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
2928 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00002929
2930 /* Disable Nagle */
2931 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08002932 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
2933 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00002934
Andy Green4739e5c2011-01-22 12:51:57 +00002935 bzero((char *) &serv_addr, sizeof(serv_addr));
2936 serv_addr.sin_family = AF_INET;
Peter Hinz56885f32011-03-02 22:03:47 +00002937 if (interf == NULL)
Andy Green32375b72011-02-19 08:32:53 +00002938 serv_addr.sin_addr.s_addr = INADDR_ANY;
2939 else
Peter Hinz56885f32011-03-02 22:03:47 +00002940 interface_to_sa(interf, &serv_addr,
Andy Green32375b72011-02-19 08:32:53 +00002941 sizeof(serv_addr));
Andy Green4739e5c2011-01-22 12:51:57 +00002942 serv_addr.sin_port = htons(port);
2943
2944 n = bind(sockfd, (struct sockaddr *) &serv_addr,
2945 sizeof(serv_addr));
2946 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002947 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Green8f037e42010-12-19 22:13:26 +00002948 port, n, errno);
Andy Green41c58032013-01-12 13:21:08 +08002949 close(sockfd);
Andy Green4739e5c2011-01-22 12:51:57 +00002950 return NULL;
2951 }
Andy Green0d338332011-02-12 11:57:43 +00002952
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002953 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08002954 if (wsi == NULL) {
2955 lwsl_err("Out of mem\n");
2956 close(sockfd);
2957 return NULL;
2958 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002959 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00002960 wsi->sock = sockfd;
Andy Greend6e09112011-03-05 16:12:15 +00002961 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00002962 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
Peter Hinz56885f32011-03-02 22:03:47 +00002963 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002964
David Galeano36973092013-01-10 09:58:24 +08002965 listen(sockfd, SOMAXCONN);
Andy Green43db0452013-01-10 19:50:35 +08002966 lwsl_info(" Listening on port %d\n", port);
Andy Green0d338332011-02-12 11:57:43 +00002967
2968 /* list in the internal poll array */
Andy Green6ee372f2012-04-09 15:09:01 +08002969
Peter Hinz56885f32011-03-02 22:03:47 +00002970 context->fds[context->fds_count].fd = sockfd;
2971 context->fds[context->fds_count++].events = POLLIN;
Andy Green3221f922011-02-12 13:14:11 +00002972
2973 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002974 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002975 LWS_CALLBACK_ADD_POLL_FD,
2976 (void *)(long)sockfd, NULL, POLLIN);
2977
Andy Green8f037e42010-12-19 22:13:26 +00002978 }
Andy Greenb45993c2010-12-18 15:13:50 +00002979
Andy Green6ee372f2012-04-09 15:09:01 +08002980 /*
2981 * drop any root privs for this process
2982 * to listen on port < 1023 we would have needed root, but now we are
2983 * listening, we don't want the power for anything else
2984 */
Peter Hinz56885f32011-03-02 22:03:47 +00002985#ifdef WIN32
2986#else
Andy Green3faa9c72010-11-08 17:03:03 +00002987 if (gid != -1)
2988 if (setgid(gid))
Andy Green43db0452013-01-10 19:50:35 +08002989 lwsl_warn("setgid: %s\n", strerror(errno));
Andy Green3faa9c72010-11-08 17:03:03 +00002990 if (uid != -1)
2991 if (setuid(uid))
Andy Green43db0452013-01-10 19:50:35 +08002992 lwsl_warn("setuid: %s\n", strerror(errno));
Peter Hinz56885f32011-03-02 22:03:47 +00002993#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002994
2995 /* set up our internal broadcast trigger sockets per-protocol */
2996
Peter Hinz56885f32011-03-02 22:03:47 +00002997 for (context->count_protocols = 0;
2998 protocols[context->count_protocols].callback;
2999 context->count_protocols++) {
Andy Green2d1301e2011-05-24 10:14:41 +01003000
Andy Green43db0452013-01-10 19:50:35 +08003001 lwsl_parser(" Protocol: %s\n",
3002 protocols[context->count_protocols].name);
Andy Green2d1301e2011-05-24 10:14:41 +01003003
Peter Hinz56885f32011-03-02 22:03:47 +00003004 protocols[context->count_protocols].owning_server = context;
3005 protocols[context->count_protocols].protocol_index =
3006 context->count_protocols;
Andy Greenb45993c2010-12-18 15:13:50 +00003007
3008 fd = socket(AF_INET, SOCK_STREAM, 0);
3009 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003010 lwsl_err("ERROR opening socket");
Andy Greene92cd172011-01-19 13:11:55 +00003011 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003012 }
Andy Green8f037e42010-12-19 22:13:26 +00003013
Andy Greenb45993c2010-12-18 15:13:50 +00003014 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08003015 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt,
3016 sizeof(opt));
Andy Greenb45993c2010-12-18 15:13:50 +00003017
3018 bzero((char *) &serv_addr, sizeof(serv_addr));
3019 serv_addr.sin_family = AF_INET;
3020 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3021 serv_addr.sin_port = 0; /* pick the port for us */
3022
3023 n = bind(fd, (struct sockaddr *) &serv_addr, 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 Greenb45993c2010-12-18 15:13:50 +00003026 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +00003027 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003028 }
3029
3030 slen = sizeof cli_addr;
3031 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
3032 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003033 lwsl_err("getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +00003034 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003035 }
Peter Hinz56885f32011-03-02 22:03:47 +00003036 protocols[context->count_protocols].broadcast_socket_port =
Andy Greenb45993c2010-12-18 15:13:50 +00003037 ntohs(cli_addr.sin_port);
3038 listen(fd, 5);
3039
Andy Green43db0452013-01-10 19:50:35 +08003040 lwsl_debug(" Protocol %s broadcast socket %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00003041 protocols[context->count_protocols].name,
Andy Greenb45993c2010-12-18 15:13:50 +00003042 ntohs(cli_addr.sin_port));
3043
Andy Green0d338332011-02-12 11:57:43 +00003044 /* dummy wsi per broadcast proxy socket */
3045
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003046 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08003047 if (wsi == NULL) {
3048 lwsl_err("Out of mem\n");
3049 close(fd);
3050 return NULL;
3051 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003052 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00003053 wsi->sock = fd;
3054 wsi->mode = LWS_CONNMODE_BROADCAST_PROXY_LISTENER;
Andy Greend6e09112011-03-05 16:12:15 +00003055 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00003056 /* note which protocol we are proxying */
Peter Hinz56885f32011-03-02 22:03:47 +00003057 wsi->protocol_index_for_broadcast_proxy =
3058 context->count_protocols;
3059 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00003060
3061 /* list in internal poll array */
3062
Peter Hinz56885f32011-03-02 22:03:47 +00003063 context->fds[context->fds_count].fd = fd;
3064 context->fds[context->fds_count].events = POLLIN;
3065 context->fds[context->fds_count].revents = 0;
3066 context->fds_count++;
Andy Green3221f922011-02-12 13:14:11 +00003067
3068 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00003069 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00003070 LWS_CALLBACK_ADD_POLL_FD,
3071 (void *)(long)fd, NULL, POLLIN);
Andy Greenb45993c2010-12-18 15:13:50 +00003072 }
3073
Andy Greena41314f2011-05-23 10:00:03 +01003074 /*
3075 * give all extensions a chance to create any per-context
3076 * allocations they need
3077 */
3078
3079 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
3080 if (port)
3081 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
Andrew Chambersd5512172012-05-20 08:17:09 +08003082
3083 if (extensions) {
3084 while (extensions->callback) {
Andy Green43db0452013-01-10 19:50:35 +08003085 lwsl_ext(" Extension: %s\n", extensions->name);
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003086 extensions->callback(context, extensions, NULL,
3087 (enum libwebsocket_extension_callback_reasons)m,
3088 NULL, NULL, 0);
Andrew Chambersd5512172012-05-20 08:17:09 +08003089 extensions++;
3090 }
Andy Greena41314f2011-05-23 10:00:03 +01003091 }
3092
Peter Hinz56885f32011-03-02 22:03:47 +00003093 return context;
Andy Greene92cd172011-01-19 13:11:55 +00003094}
Andy Greenb45993c2010-12-18 15:13:50 +00003095
Andy Green4739e5c2011-01-22 12:51:57 +00003096
Andy Greened11a022011-01-20 10:23:50 +00003097#ifndef LWS_NO_FORK
3098
Andy Greene92cd172011-01-19 13:11:55 +00003099/**
3100 * libwebsockets_fork_service_loop() - Optional helper function forks off
3101 * a process for the websocket server loop.
Andy Green6964bb52011-01-23 16:50:33 +00003102 * You don't have to use this but if not, you
3103 * have to make sure you are calling
3104 * libwebsocket_service periodically to service
3105 * the websocket traffic
Peter Hinz56885f32011-03-02 22:03:47 +00003106 * @context: server context returned by creation function
Andy Greene92cd172011-01-19 13:11:55 +00003107 */
Andy Greenb45993c2010-12-18 15:13:50 +00003108
Andy Greene92cd172011-01-19 13:11:55 +00003109int
Peter Hinz56885f32011-03-02 22:03:47 +00003110libwebsockets_fork_service_loop(struct libwebsocket_context *context)
Andy Greene92cd172011-01-19 13:11:55 +00003111{
Andy Greene92cd172011-01-19 13:11:55 +00003112 int fd;
3113 struct sockaddr_in cli_addr;
3114 int n;
Andy Green3221f922011-02-12 13:14:11 +00003115 int p;
Andy Greenb45993c2010-12-18 15:13:50 +00003116
Andy Greened11a022011-01-20 10:23:50 +00003117 n = fork();
3118 if (n < 0)
3119 return n;
3120
3121 if (!n) {
3122
3123 /* main process context */
3124
Andy Green3221f922011-02-12 13:14:11 +00003125 /*
3126 * set up the proxy sockets to allow broadcast from
3127 * service process context
3128 */
3129
Peter Hinz56885f32011-03-02 22:03:47 +00003130 for (p = 0; p < context->count_protocols; p++) {
Andy Greened11a022011-01-20 10:23:50 +00003131 fd = socket(AF_INET, SOCK_STREAM, 0);
3132 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003133 lwsl_err("Unable to create socket\n");
Andy Greened11a022011-01-20 10:23:50 +00003134 return -1;
3135 }
3136 cli_addr.sin_family = AF_INET;
3137 cli_addr.sin_port = htons(
Peter Hinz56885f32011-03-02 22:03:47 +00003138 context->protocols[p].broadcast_socket_port);
Andy Greened11a022011-01-20 10:23:50 +00003139 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3140 n = connect(fd, (struct sockaddr *)&cli_addr,
3141 sizeof cli_addr);
3142 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003143 lwsl_err("Unable to connect to "
Andy Greened11a022011-01-20 10:23:50 +00003144 "broadcast socket %d, %s\n",
Andy Green3221f922011-02-12 13:14:11 +00003145 n, strerror(errno));
Andy Greened11a022011-01-20 10:23:50 +00003146 return -1;
3147 }
3148
Peter Hinz56885f32011-03-02 22:03:47 +00003149 context->protocols[p].broadcast_socket_user_fd = fd;
Andy Greened11a022011-01-20 10:23:50 +00003150 }
3151
Andy Greene92cd172011-01-19 13:11:55 +00003152 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00003153 }
3154
Artem Baguinski91531662011-12-14 22:14:03 +01003155#ifdef HAVE_SYS_PRCTL_H
Andy Greenb45993c2010-12-18 15:13:50 +00003156 /* we want a SIGHUP when our parent goes down */
3157 prctl(PR_SET_PDEATHSIG, SIGHUP);
Artem Baguinski91531662011-12-14 22:14:03 +01003158#endif
Andy Greenb45993c2010-12-18 15:13:50 +00003159
3160 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +00003161
Artem Baguinski91531662011-12-14 22:14:03 +01003162 while (1) {
Peter Hinz56885f32011-03-02 22:03:47 +00003163 if (libwebsocket_service(context, 1000))
Andy Green3928f612012-07-20 12:58:38 +08003164 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003165//#ifndef HAVE_SYS_PRCTL_H
Artem Baguinski91531662011-12-14 22:14:03 +01003166/*
3167 * on systems without prctl() (i.e. anything but linux) we can notice that our
3168 * parent is dead if getppid() returns 1. FIXME apparently this is not true for
3169 * solaris, could remember ppid right after fork and wait for it to change.
3170 */
3171
3172 if (getppid() == 1)
3173 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003174//#endif
Artem Baguinski91531662011-12-14 22:14:03 +01003175 }
3176
Andy Green8f037e42010-12-19 22:13:26 +00003177
Andy Green3928f612012-07-20 12:58:38 +08003178 return 1;
Andy Greenff95d7a2010-10-28 22:36:01 +01003179}
3180
Andy Greened11a022011-01-20 10:23:50 +00003181#endif
3182
Andy Greenb45993c2010-12-18 15:13:50 +00003183/**
3184 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +00003185 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +00003186 * @wsi: pointer to struct websocket you want to know the protocol of
3187 *
Andy Green8f037e42010-12-19 22:13:26 +00003188 *
3189 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +00003190 * the callback.
3191 */
Andy Greenab990e42010-10-31 12:42:52 +00003192
Andy Greenb45993c2010-12-18 15:13:50 +00003193const struct libwebsocket_protocols *
3194libwebsockets_get_protocol(struct libwebsocket *wsi)
3195{
3196 return wsi->protocol;
3197}
3198
3199/**
Andy Greene92cd172011-01-19 13:11:55 +00003200 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +00003201 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +00003202 * @protocol: pointer to the protocol you will broadcast to all members of
3203 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +00003204 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
3205 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
3206 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +00003207 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +00003208 *
3209 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +00003210 * the given protocol. It does not send the data directly; instead it calls
3211 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
3212 * wants to actually send the data for that connection, the callback itself
3213 * should call libwebsocket_write().
3214 *
3215 * libwebsockets_broadcast() can be called from another fork context without
3216 * having to take any care about data visibility between the processes, it'll
3217 * "just work".
3218 */
3219
3220
3221int
Andy Green8f037e42010-12-19 22:13:26 +00003222libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +00003223 unsigned char *buf, size_t len)
3224{
Peter Hinz56885f32011-03-02 22:03:47 +00003225 struct libwebsocket_context *context = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +00003226 int n;
Andy Green0d338332011-02-12 11:57:43 +00003227 int m;
Andy Green6ee372f2012-04-09 15:09:01 +08003228 struct libwebsocket *wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00003229
3230 if (!protocol->broadcast_socket_user_fd) {
3231 /*
Andy Greene92cd172011-01-19 13:11:55 +00003232 * We are either running unforked / flat, or we are being
3233 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +00003234 * eg, from a callback. In that case don't use sockets for
3235 * broadcast IPC (since we can't open a socket connection to
3236 * a socket listening on our own thread) but directly do the
3237 * send action.
3238 *
3239 * Locking is not needed because we are by definition being
3240 * called in the poll thread context and are serialized.
3241 */
3242
Andy Green0d338332011-02-12 11:57:43 +00003243 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003244
Peter Hinz56885f32011-03-02 22:03:47 +00003245 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003246
Peter Hinz56885f32011-03-02 22:03:47 +00003247 wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00003248
Andy Green0d338332011-02-12 11:57:43 +00003249 if (wsi->mode != LWS_CONNMODE_WS_SERVING)
3250 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00003251
Andy Green0d338332011-02-12 11:57:43 +00003252 /*
3253 * never broadcast to
3254 * non-established connections
3255 */
3256 if (wsi->state != WSI_STATE_ESTABLISHED)
3257 continue;
3258
3259 /* only broadcast to guys using
3260 * requested protocol
3261 */
3262 if (wsi->protocol != protocol)
3263 continue;
3264
Peter Hinz56885f32011-03-02 22:03:47 +00003265 wsi->protocol->callback(context, wsi,
Andy Green8f037e42010-12-19 22:13:26 +00003266 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00003267 wsi->user_space,
Andy Greenb45993c2010-12-18 15:13:50 +00003268 buf, len);
Andy Green0d338332011-02-12 11:57:43 +00003269 }
Andy Greenb45993c2010-12-18 15:13:50 +00003270 }
3271
3272 return 0;
3273 }
3274
Andy Green0ca6a172010-12-19 20:50:01 +00003275 /*
3276 * We're being called from a different process context than the server
3277 * loop. Instead of broadcasting directly, we send our
3278 * payload on a socket to do the IPC; the server process will serialize
3279 * the broadcast action in its main poll() loop.
3280 *
3281 * There's one broadcast socket listening for each protocol supported
3282 * set up when the websocket server initializes
3283 */
3284
Andy Green6964bb52011-01-23 16:50:33 +00003285 n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
Andy Greenb45993c2010-12-18 15:13:50 +00003286
3287 return n;
3288}
Andy Green82c3d542011-03-07 21:16:31 +00003289
3290int
3291libwebsocket_is_final_fragment(struct libwebsocket *wsi)
3292{
3293 return wsi->final;
3294}
Alex Bligh49146db2011-11-07 17:19:25 +08003295
David Galeanoe2cf9922013-01-09 18:06:55 +08003296unsigned char
3297libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
3298{
3299 return wsi->rsv;
3300}
3301
Alex Bligh49146db2011-11-07 17:19:25 +08003302void *
3303libwebsocket_ensure_user_space(struct libwebsocket *wsi)
3304{
3305 /* allocate the per-connection user memory (if any) */
3306
3307 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
3308 wsi->user_space = malloc(
3309 wsi->protocol->per_session_data_size);
3310 if (wsi->user_space == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08003311 lwsl_err("Out of memory for conn user space\n");
Alex Bligh49146db2011-11-07 17:19:25 +08003312 return NULL;
3313 }
Andy Green6ee372f2012-04-09 15:09:01 +08003314 memset(wsi->user_space, 0,
3315 wsi->protocol->per_session_data_size);
Alex Bligh49146db2011-11-07 17:19:25 +08003316 }
3317 return wsi->user_space;
3318}
Andy Green43db0452013-01-10 19:50:35 +08003319
Andy Greende8f27a2013-01-12 09:17:42 +08003320
3321static void lwsl_emit_stderr(const char *line)
3322{
3323 fprintf(stderr, "%s", line);
3324}
3325
Andy Green43db0452013-01-10 19:50:35 +08003326void _lws_log(int filter, const char *format, ...)
3327{
Andy Greende8f27a2013-01-12 09:17:42 +08003328 char buf[256];
Andy Green43db0452013-01-10 19:50:35 +08003329 va_list ap;
3330 int n;
Andy Greende8f27a2013-01-12 09:17:42 +08003331 int pos = 0;
Andy Green8a265092013-01-12 09:25:07 +08003332 struct timeval tv;
Andy Green43db0452013-01-10 19:50:35 +08003333
3334 if (!(log_level & filter))
3335 return;
3336
Andy Green8a265092013-01-12 09:25:07 +08003337 gettimeofday(&tv, NULL);
3338
Andy Green43db0452013-01-10 19:50:35 +08003339 for (n = 0; n < LLL_COUNT; n++)
3340 if (filter == (1 << n)) {
Andy Green8a265092013-01-12 09:25:07 +08003341 pos = sprintf(buf, "[%ld:%04ld] %s: ", tv.tv_sec,
3342 tv.tv_usec / 100, log_level_names[n]);
Andy Green43db0452013-01-10 19:50:35 +08003343 break;
3344 }
3345
3346 va_start(ap, format);
Andy Greende8f27a2013-01-12 09:17:42 +08003347 vsnprintf(buf + pos, (sizeof buf) - pos, format, ap);
3348 buf[(sizeof buf) - 1] = '\0';
3349 va_end(ap);
3350
3351 lwsl_emit(buf);
Andy Green43db0452013-01-10 19:50:35 +08003352}
3353
3354/**
3355 * lws_set_log_level() - Set the logging bitfield
3356 * @level: OR together the LLL_ debug contexts you want output from
Andy Greende8f27a2013-01-12 09:17:42 +08003357 * @log_emit_function: NULL to leave it as it is, or a user-supplied
3358 * function to perform log string emission instead of
3359 * the default stderr one.
Andy Green43db0452013-01-10 19:50:35 +08003360 *
Andy Greende8f27a2013-01-12 09:17:42 +08003361 * log level defaults to "err" and "warn" contexts enabled only and
3362 * emission on stderr.
Andy Green43db0452013-01-10 19:50:35 +08003363 */
3364
Andy Greende8f27a2013-01-12 09:17:42 +08003365void lws_set_log_level(int level, void (*log_emit_function)(const char *line))
Andy Green43db0452013-01-10 19:50:35 +08003366{
3367 log_level = level;
Andy Greende8f27a2013-01-12 09:17:42 +08003368 if (log_emit_function)
3369 lwsl_emit = log_emit_function;
Andy Green43db0452013-01-10 19:50:35 +08003370}