blob: b36a9b288f7da45460d69d45f3a627d1eca9117c [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
28#include <ifaddrs.h>
Andy Green7627af52011-03-09 15:13:52 +000029#include <sys/un.h>
Andy Greena69f0512012-05-03 12:32:38 +080030#include <sys/socket.h>
31#include <netdb.h>
Peter Hinz56885f32011-03-02 22:03:47 +000032#endif
Andy Green2e24da02011-03-05 16:12:04 +000033
34#ifdef LWS_OPENSSL_SUPPORT
35int openssl_websocket_private_data_index;
36#endif
37
Andy Greenaa6fc442012-04-12 13:26:49 +080038#ifdef __MINGW32__
39#include "../win32port/win32helpers/websock-w32.c"
40#else
41#ifdef __MINGW64__
42#include "../win32port/win32helpers/websock-w32.c"
43#endif
44#endif
45
Andy Green43db0452013-01-10 19:50:35 +080046static int log_level = LLL_ERR | LLL_WARN;
Andy Greende8f27a2013-01-12 09:17:42 +080047static void lwsl_emit_stderr(const char *line);
48static void (*lwsl_emit)(const char *line) = lwsl_emit_stderr;
Andy Green43db0452013-01-10 19:50:35 +080049static const char *log_level_names[] = {
50 "ERR",
51 "WARN",
52 "INFO",
53 "DEBUG",
54 "PARSER",
55 "HEADER",
56 "EXTENSION",
57 "CLIENT",
58};
59
Andy Greenbe93fef2011-02-14 20:25:43 +000060/*
61 * In-place str to lower case
62 */
63
64static void
65strtolower(char *s)
66{
67 while (*s) {
68 *s = tolower(*s);
69 s++;
70 }
71}
72
Andy Green0d338332011-02-12 11:57:43 +000073/* file descriptor hash management */
74
75struct libwebsocket *
Peter Hinz56885f32011-03-02 22:03:47 +000076wsi_from_fd(struct libwebsocket_context *context, int fd)
Andy Green0d338332011-02-12 11:57:43 +000077{
78 int h = LWS_FD_HASH(fd);
79 int n = 0;
80
Peter Hinz56885f32011-03-02 22:03:47 +000081 for (n = 0; n < context->fd_hashtable[h].length; n++)
82 if (context->fd_hashtable[h].wsi[n]->sock == fd)
83 return context->fd_hashtable[h].wsi[n];
Andy Green0d338332011-02-12 11:57:43 +000084
85 return NULL;
86}
87
88int
Peter Hinz56885f32011-03-02 22:03:47 +000089insert_wsi(struct libwebsocket_context *context, struct libwebsocket *wsi)
Andy Green0d338332011-02-12 11:57:43 +000090{
91 int h = LWS_FD_HASH(wsi->sock);
92
Peter Hinz56885f32011-03-02 22:03:47 +000093 if (context->fd_hashtable[h].length == MAX_CLIENTS - 1) {
Andy Green43db0452013-01-10 19:50:35 +080094 lwsl_err("hash table overflow\n");
Andy Green0d338332011-02-12 11:57:43 +000095 return 1;
96 }
97
Peter Hinz56885f32011-03-02 22:03:47 +000098 context->fd_hashtable[h].wsi[context->fd_hashtable[h].length++] = wsi;
Andy Green0d338332011-02-12 11:57:43 +000099
100 return 0;
101}
102
103int
Peter Hinz56885f32011-03-02 22:03:47 +0000104delete_from_fd(struct libwebsocket_context *context, int fd)
Andy Green0d338332011-02-12 11:57:43 +0000105{
106 int h = LWS_FD_HASH(fd);
107 int n = 0;
108
Peter Hinz56885f32011-03-02 22:03:47 +0000109 for (n = 0; n < context->fd_hashtable[h].length; n++)
110 if (context->fd_hashtable[h].wsi[n]->sock == fd) {
111 while (n < context->fd_hashtable[h].length) {
112 context->fd_hashtable[h].wsi[n] =
113 context->fd_hashtable[h].wsi[n + 1];
Andy Green0d338332011-02-12 11:57:43 +0000114 n++;
115 }
Peter Hinz56885f32011-03-02 22:03:47 +0000116 context->fd_hashtable[h].length--;
Andy Green0d338332011-02-12 11:57:43 +0000117
118 return 0;
119 }
120
Andy Green43db0452013-01-10 19:50:35 +0800121 lwsl_err("Failed to find fd %d requested for "
Andy Green0d338332011-02-12 11:57:43 +0000122 "delete in hashtable\n", fd);
123 return 1;
124}
125
Andy Green1f9bf522011-02-14 21:14:37 +0000126#ifdef LWS_OPENSSL_SUPPORT
127static void
128libwebsockets_decode_ssl_error(void)
129{
130 char buf[256];
131 u_long err;
132
133 while ((err = ERR_get_error()) != 0) {
134 ERR_error_string_n(err, buf, sizeof(buf));
Andy Green43db0452013-01-10 19:50:35 +0800135 lwsl_err("*** %s\n", buf);
Andy Green1f9bf522011-02-14 21:14:37 +0000136 }
137}
138#endif
Andy Green0d338332011-02-12 11:57:43 +0000139
Andy Green32375b72011-02-19 08:32:53 +0000140
141static int
Andy Green6ee372f2012-04-09 15:09:01 +0800142interface_to_sa(const char *ifname, struct sockaddr_in *addr, size_t addrlen)
Andy Green32375b72011-02-19 08:32:53 +0000143{
144 int rc = -1;
Peter Hinz56885f32011-03-02 22:03:47 +0000145#ifdef WIN32
Andy Green6ee372f2012-04-09 15:09:01 +0800146 /* TODO */
Peter Hinz56885f32011-03-02 22:03:47 +0000147#else
Andy Green32375b72011-02-19 08:32:53 +0000148 struct ifaddrs *ifr;
149 struct ifaddrs *ifc;
150 struct sockaddr_in *sin;
151
152 getifaddrs(&ifr);
153 for (ifc = ifr; ifc != NULL; ifc = ifc->ifa_next) {
154 if (strcmp(ifc->ifa_name, ifname))
155 continue;
156 if (ifc->ifa_addr == NULL)
157 continue;
158 sin = (struct sockaddr_in *)ifc->ifa_addr;
159 if (sin->sin_family != AF_INET)
160 continue;
161 memcpy(addr, sin, addrlen);
Andy Green6ee372f2012-04-09 15:09:01 +0800162 rc = 0;
Andy Green32375b72011-02-19 08:32:53 +0000163 }
164
165 freeifaddrs(ifr);
Peter Hinz56885f32011-03-02 22:03:47 +0000166#endif
Andy Green32375b72011-02-19 08:32:53 +0000167 return rc;
168}
169
Andy Green8f037e42010-12-19 22:13:26 +0000170void
Peter Hinz56885f32011-03-02 22:03:47 +0000171libwebsocket_close_and_free_session(struct libwebsocket_context *context,
Andy Green687b0182011-02-26 11:04:01 +0000172 struct libwebsocket *wsi, enum lws_close_status reason)
Andy Green251f6fa2010-11-03 11:13:06 +0000173{
Andy Greenb45993c2010-12-18 15:13:50 +0000174 int n;
Andy Green62c54d22011-02-14 09:14:25 +0000175 int old_state;
Andy Green5e1fa172011-02-10 09:07:05 +0000176 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
177 LWS_SEND_BUFFER_POST_PADDING];
Andy Greenc44159f2011-03-07 07:08:18 +0000178 int ret;
179 int m;
180 struct lws_tokens eff_buf;
Andy Greena41314f2011-05-23 10:00:03 +0100181 struct libwebsocket_extension *ext;
Andy Greenb45993c2010-12-18 15:13:50 +0000182
Andy Green4b6fbe12011-02-14 08:03:48 +0000183 if (!wsi)
Andy Greenb45993c2010-12-18 15:13:50 +0000184 return;
185
Andy Green62c54d22011-02-14 09:14:25 +0000186 old_state = wsi->state;
Andy Green251f6fa2010-11-03 11:13:06 +0000187
Andy Green62c54d22011-02-14 09:14:25 +0000188 if (old_state == WSI_STATE_DEAD_SOCKET)
Andy Green5e1fa172011-02-10 09:07:05 +0000189 return;
190
Andy Greenda527df2011-03-07 07:08:12 +0000191 wsi->close_reason = reason;
192
193 /*
Andy Green68b45042011-05-25 21:41:57 +0100194 * are his extensions okay with him closing? Eg he might be a mux
195 * parent and just his ch1 aspect is closing?
196 */
197
198
199 for (n = 0; n < wsi->count_active_extensions; n++) {
200 if (!wsi->active_extensions[n]->callback)
201 continue;
202
203 m = wsi->active_extensions[n]->callback(context,
204 wsi->active_extensions[n], wsi,
205 LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
206 wsi->active_extensions_user[n], NULL, 0);
207
208 /*
209 * if somebody vetoed actually closing him at this time....
210 * up to the extension to track the attempted close, let's
211 * just bail
212 */
213
214 if (m) {
Andy Green43db0452013-01-10 19:50:35 +0800215 lwsl_ext("extension vetoed close\n");
Andy Green68b45042011-05-25 21:41:57 +0100216 return;
217 }
218 }
219
220
221
222 /*
Andy Greenc44159f2011-03-07 07:08:18 +0000223 * flush any tx pending from extensions, since we may send close packet
224 * if there are problems with send, just nuke the connection
225 */
226
227 ret = 1;
228 while (ret == 1) {
229
230 /* default to nobody has more to spill */
231
232 ret = 0;
233 eff_buf.token = NULL;
234 eff_buf.token_len = 0;
235
236 /* show every extension the new incoming data */
237
238 for (n = 0; n < wsi->count_active_extensions; n++) {
239 m = wsi->active_extensions[n]->callback(
Andy Green46c2ea02011-03-22 09:04:01 +0000240 wsi->protocol->owning_server,
241 wsi->active_extensions[n], wsi,
Andy Greenc44159f2011-03-07 07:08:18 +0000242 LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
243 wsi->active_extensions_user[n], &eff_buf, 0);
244 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +0800245 lwsl_ext("Extension reports fatal error\n");
Andy Greenc44159f2011-03-07 07:08:18 +0000246 goto just_kill_connection;
247 }
248 if (m)
249 /*
250 * at least one extension told us he has more
251 * to spill, so we will go around again after
252 */
253 ret = 1;
254 }
255
256 /* assuming they left us something to send, send it */
257
258 if (eff_buf.token_len)
259 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
260 eff_buf.token_len))
261 goto just_kill_connection;
262 }
263
264 /*
Andy Greenda527df2011-03-07 07:08:12 +0000265 * signal we are closing, libsocket_write will
266 * add any necessary version-specific stuff. If the write fails,
267 * no worries we are closing anyway. If we didn't initiate this
268 * close, then our state has been changed to
269 * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
270 *
271 * Likewise if it's a second call to close this connection after we
272 * sent the close indication to the peer already, we are in state
273 * WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
274 */
275
276 if (old_state == WSI_STATE_ESTABLISHED &&
277 reason != LWS_CLOSE_STATUS_NOSTATUS) {
Andy Green66a16f32011-05-24 22:07:45 +0100278
Andy Green43db0452013-01-10 19:50:35 +0800279 lwsl_debug("sending close indication...\n");
Andy Green66a16f32011-05-24 22:07:45 +0100280
Andy Greenda527df2011-03-07 07:08:12 +0000281 n = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING],
282 0, LWS_WRITE_CLOSE);
283 if (!n) {
284 /*
285 * we have sent a nice protocol level indication we
286 * now wish to close, we should not send anything more
287 */
288
289 wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
290
291 /* and we should wait for a reply for a bit */
292
293 libwebsocket_set_timeout(wsi,
David Galeanoc9f1ff82013-01-09 18:01:23 +0800294 PENDING_TIMEOUT_CLOSE_ACK, AWAITING_TIMEOUT);
Andy Greenda527df2011-03-07 07:08:12 +0000295
Andy Green43db0452013-01-10 19:50:35 +0800296 lwsl_debug("sent close indication, awaiting ack\n");
Andy Greenda527df2011-03-07 07:08:12 +0000297
298 return;
299 }
300
301 /* else, the send failed and we should just hang up */
302 }
303
Andy Greenc44159f2011-03-07 07:08:18 +0000304just_kill_connection:
Andy Green66a16f32011-05-24 22:07:45 +0100305
Andy Green43db0452013-01-10 19:50:35 +0800306 lwsl_debug("libwebsocket_close_and_free_session: just_kill_connection\n");
Andy Green66a16f32011-05-24 22:07:45 +0100307
Andy Greenda527df2011-03-07 07:08:12 +0000308 /*
309 * we won't be servicing or receiving anything further from this guy
310 * remove this fd from wsi mapping hashtable
311 */
Andy Green4b6fbe12011-02-14 08:03:48 +0000312
Andy Greena41314f2011-05-23 10:00:03 +0100313 if (wsi->sock)
314 delete_from_fd(context, wsi->sock);
Andy Green4b6fbe12011-02-14 08:03:48 +0000315
316 /* delete it from the internal poll list if still present */
317
Peter Hinz56885f32011-03-02 22:03:47 +0000318 for (n = 0; n < context->fds_count; n++) {
319 if (context->fds[n].fd != wsi->sock)
Andy Green4b6fbe12011-02-14 08:03:48 +0000320 continue;
Peter Hinz56885f32011-03-02 22:03:47 +0000321 while (n < context->fds_count - 1) {
322 context->fds[n] = context->fds[n + 1];
Andy Green4b6fbe12011-02-14 08:03:48 +0000323 n++;
324 }
Peter Hinz56885f32011-03-02 22:03:47 +0000325 context->fds_count--;
Andy Green4b6fbe12011-02-14 08:03:48 +0000326 /* we only have to deal with one */
Peter Hinz56885f32011-03-02 22:03:47 +0000327 n = context->fds_count;
Andy Green4b6fbe12011-02-14 08:03:48 +0000328 }
329
330 /* remove also from external POLL support via protocol 0 */
Andy Greena41314f2011-05-23 10:00:03 +0100331 if (wsi->sock)
332 context->protocols[0].callback(context, wsi,
Andy Green4b6fbe12011-02-14 08:03:48 +0000333 LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
334
Andy Green251f6fa2010-11-03 11:13:06 +0000335 wsi->state = WSI_STATE_DEAD_SOCKET;
336
Andy Green4b6fbe12011-02-14 08:03:48 +0000337 /* tell the user it's all over for this guy */
338
Andy Greend4302732011-02-28 07:45:29 +0000339 if (wsi->protocol && wsi->protocol->callback &&
Andy Green6ee372f2012-04-09 15:09:01 +0800340 ((old_state == WSI_STATE_ESTABLISHED) ||
341 (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
342 (old_state == WSI_STATE_AWAITING_CLOSE_ACK))) {
Andy Green43db0452013-01-10 19:50:35 +0800343 lwsl_debug("calling back CLOSED\n");
Peter Hinz56885f32011-03-02 22:03:47 +0000344 wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
Andy Greene77ddd82010-11-13 10:03:47 +0000345 wsi->user_space, NULL, 0);
Andy Greencc012472011-11-07 19:53:23 +0800346 } else
Andy Green43db0452013-01-10 19:50:35 +0800347 lwsl_debug("not calling back closed, old_state=%d\n", old_state);
Andy Green251f6fa2010-11-03 11:13:06 +0000348
Andy Greenef660a92011-03-06 10:29:38 +0000349 /* deallocate any active extension contexts */
350
351 for (n = 0; n < wsi->count_active_extensions; n++) {
352 if (!wsi->active_extensions[n]->callback)
353 continue;
354
Andy Green46c2ea02011-03-22 09:04:01 +0000355 wsi->active_extensions[n]->callback(context,
356 wsi->active_extensions[n], wsi,
357 LWS_EXT_CALLBACK_DESTROY,
358 wsi->active_extensions_user[n], NULL, 0);
Andy Greenef660a92011-03-06 10:29:38 +0000359
360 free(wsi->active_extensions_user[n]);
361 }
362
Andy Greena41314f2011-05-23 10:00:03 +0100363 /*
364 * inform all extensions in case they tracked this guy out of band
365 * even though not active on him specifically
366 */
367
368 ext = context->extensions;
369 while (ext && ext->callback) {
370 ext->callback(context, ext, wsi,
371 LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
372 NULL, NULL, 0);
373 ext++;
374 }
375
Andy Greenef660a92011-03-06 10:29:38 +0000376 /* free up his parsing allocations */
Andy Green4b6fbe12011-02-14 08:03:48 +0000377
Andy Green251f6fa2010-11-03 11:13:06 +0000378 for (n = 0; n < WSI_TOKEN_COUNT; n++)
379 if (wsi->utf8_token[n].token)
380 free(wsi->utf8_token[n].token);
381
Andy Greena41314f2011-05-23 10:00:03 +0100382 if (wsi->c_address)
383 free(wsi->c_address);
384
Andy Green43db0452013-01-10 19:50:35 +0800385/* lwsl_info("closing fd=%d\n", wsi->sock); */
Andy Green251f6fa2010-11-03 11:13:06 +0000386
Andy Green3faa9c72010-11-08 17:03:03 +0000387#ifdef LWS_OPENSSL_SUPPORT
Andy Green90c7cbc2011-01-27 06:26:52 +0000388 if (wsi->ssl) {
Andy Green3faa9c72010-11-08 17:03:03 +0000389 n = SSL_get_fd(wsi->ssl);
390 SSL_shutdown(wsi->ssl);
Peter Hinz56885f32011-03-02 22:03:47 +0000391#ifdef WIN32
392 closesocket(n);
393#else
Andy Green3faa9c72010-11-08 17:03:03 +0000394 close(n);
Peter Hinz56885f32011-03-02 22:03:47 +0000395#endif
Andy Green3faa9c72010-11-08 17:03:03 +0000396 SSL_free(wsi->ssl);
397 } else {
398#endif
399 shutdown(wsi->sock, SHUT_RDWR);
Peter Hinz56885f32011-03-02 22:03:47 +0000400#ifdef WIN32
Andy Green66a16f32011-05-24 22:07:45 +0100401 if (wsi->sock)
402 closesocket(wsi->sock);
Peter Hinz56885f32011-03-02 22:03:47 +0000403#else
Andy Green66a16f32011-05-24 22:07:45 +0100404 if (wsi->sock)
405 close(wsi->sock);
Peter Hinz56885f32011-03-02 22:03:47 +0000406#endif
Andy Green3faa9c72010-11-08 17:03:03 +0000407#ifdef LWS_OPENSSL_SUPPORT
408 }
409#endif
David Brooks2c60d952012-04-20 12:19:01 +0800410 if (wsi->protocol && wsi->protocol->per_session_data_size && wsi->user_space) /* user code may own */
Andy Green4f3943a2010-11-12 10:44:16 +0000411 free(wsi->user_space);
412
Andy Green251f6fa2010-11-03 11:13:06 +0000413 free(wsi);
414}
415
Andy Green07034092011-02-13 08:37:12 +0000416/**
Andy Greenf7ee5492011-02-13 09:04:21 +0000417 * libwebsockets_hangup_on_client() - Server calls to terminate client
Andy Green6ee372f2012-04-09 15:09:01 +0800418 * connection
Peter Hinz56885f32011-03-02 22:03:47 +0000419 * @context: libwebsockets context
Andy Greenf7ee5492011-02-13 09:04:21 +0000420 * @fd: Connection socket descriptor
421 */
422
423void
Peter Hinz56885f32011-03-02 22:03:47 +0000424libwebsockets_hangup_on_client(struct libwebsocket_context *context, int fd)
Andy Greenf7ee5492011-02-13 09:04:21 +0000425{
Peter Hinz56885f32011-03-02 22:03:47 +0000426 struct libwebsocket *wsi = wsi_from_fd(context, fd);
Andy Greenf7ee5492011-02-13 09:04:21 +0000427
428 if (wsi == NULL)
429 return;
430
Peter Hinz56885f32011-03-02 22:03:47 +0000431 libwebsocket_close_and_free_session(context, wsi,
Andy Green6da560c2011-02-26 11:06:27 +0000432 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenf7ee5492011-02-13 09:04:21 +0000433}
434
435
436/**
Andy Green07034092011-02-13 08:37:12 +0000437 * libwebsockets_get_peer_addresses() - Get client address information
438 * @fd: Connection socket descriptor
439 * @name: Buffer to take client address name
440 * @name_len: Length of client address name buffer
441 * @rip: Buffer to take client address IP qotted quad
442 * @rip_len: Length of client address IP buffer
443 *
444 * This function fills in @name and @rip with the name and IP of
Andy Green6ee372f2012-04-09 15:09:01 +0800445 * the client connected with socket descriptor @fd. Names may be
446 * truncated if there is not enough room. If either cannot be
447 * determined, they will be returned as valid zero-length strings.
Andy Green07034092011-02-13 08:37:12 +0000448 */
449
450void
451libwebsockets_get_peer_addresses(int fd, char *name, int name_len,
452 char *rip, int rip_len)
453{
454 unsigned int len;
455 struct sockaddr_in sin;
456 struct hostent *host;
457 struct hostent *host1;
458 char ip[128];
Andy Greenf92def72011-03-09 15:02:20 +0000459 unsigned char *p;
Andy Green07034092011-02-13 08:37:12 +0000460 int n;
David Galeanocb193682013-01-09 15:29:00 +0800461#ifdef AF_LOCAL
462 struct sockaddr_un *un;
463#endif
Andy Green07034092011-02-13 08:37:12 +0000464
465 rip[0] = '\0';
466 name[0] = '\0';
467
468 len = sizeof sin;
469 if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
470 perror("getpeername");
471 return;
472 }
Andy Green6ee372f2012-04-09 15:09:01 +0800473
Andy Green07034092011-02-13 08:37:12 +0000474 host = gethostbyaddr((char *) &sin.sin_addr, sizeof sin.sin_addr,
475 AF_INET);
476 if (host == NULL) {
477 perror("gethostbyaddr");
478 return;
479 }
480
481 strncpy(name, host->h_name, name_len);
482 name[name_len - 1] = '\0';
483
484 host1 = gethostbyname(host->h_name);
485 if (host1 == NULL)
486 return;
Andy Greenf92def72011-03-09 15:02:20 +0000487 p = (unsigned char *)host1;
Andy Green07034092011-02-13 08:37:12 +0000488 n = 0;
489 while (p != NULL) {
Andy Greenf92def72011-03-09 15:02:20 +0000490 p = (unsigned char *)host1->h_addr_list[n++];
Andy Green07034092011-02-13 08:37:12 +0000491 if (p == NULL)
492 continue;
Peter Hinzbb45a902011-03-10 18:14:01 +0000493 if ((host1->h_addrtype != AF_INET)
494#ifdef AF_LOCAL
495 && (host1->h_addrtype != AF_LOCAL)
496#endif
497 )
Andy Green07034092011-02-13 08:37:12 +0000498 continue;
499
Andy Green7627af52011-03-09 15:13:52 +0000500 if (host1->h_addrtype == AF_INET)
501 sprintf(ip, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
Peter Hinzbb45a902011-03-10 18:14:01 +0000502#ifdef AF_LOCAL
Andy Green7627af52011-03-09 15:13:52 +0000503 else {
504 un = (struct sockaddr_un *)p;
Andy Green6ee372f2012-04-09 15:09:01 +0800505 strncpy(ip, un->sun_path, sizeof(ip) - 1);
Andy Green7627af52011-03-09 15:13:52 +0000506 ip[sizeof(ip) - 1] = '\0';
507 }
Peter Hinzbb45a902011-03-10 18:14:01 +0000508#endif
Andy Green07034092011-02-13 08:37:12 +0000509 p = NULL;
510 strncpy(rip, ip, rip_len);
511 rip[rip_len - 1] = '\0';
512 }
513}
Andy Green9f990342011-02-12 11:57:45 +0000514
Peter Hinz56885f32011-03-02 22:03:47 +0000515int libwebsockets_get_random(struct libwebsocket_context *context,
516 void *buf, int len)
517{
518 int n;
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800519 char *p = (char *)buf;
Peter Hinz56885f32011-03-02 22:03:47 +0000520
521#ifdef WIN32
522 for (n = 0; n < len; n++)
523 p[n] = (unsigned char)rand();
524#else
525 n = read(context->fd_random, p, len);
526#endif
527
528 return n;
529}
530
Andy Green2836c642011-03-07 20:47:41 +0000531unsigned char *
532libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md)
533{
534 return SHA1(d, n, md);
535}
536
Andy Greeneeaacb32011-03-01 20:44:24 +0000537void libwebsockets_00_spaceout(char *key, int spaces, int seed)
538{
539 char *p;
Andy Green6ee372f2012-04-09 15:09:01 +0800540
Andy Greeneeaacb32011-03-01 20:44:24 +0000541 key++;
542 while (spaces--) {
543 if (*key && (seed & 1))
544 key++;
545 seed >>= 1;
Andy Green6ee372f2012-04-09 15:09:01 +0800546
Andy Greeneeaacb32011-03-01 20:44:24 +0000547 p = key + strlen(key);
548 while (p >= key) {
549 p[1] = p[0];
550 p--;
551 }
552 *key++ = ' ';
553 }
554}
555
556void libwebsockets_00_spam(char *key, int count, int seed)
557{
558 char *p;
559
560 key++;
561 while (count--) {
Andy Green6ee372f2012-04-09 15:09:01 +0800562
Andy Greeneeaacb32011-03-01 20:44:24 +0000563 if (*key && (seed & 1))
564 key++;
565 seed >>= 1;
566
567 p = key + strlen(key);
568 while (p >= key) {
569 p[1] = p[0];
570 p--;
571 }
572 *key++ = 0x21 + ((seed & 0xffff) % 15);
573 /* 4 would use it up too fast.. not like it matters */
574 seed >>= 1;
575 }
576}
577
Andy Green95a7b5d2011-03-06 10:29:39 +0000578int lws_send_pipe_choked(struct libwebsocket *wsi)
579{
580 struct pollfd fds;
581
582 fds.fd = wsi->sock;
583 fds.events = POLLOUT;
584 fds.revents = 0;
585
586 if (poll(&fds, 1, 0) != 1)
587 return 1;
588
589 if ((fds.revents & POLLOUT) == 0)
590 return 1;
591
592 /* okay to send another packet without blocking */
593
594 return 0;
595}
596
Andy Greena41314f2011-05-23 10:00:03 +0100597int
Andy Green3b84c002011-03-06 13:14:42 +0000598lws_handle_POLLOUT_event(struct libwebsocket_context *context,
599 struct libwebsocket *wsi, struct pollfd *pollfd)
600{
601 struct lws_tokens eff_buf;
602 int n;
603 int ret;
604 int m;
Andy Greena41314f2011-05-23 10:00:03 +0100605 int handled = 0;
Andy Green3b84c002011-03-06 13:14:42 +0000606
Andy Greena41314f2011-05-23 10:00:03 +0100607 for (n = 0; n < wsi->count_active_extensions; n++) {
608 if (!wsi->active_extensions[n]->callback)
609 continue;
610
611 m = wsi->active_extensions[n]->callback(context,
612 wsi->active_extensions[n], wsi,
613 LWS_EXT_CALLBACK_IS_WRITEABLE,
614 wsi->active_extensions_user[n], NULL, 0);
615 if (m > handled)
616 handled = m;
617 }
618
619 if (handled == 1)
620 goto notify_action;
621
622 if (!wsi->extension_data_pending || handled == 2)
Andy Green3b84c002011-03-06 13:14:42 +0000623 goto user_service;
624
625 /*
626 * check in on the active extensions, see if they
627 * had pending stuff to spill... they need to get the
628 * first look-in otherwise sequence will be disordered
629 *
630 * NULL, zero-length eff_buf means just spill pending
631 */
632
633 ret = 1;
634 while (ret == 1) {
635
636 /* default to nobody has more to spill */
637
638 ret = 0;
639 eff_buf.token = NULL;
640 eff_buf.token_len = 0;
641
642 /* give every extension a chance to spill */
643
644 for (n = 0; n < wsi->count_active_extensions; n++) {
645 m = wsi->active_extensions[n]->callback(
Andy Green46c2ea02011-03-22 09:04:01 +0000646 wsi->protocol->owning_server,
647 wsi->active_extensions[n], wsi,
Andy Green3b84c002011-03-06 13:14:42 +0000648 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
649 wsi->active_extensions_user[n], &eff_buf, 0);
650 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +0800651 lwsl_err("ext reports fatal error\n");
Andy Green3b84c002011-03-06 13:14:42 +0000652 return -1;
653 }
654 if (m)
655 /*
656 * at least one extension told us he has more
657 * to spill, so we will go around again after
658 */
659 ret = 1;
660 }
661
662 /* assuming they gave us something to send, send it */
663
664 if (eff_buf.token_len) {
665 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
666 eff_buf.token_len))
667 return -1;
668 } else
669 continue;
670
671 /* no extension has more to spill */
672
673 if (!ret)
674 continue;
675
676 /*
677 * There's more to spill from an extension, but we just sent
678 * something... did that leave the pipe choked?
679 */
680
681 if (!lws_send_pipe_choked(wsi))
682 /* no we could add more */
683 continue;
684
Andy Green43db0452013-01-10 19:50:35 +0800685 lwsl_info("choked in POLLOUT service\n");
Andy Green3b84c002011-03-06 13:14:42 +0000686
687 /*
688 * Yes, he's choked. Leave the POLLOUT masked on so we will
689 * come back here when he is unchoked. Don't call the user
690 * callback to enforce ordering of spilling, he'll get called
691 * when we come back here and there's nothing more to spill.
692 */
693
694 return 0;
695 }
696
697 wsi->extension_data_pending = 0;
698
699user_service:
700 /* one shot */
701
Andy Greena41314f2011-05-23 10:00:03 +0100702 if (pollfd) {
703 pollfd->events &= ~POLLOUT;
Andy Green3b84c002011-03-06 13:14:42 +0000704
Andy Greena41314f2011-05-23 10:00:03 +0100705 /* external POLL support via protocol 0 */
706 context->protocols[0].callback(context, wsi,
707 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
708 (void *)(long)wsi->sock, NULL, POLLOUT);
709 }
710
711notify_action:
Andy Green3b84c002011-03-06 13:14:42 +0000712
Andy Green9e4c2b62011-03-07 20:47:39 +0000713 if (wsi->mode == LWS_CONNMODE_WS_CLIENT)
714 n = LWS_CALLBACK_CLIENT_WRITEABLE;
715 else
716 n = LWS_CALLBACK_SERVER_WRITEABLE;
717
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800718 wsi->protocol->callback(context, wsi, (enum libwebsocket_callback_reasons) n, wsi->user_space, NULL, 0);
Andy Green3b84c002011-03-06 13:14:42 +0000719
720 return 0;
721}
722
723
724
Andy Greena41314f2011-05-23 10:00:03 +0100725void
726libwebsocket_service_timeout_check(struct libwebsocket_context *context,
727 struct libwebsocket *wsi, unsigned int sec)
728{
729 int n;
730
731 /*
732 * if extensions want in on it (eg, we are a mux parent)
733 * give them a chance to service child timeouts
734 */
735
736 for (n = 0; n < wsi->count_active_extensions; n++)
737 wsi->active_extensions[n]->callback(
738 context, wsi->active_extensions[n],
739 wsi, LWS_EXT_CALLBACK_1HZ,
740 wsi->active_extensions_user[n], NULL, sec);
741
742 if (!wsi->pending_timeout)
743 return;
Andy Green6ee372f2012-04-09 15:09:01 +0800744
Andy Greena41314f2011-05-23 10:00:03 +0100745 /*
746 * if we went beyond the allowed time, kill the
747 * connection
748 */
749
750 if (sec > wsi->pending_timeout_limit) {
Andy Green43db0452013-01-10 19:50:35 +0800751 lwsl_info("TIMEDOUT WAITING\n");
Andy Greena41314f2011-05-23 10:00:03 +0100752 libwebsocket_close_and_free_session(context,
753 wsi, LWS_CLOSE_STATUS_NOSTATUS);
754 }
755}
756
757struct libwebsocket *
758libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
759{
760 struct libwebsocket *new_wsi;
761 int n;
762
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800763 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Greena41314f2011-05-23 10:00:03 +0100764 if (new_wsi == NULL) {
Andy Green43db0452013-01-10 19:50:35 +0800765 lwsl_err("Out of memory for new connection\n");
Andy Greena41314f2011-05-23 10:00:03 +0100766 return NULL;
767 }
768
Andy Green6ee372f2012-04-09 15:09:01 +0800769 memset(new_wsi, 0, sizeof(struct libwebsocket));
Andy Greena41314f2011-05-23 10:00:03 +0100770 new_wsi->count_active_extensions = 0;
771 new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
772
773 /* intialize the instance struct */
774
775 new_wsi->state = WSI_STATE_HTTP;
776 new_wsi->name_buffer_pos = 0;
777 new_wsi->mode = LWS_CONNMODE_WS_SERVING;
778
779 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
780 new_wsi->utf8_token[n].token = NULL;
781 new_wsi->utf8_token[n].token_len = 0;
782 }
783
784 /*
785 * these can only be set once the protocol is known
786 * we set an unestablished connection's protocol pointer
787 * to the start of the supported list, so it can look
788 * for matching ones during the handshake
789 */
790 new_wsi->protocol = context->protocols;
791 new_wsi->user_space = NULL;
792
793 /*
794 * Default protocol is 76 / 00
795 * After 76, there's a header specified to inform which
796 * draft the client wants, when that's seen we modify
797 * the individual connection's spec revision accordingly
798 */
799 new_wsi->ietf_spec_revision = 0;
800
801 return new_wsi;
802}
803
804char *
805libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
806 struct libwebsocket *wsi, char *pkt)
807{
808 char hash[20];
809 char *p = pkt;
810 int n;
811 struct libwebsocket_extension *ext;
Andy Green09226502011-05-28 10:19:19 +0100812 struct libwebsocket_extension *ext1;
Andy Greena41314f2011-05-23 10:00:03 +0100813 int ext_count = 0;
Andy Green6ee372f2012-04-09 15:09:01 +0800814 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
815 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena41314f2011-05-23 10:00:03 +0100816 static const char magic_websocket_guid[] =
817 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
818
819 /*
820 * create the random key
821 */
822
823 n = libwebsockets_get_random(context, hash, 16);
824 if (n != 16) {
Andy Green43db0452013-01-10 19:50:35 +0800825 lwsl_err("Unable to read from random dev %s\n",
Andy Greena41314f2011-05-23 10:00:03 +0100826 SYSTEM_RANDOM_FILEPATH);
827 free(wsi->c_path);
828 free(wsi->c_host);
829 if (wsi->c_origin)
830 free(wsi->c_origin);
831 if (wsi->c_protocol)
832 free(wsi->c_protocol);
833 libwebsocket_close_and_free_session(context, wsi,
834 LWS_CLOSE_STATUS_NOSTATUS);
835 return NULL;
836 }
837
838 lws_b64_encode_string(hash, 16, wsi->key_b64,
839 sizeof wsi->key_b64);
840
841 /*
842 * 00 example client handshake
843 *
844 * GET /socket.io/websocket HTTP/1.1
845 * Upgrade: WebSocket
846 * Connection: Upgrade
847 * Host: 127.0.0.1:9999
848 * Origin: http://127.0.0.1
849 * Sec-WebSocket-Key1: 1 0 2#0W 9 89 7 92 ^
850 * Sec-WebSocket-Key2: 7 7Y 4328 B2v[8(z1
851 * Cookie: socketio=websocket
852 *
853 * (Á®Ä0¶†≥
854 *
855 * 04 example client handshake
856 *
857 * GET /chat HTTP/1.1
858 * Host: server.example.com
859 * Upgrade: websocket
860 * Connection: Upgrade
861 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
862 * Sec-WebSocket-Origin: http://example.com
863 * Sec-WebSocket-Protocol: chat, superchat
864 * Sec-WebSocket-Version: 4
865 */
866
867 p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a", wsi->c_path);
868
David Galeano4fbc40c2013-01-10 10:26:05 +0800869 p += sprintf(p, "Pragma: no-cache\x0d\x0a"
870 "Cache-Control: no-cache\x0d\x0a");
871
Andy Greena41314f2011-05-23 10:00:03 +0100872 if (wsi->ietf_spec_revision == 0) {
873 unsigned char spaces_1, spaces_2;
874 unsigned int max_1, max_2;
875 unsigned int num_1, num_2;
876 unsigned long product_1, product_2;
877 char key_1[40];
878 char key_2[40];
879 unsigned int seed;
880 unsigned int count;
881 char challenge[16];
882
Andy Green6ee372f2012-04-09 15:09:01 +0800883 libwebsockets_get_random(context, &spaces_1, sizeof(char));
884 libwebsockets_get_random(context, &spaces_2, sizeof(char));
Andy Greena41314f2011-05-23 10:00:03 +0100885
886 spaces_1 = (spaces_1 % 12) + 1;
887 spaces_2 = (spaces_2 % 12) + 1;
888
889 max_1 = 4294967295 / spaces_1;
890 max_2 = 4294967295 / spaces_2;
891
892 libwebsockets_get_random(context, &num_1, sizeof(int));
893 libwebsockets_get_random(context, &num_2, sizeof(int));
894
895 num_1 = (num_1 % max_1);
896 num_2 = (num_2 % max_2);
897
898 challenge[0] = num_1 >> 24;
899 challenge[1] = num_1 >> 16;
900 challenge[2] = num_1 >> 8;
901 challenge[3] = num_1;
902 challenge[4] = num_2 >> 24;
903 challenge[5] = num_2 >> 16;
904 challenge[6] = num_2 >> 8;
905 challenge[7] = num_2;
906
907 product_1 = num_1 * spaces_1;
908 product_2 = num_2 * spaces_2;
909
910 sprintf(key_1, "%lu", product_1);
911 sprintf(key_2, "%lu", product_2);
912
913 libwebsockets_get_random(context, &seed, sizeof(int));
914 libwebsockets_get_random(context, &count, sizeof(int));
915
916 libwebsockets_00_spam(key_1, (count % 12) + 1, seed);
917
918 libwebsockets_get_random(context, &seed, sizeof(int));
919 libwebsockets_get_random(context, &count, sizeof(int));
920
921 libwebsockets_00_spam(key_2, (count % 12) + 1, seed);
922
923 libwebsockets_get_random(context, &seed, sizeof(int));
924
925 libwebsockets_00_spaceout(key_1, spaces_1, seed);
926 libwebsockets_00_spaceout(key_2, spaces_2, seed >> 16);
927
928 p += sprintf(p, "Upgrade: WebSocket\x0d\x0a"
929 "Connection: Upgrade\x0d\x0aHost: %s\x0d\x0a",
930 wsi->c_host);
931 if (wsi->c_origin)
Andy Green6ee372f2012-04-09 15:09:01 +0800932 p += sprintf(p, "Origin: %s\x0d\x0a", wsi->c_origin);
Andy Greena41314f2011-05-23 10:00:03 +0100933
934 if (wsi->c_protocol)
935 p += sprintf(p, "Sec-WebSocket-Protocol: %s"
936 "\x0d\x0a", wsi->c_protocol);
937
Andy Green6ee372f2012-04-09 15:09:01 +0800938 p += sprintf(p, "Sec-WebSocket-Key1: %s\x0d\x0a", key_1);
939 p += sprintf(p, "Sec-WebSocket-Key2: %s\x0d\x0a", key_2);
Andy Greena41314f2011-05-23 10:00:03 +0100940
941 /* give userland a chance to append, eg, cookies */
942
943 context->protocols[0].callback(context, wsi,
944 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
945 NULL, &p, (pkt + sizeof(pkt)) - p - 12);
946
947 p += sprintf(p, "\x0d\x0a");
948
949 if (libwebsockets_get_random(context, p, 8) != 8)
950 return NULL;
951 memcpy(&challenge[8], p, 8);
952 p += 8;
953
954 /* precompute what we want to see from the server */
955
956 MD5((unsigned char *)challenge, 16,
957 (unsigned char *)wsi->initial_handshake_hash_base64);
958
959 goto issue_hdr;
960 }
961
962 p += sprintf(p, "Host: %s\x0d\x0a", wsi->c_host);
David Galeano4fbc40c2013-01-10 10:26:05 +0800963 p += sprintf(p, "Upgrade: websocket\x0d\x0a"
964 "Connection: Upgrade\x0d\x0a"
965 "Sec-WebSocket-Key: ");
Andy Greena41314f2011-05-23 10:00:03 +0100966 strcpy(p, wsi->key_b64);
967 p += strlen(wsi->key_b64);
968 p += sprintf(p, "\x0d\x0a");
David Galeanoaa0bc862013-01-09 15:31:46 +0800969 if (wsi->c_origin) {
970 if (wsi->ietf_spec_revision == 13) {
971 p += sprintf(p, "Origin: %s\x0d\x0a",
972 wsi->c_origin);
973 }
974 else {
David Galeanocb193682013-01-09 15:29:00 +0800975 p += sprintf(p, "Sec-WebSocket-Origin: %s\x0d\x0a",
Andy Greena41314f2011-05-23 10:00:03 +0100976 wsi->c_origin);
David Galeanoaa0bc862013-01-09 15:31:46 +0800977 }
978 }
Andy Greena41314f2011-05-23 10:00:03 +0100979 if (wsi->c_protocol)
980 p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
981 wsi->c_protocol);
982
983 /* tell the server what extensions we could support */
984
985 p += sprintf(p, "Sec-WebSocket-Extensions: ");
986
Andy Green6ee372f2012-04-09 15:09:01 +0800987 ext = context->extensions;
Andy Greena41314f2011-05-23 10:00:03 +0100988 while (ext && ext->callback) {
989
990 n = 0;
Andy Green09226502011-05-28 10:19:19 +0100991 ext1 = context->extensions;
Andy Green09226502011-05-28 10:19:19 +0100992
Andy Green6ee372f2012-04-09 15:09:01 +0800993 while (ext1 && ext1->callback) {
Andy Green09226502011-05-28 10:19:19 +0100994 n |= ext1->callback(context, ext1, wsi,
995 LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
996 NULL, (char *)ext->name, 0);
997
998 ext1++;
999 }
1000
Andy Green6ee372f2012-04-09 15:09:01 +08001001 if (n) { /* an extension vetos us */
Andy Green43db0452013-01-10 19:50:35 +08001002 lwsl_ext("ext %s vetoed\n", (char *)ext->name);
Andy Green09226502011-05-28 10:19:19 +01001003 ext++;
1004 continue;
1005 }
1006
Andy Greena41314f2011-05-23 10:00:03 +01001007 n = context->protocols[0].callback(context, wsi,
1008 LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
1009 wsi->user_space, (char *)ext->name, 0);
1010
1011 /*
1012 * zero return from callback means
1013 * go ahead and allow the extension,
1014 * it's what we get if the callback is
1015 * unhandled
1016 */
1017
1018 if (n) {
1019 ext++;
1020 continue;
1021 }
1022
1023 /* apply it */
1024
1025 if (ext_count)
1026 *p++ = ',';
1027 p += sprintf(p, "%s", ext->name);
1028 ext_count++;
1029
1030 ext++;
1031 }
1032
1033 p += sprintf(p, "\x0d\x0a");
1034
1035 if (wsi->ietf_spec_revision)
1036 p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
1037 wsi->ietf_spec_revision);
1038
1039 /* give userland a chance to append, eg, cookies */
1040
1041 context->protocols[0].callback(context, wsi,
1042 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
1043 NULL, &p, (pkt + sizeof(pkt)) - p - 12);
1044
1045 p += sprintf(p, "\x0d\x0a");
1046
1047 /* prepare the expected server accept response */
1048
1049 strcpy((char *)buf, wsi->key_b64);
1050 strcpy((char *)&buf[strlen((char *)buf)], magic_websocket_guid);
1051
1052 SHA1(buf, strlen((char *)buf), (unsigned char *)hash);
1053
1054 lws_b64_encode_string(hash, 20,
1055 wsi->initial_handshake_hash_base64,
1056 sizeof wsi->initial_handshake_hash_base64);
1057
1058issue_hdr:
1059
Andy Green6ee372f2012-04-09 15:09:01 +08001060#if 0
1061 puts(pkt);
1062#endif
Andy Green09226502011-05-28 10:19:19 +01001063
Andy Greena41314f2011-05-23 10:00:03 +01001064 /* done with these now */
1065
1066 free(wsi->c_path);
1067 free(wsi->c_host);
1068 if (wsi->c_origin)
1069 free(wsi->c_origin);
1070
1071 return p;
1072}
1073
1074int
1075lws_client_interpret_server_handshake(struct libwebsocket_context *context,
1076 struct libwebsocket *wsi)
1077{
Andy Green6ee372f2012-04-09 15:09:01 +08001078 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
1079 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena41314f2011-05-23 10:00:03 +01001080 char pkt[1024];
1081 char *p = &pkt[0];
1082 const char *pc;
1083 const char *c;
1084 int more = 1;
1085 int okay = 0;
1086 char ext_name[128];
1087 struct libwebsocket_extension *ext;
1088 void *v;
Andy Greenc15cb382011-06-26 10:27:28 +01001089 int len = 0;
Andy Greena41314f2011-05-23 10:00:03 +01001090 int n;
1091 static const char magic_websocket_04_masking_guid[] =
1092 "61AC5F19-FBBA-4540-B96F-6561F1AB40A8";
1093
1094 /*
1095 * 00 / 76 -->
1096 *
1097 * HTTP/1.1 101 WebSocket Protocol Handshake
1098 * Upgrade: WebSocket
1099 * Connection: Upgrade
1100 * Sec-WebSocket-Origin: http://127.0.0.1
1101 * Sec-WebSocket-Location: ws://127.0.0.1:9999/socket.io/websocket
1102 *
1103 * xxxxxxxxxxxxxxxx
1104 */
1105
1106 if (wsi->ietf_spec_revision == 0) {
1107 if (!wsi->utf8_token[WSI_TOKEN_HTTP].token_len ||
1108 !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
1109 !wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len ||
1110 !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len ||
1111 (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len &&
1112 wsi->c_protocol != NULL)) {
Andy Green43db0452013-01-10 19:50:35 +08001113 lwsl_parser("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001114 "missing required header(s)\n");
1115 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001116 lwsl_parser("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001117 goto bail3;
1118 }
1119
1120 strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token);
Andy Green6ee372f2012-04-09 15:09:01 +08001121 if (strncmp(wsi->utf8_token[WSI_TOKEN_HTTP].token, "101", 3)) {
Andy Green43db0452013-01-10 19:50:35 +08001122 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001123 "server sent bad HTTP response '%s'\n",
1124 wsi->utf8_token[WSI_TOKEN_HTTP].token);
1125 goto bail3;
1126 }
1127
Andy Green6ee372f2012-04-09 15:09:01 +08001128 if (wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len < 16) {
Andy Green43db0452013-01-10 19:50:35 +08001129 lwsl_parser("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001130 "challenge reply too short %d\n",
1131 wsi->utf8_token[
1132 WSI_TOKEN_CHALLENGE].token_len);
1133 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001134 lwsl_parser("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001135 goto bail3;
1136
1137 }
1138
1139 goto select_protocol;
1140 }
1141
1142 /*
1143 * well, what the server sent looked reasonable for syntax.
1144 * Now let's confirm it sent all the necessary headers
1145 */
1146#if 0
Andy Green43db0452013-01-10 19:50:35 +08001147 lwsl_parser("WSI_TOKEN_HTTP: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001148 wsi->utf8_token[WSI_TOKEN_HTTP].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001149 lwsl_parser("WSI_TOKEN_UPGRADE: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001150 wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001151 lwsl_parser("WSI_TOKEN_CONNECTION: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001152 wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001153 lwsl_parser("WSI_TOKEN_ACCEPT: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001154 wsi->utf8_token[WSI_TOKEN_ACCEPT].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001155 lwsl_parser("WSI_TOKEN_NONCE: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001156 wsi->utf8_token[WSI_TOKEN_NONCE].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001157 lwsl_parser("WSI_TOKEN_PROTOCOL: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001158 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len);
Andy Greena41314f2011-05-23 10:00:03 +01001159#endif
Andy Green6ee372f2012-04-09 15:09:01 +08001160 if (!wsi->utf8_token[WSI_TOKEN_HTTP].token_len ||
1161 !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
1162 !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len ||
1163 !wsi->utf8_token[WSI_TOKEN_ACCEPT].token_len ||
1164 (!wsi->utf8_token[WSI_TOKEN_NONCE].token_len &&
Andy Greena41314f2011-05-23 10:00:03 +01001165 wsi->ietf_spec_revision == 4) ||
Andy Green6ee372f2012-04-09 15:09:01 +08001166 (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len &&
1167 wsi->c_protocol != NULL)) {
Andy Green43db0452013-01-10 19:50:35 +08001168 lwsl_parser("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001169 "missing required header(s)\n");
1170 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001171 lwsl_parser("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001172 goto bail3;
1173 }
1174
1175 /*
1176 * Everything seems to be there, now take a closer look at what
1177 * is in each header
1178 */
1179
1180 strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token);
Artem Egorkined515ddd2011-11-23 10:46:24 +02001181 if (strncmp(wsi->utf8_token[WSI_TOKEN_HTTP].token, "101", 3)) {
Andy Green43db0452013-01-10 19:50:35 +08001182 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001183 "server sent bad HTTP response '%s'\n",
1184 wsi->utf8_token[WSI_TOKEN_HTTP].token);
1185 goto bail3;
1186 }
1187
1188 strtolower(wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
1189 if (strcmp(wsi->utf8_token[WSI_TOKEN_UPGRADE].token,
1190 "websocket")) {
Andy Green43db0452013-01-10 19:50:35 +08001191 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001192 "sent bad Upgrade header '%s'\n",
1193 wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
1194 goto bail3;
1195 }
1196
1197 strtolower(wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
1198 if (strcmp(wsi->utf8_token[WSI_TOKEN_CONNECTION].token,
1199 "upgrade")) {
Andy Green43db0452013-01-10 19:50:35 +08001200 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001201 "sent bad Connection hdr '%s'\n",
1202 wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
1203 goto bail3;
1204 }
1205
1206select_protocol:
1207 pc = wsi->c_protocol;
1208 if (pc == NULL)
Andy Green43db0452013-01-10 19:50:35 +08001209 lwsl_parser("lws_client_interpret_server_handshake: "
Andy Green6ee372f2012-04-09 15:09:01 +08001210 "NULL c_protocol\n");
Andy Greena41314f2011-05-23 10:00:03 +01001211 else
Andy Green43db0452013-01-10 19:50:35 +08001212 lwsl_parser("lws_client_interpret_server_handshake: "
Andy Green6ee372f2012-04-09 15:09:01 +08001213 "cPprotocol='%s'\n", pc);
Andy Greena41314f2011-05-23 10:00:03 +01001214
1215 /*
1216 * confirm the protocol the server wants to talk was in the list
1217 * of protocols we offered
1218 */
1219
1220 if (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len) {
1221
Andy Green43db0452013-01-10 19:50:35 +08001222 lwsl_warn("lws_client_interpret_server_handshake "
Andy Green6ee372f2012-04-09 15:09:01 +08001223 "WSI_TOKEN_PROTOCOL is null\n");
Andy Greena41314f2011-05-23 10:00:03 +01001224 /*
1225 * no protocol name to work from,
1226 * default to first protocol
1227 */
1228 wsi->protocol = &context->protocols[0];
David Brooks2c60d952012-04-20 12:19:01 +08001229 wsi->c_callback = wsi->protocol->callback;
Andy Greena41314f2011-05-23 10:00:03 +01001230 free(wsi->c_protocol);
1231
David Galeano4c38f142013-01-09 19:49:50 +08001232 goto check_extensions;
Andy Greena41314f2011-05-23 10:00:03 +01001233 }
1234
1235 while (*pc && !okay) {
Andy Green6ee372f2012-04-09 15:09:01 +08001236 if ((!strncmp(pc, wsi->utf8_token[WSI_TOKEN_PROTOCOL].token,
1237 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len)) &&
1238 (pc[wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len] == ',' ||
1239 pc[wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len] == '\0')) {
Andy Greena41314f2011-05-23 10:00:03 +01001240 okay = 1;
1241 continue;
1242 }
1243 while (*pc && *pc != ',')
1244 pc++;
1245 while (*pc && *pc != ' ')
1246 pc++;
1247 }
1248
1249 /* done with him now */
1250
1251 if (wsi->c_protocol)
1252 free(wsi->c_protocol);
1253
Andy Greena41314f2011-05-23 10:00:03 +01001254 if (!okay) {
Andy Green43db0452013-01-10 19:50:35 +08001255 lwsl_err("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001256 "sent bad protocol '%s'\n",
1257 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
1258 goto bail2;
1259 }
1260
1261 /*
1262 * identify the selected protocol struct and set it
1263 */
1264 n = 0;
1265 wsi->protocol = NULL;
David Brooks2c60d952012-04-20 12:19:01 +08001266 while (context->protocols[n].callback && !wsi->protocol) { /* Stop after finding first one?? */
Andy Greena41314f2011-05-23 10:00:03 +01001267 if (strcmp(wsi->utf8_token[WSI_TOKEN_PROTOCOL].token,
David Brooks2c60d952012-04-20 12:19:01 +08001268 context->protocols[n].name) == 0) {
Andy Greena41314f2011-05-23 10:00:03 +01001269 wsi->protocol = &context->protocols[n];
David Brooks2c60d952012-04-20 12:19:01 +08001270 wsi->c_callback = wsi->protocol->callback;
1271 }
Andy Greena41314f2011-05-23 10:00:03 +01001272 n++;
1273 }
1274
1275 if (wsi->protocol == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08001276 lwsl_err("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001277 "requested protocol '%s', which we "
1278 "said we supported but we don't!\n",
1279 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
1280 goto bail2;
1281 }
1282
1283
David Galeano4c38f142013-01-09 19:49:50 +08001284check_extensions:
1285
Andy Greena41314f2011-05-23 10:00:03 +01001286 /* instantiate the accepted extensions */
1287
1288 if (!wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token_len) {
Andy Green43db0452013-01-10 19:50:35 +08001289 lwsl_ext("no client extenstions allowed by server\n");
Andy Greena41314f2011-05-23 10:00:03 +01001290 goto check_accept;
1291 }
1292
1293 /*
1294 * break down the list of server accepted extensions
1295 * and go through matching them or identifying bogons
1296 */
1297
1298 c = wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token;
1299 n = 0;
1300 while (more) {
1301
1302 if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
1303 ext_name[n] = *c++;
1304 if (n < sizeof(ext_name) - 1)
1305 n++;
1306 continue;
1307 }
1308 ext_name[n] = '\0';
1309 if (!*c)
1310 more = 0;
1311 else {
1312 c++;
1313 if (!n)
1314 continue;
1315 }
1316
1317 /* check we actually support it */
1318
Andy Green43db0452013-01-10 19:50:35 +08001319 lwsl_ext("checking client ext %s\n", ext_name);
Andy Greena41314f2011-05-23 10:00:03 +01001320
1321 n = 0;
1322 ext = wsi->protocol->owning_server->extensions;
1323 while (ext && ext->callback) {
1324
1325 if (strcmp(ext_name, ext->name)) {
1326 ext++;
1327 continue;
1328 }
1329
1330 n = 1;
1331
Andy Green43db0452013-01-10 19:50:35 +08001332 lwsl_ext("instantiating client ext %s\n", ext_name);
Andy Greena41314f2011-05-23 10:00:03 +01001333
1334 /* instantiate the extension on this conn */
1335
1336 wsi->active_extensions_user[
1337 wsi->count_active_extensions] =
1338 malloc(ext->per_session_data_size);
Andy Green41c58032013-01-12 13:21:08 +08001339 if (wsi->active_extensions_user[
1340 wsi->count_active_extensions] == NULL) {
1341 lwsl_err("Out of mem\n");
1342 goto bail2;
1343 }
Andy Greenf6652412011-05-25 20:46:18 +01001344 memset(wsi->active_extensions_user[
1345 wsi->count_active_extensions], 0,
1346 ext->per_session_data_size);
Andy Greena41314f2011-05-23 10:00:03 +01001347 wsi->active_extensions[
1348 wsi->count_active_extensions] = ext;
1349
1350 /* allow him to construct his context */
1351
1352 ext->callback(wsi->protocol->owning_server,
1353 ext, wsi,
1354 LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
1355 wsi->active_extensions_user[
1356 wsi->count_active_extensions],
1357 NULL, 0);
1358
1359 wsi->count_active_extensions++;
1360
1361 ext++;
1362 }
1363
1364 if (n == 0) {
Andy Green43db0452013-01-10 19:50:35 +08001365 lwsl_warn("Server said we should use"
Andy Greena41314f2011-05-23 10:00:03 +01001366 "an unknown extension '%s'!\n", ext_name);
1367 goto bail2;
1368 }
1369
1370 n = 0;
1371 }
1372
1373
1374check_accept:
1375
1376 if (wsi->ietf_spec_revision == 0) {
1377
1378 if (memcmp(wsi->initial_handshake_hash_base64,
1379 wsi->utf8_token[WSI_TOKEN_CHALLENGE].token, 16)) {
Andy Green43db0452013-01-10 19:50:35 +08001380 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001381 "failed 00 challenge compare\n");
1382 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001383 lwsl_warn("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001384 goto bail2;
1385 }
1386
1387 goto accept_ok;
1388 }
1389
1390 /*
1391 * Confirm his accept token is the one we precomputed
1392 */
1393
1394 if (strcmp(wsi->utf8_token[WSI_TOKEN_ACCEPT].token,
1395 wsi->initial_handshake_hash_base64)) {
Andy Green43db0452013-01-10 19:50:35 +08001396 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001397 "sent bad ACCEPT '%s' vs computed '%s'\n",
1398 wsi->utf8_token[WSI_TOKEN_ACCEPT].token,
1399 wsi->initial_handshake_hash_base64);
1400 goto bail2;
1401 }
1402
1403 if (wsi->ietf_spec_revision == 4) {
1404 /*
1405 * Calculate the 04 masking key to use when
1406 * sending data to server
1407 */
1408
1409 strcpy((char *)buf, wsi->key_b64);
1410 p = (char *)buf + strlen(wsi->key_b64);
1411 strcpy(p, wsi->utf8_token[WSI_TOKEN_NONCE].token);
1412 p += wsi->utf8_token[WSI_TOKEN_NONCE].token_len;
1413 strcpy(p, magic_websocket_04_masking_guid);
1414 SHA1(buf, strlen((char *)buf), wsi->masking_key_04);
1415 }
Andy Green6ee372f2012-04-09 15:09:01 +08001416accept_ok:
Andy Greena41314f2011-05-23 10:00:03 +01001417
1418 /* allocate the per-connection user memory (if any) */
Andy Green6ee372f2012-04-09 15:09:01 +08001419 if (wsi->protocol->per_session_data_size &&
1420 !libwebsocket_ensure_user_space(wsi))
1421 goto bail2;
Andy Greena41314f2011-05-23 10:00:03 +01001422
1423 /* clear his proxy connection timeout */
1424
1425 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1426
1427 /* mark him as being alive */
1428
1429 wsi->state = WSI_STATE_ESTABLISHED;
1430 wsi->mode = LWS_CONNMODE_WS_CLIENT;
1431
Andy Green43db0452013-01-10 19:50:35 +08001432 lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
Andy Greena41314f2011-05-23 10:00:03 +01001433
1434 /* call him back to inform him he is up */
1435
1436 wsi->protocol->callback(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08001437 LWS_CALLBACK_CLIENT_ESTABLISHED,
1438 wsi->user_space, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01001439
1440 /*
1441 * inform all extensions, not just active ones since they
1442 * already know
1443 */
1444
1445 ext = context->extensions;
1446
1447 while (ext && ext->callback) {
1448 v = NULL;
1449 for (n = 0; n < wsi->count_active_extensions; n++)
1450 if (wsi->active_extensions[n] == ext)
1451 v = wsi->active_extensions_user[n];
1452
1453 ext->callback(context, ext, wsi,
1454 LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED, v, NULL, 0);
1455 ext++;
1456 }
1457
1458 return 0;
1459
1460bail3:
1461 if (wsi->c_protocol)
1462 free(wsi->c_protocol);
1463
1464bail2:
David Brooks80a44972012-04-20 12:18:47 +08001465 if (wsi->c_callback) wsi->c_callback(context, wsi,
1466 LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
1467 wsi->user_space,
1468 NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01001469 libwebsocket_close_and_free_session(context, wsi,
David Brooks80a44972012-04-20 12:18:47 +08001470 LWS_CLOSE_STATUS_NOSTATUS); // But this should be LWS_CLOSE_STATUS_PROTOCOL_ERR
1471
Andy Greena41314f2011-05-23 10:00:03 +01001472 return 1;
1473}
1474
1475
1476
Andy Green9f990342011-02-12 11:57:45 +00001477/**
1478 * libwebsocket_service_fd() - Service polled socket with something waiting
Peter Hinz56885f32011-03-02 22:03:47 +00001479 * @context: Websocket context
Andy Green9f990342011-02-12 11:57:45 +00001480 * @pollfd: The pollfd entry describing the socket fd and which events
Andy Green6ee372f2012-04-09 15:09:01 +08001481 * happened.
Andy Green9f990342011-02-12 11:57:45 +00001482 *
1483 * This function closes any active connections and then frees the
1484 * context. After calling this, any further use of the context is
1485 * undefined.
1486 */
1487
1488int
Peter Hinz56885f32011-03-02 22:03:47 +00001489libwebsocket_service_fd(struct libwebsocket_context *context,
Andy Green0d338332011-02-12 11:57:43 +00001490 struct pollfd *pollfd)
Andy Greenb45993c2010-12-18 15:13:50 +00001491{
Andy Green6ee372f2012-04-09 15:09:01 +08001492 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
1493 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena71eafc2011-02-14 17:59:43 +00001494 struct libwebsocket *wsi;
Andy Green0d338332011-02-12 11:57:43 +00001495 struct libwebsocket *new_wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00001496 int n;
Andy Green0d338332011-02-12 11:57:43 +00001497 int m;
Tobias Maiere8c9b562012-04-05 11:57:12 +02001498 ssize_t len;
Andy Green0d338332011-02-12 11:57:43 +00001499 int accept_fd;
1500 unsigned int clilen;
1501 struct sockaddr_in cli_addr;
Andy Greena71eafc2011-02-14 17:59:43 +00001502 struct timeval tv;
Andy Greenbe93fef2011-02-14 20:25:43 +00001503 char pkt[1024];
1504 char *p = &pkt[0];
Andy Green2366b1c2011-03-06 13:15:31 +00001505 int more = 1;
Andy Green98a717c2011-03-06 13:14:15 +00001506 struct lws_tokens eff_buf;
Andy Green6c939552011-03-08 08:56:57 +00001507 int opt = 1;
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001508 char c;
Andy Greenc6517fa2011-03-06 13:15:29 +00001509
Andy Greenbe93fef2011-02-14 20:25:43 +00001510#ifdef LWS_OPENSSL_SUPPORT
1511 char ssl_err_buf[512];
1512#endif
Andy Greena71eafc2011-02-14 17:59:43 +00001513 /*
1514 * you can call us with pollfd = NULL to just allow the once-per-second
1515 * global timeout checks; if less than a second since the last check
1516 * it returns immediately then.
1517 */
1518
1519 gettimeofday(&tv, NULL);
1520
Peter Hinz56885f32011-03-02 22:03:47 +00001521 if (context->last_timeout_check_s != tv.tv_sec) {
1522 context->last_timeout_check_s = tv.tv_sec;
Andy Greena71eafc2011-02-14 17:59:43 +00001523
1524 /* global timeout check once per second */
1525
Peter Hinz56885f32011-03-02 22:03:47 +00001526 for (n = 0; n < context->fds_count; n++) {
1527 wsi = wsi_from_fd(context, context->fds[n].fd);
Andy Greena71eafc2011-02-14 17:59:43 +00001528
Andy Greena41314f2011-05-23 10:00:03 +01001529 libwebsocket_service_timeout_check(context, wsi,
1530 tv.tv_sec);
Andy Greena71eafc2011-02-14 17:59:43 +00001531 }
1532 }
1533
1534 /* just here for timeout management? */
1535
1536 if (pollfd == NULL)
1537 return 0;
1538
1539 /* no, here to service a socket descriptor */
1540
Peter Hinz56885f32011-03-02 22:03:47 +00001541 wsi = wsi_from_fd(context, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001542
Andy Green0d338332011-02-12 11:57:43 +00001543 if (wsi == NULL)
Andy Greenfa3f4052012-10-07 20:40:35 +08001544 return 0;
Andy Green8f037e42010-12-19 22:13:26 +00001545
Andy Green0d338332011-02-12 11:57:43 +00001546 switch (wsi->mode) {
1547 case LWS_CONNMODE_SERVER_LISTENER:
1548
1549 /* pollin means a client has connected to us then */
1550
David Galeanob88e0962013-01-10 09:54:10 +08001551 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001552 break;
1553
David Galeanof7009352011-09-26 12:09:54 +01001554 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001555 lwsl_warn("too busy to accept new client\n");
David Galeanof7009352011-09-26 12:09:54 +01001556 break;
1557 }
1558
Andy Green0d338332011-02-12 11:57:43 +00001559 /* listen socket got an unencrypted connection... */
1560
1561 clilen = sizeof(cli_addr);
1562 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1563 &clilen);
1564 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001565 lwsl_warn("ERROR on accept: %d\n", strerror(errno));
Andy Green3928f612012-07-20 12:58:38 +08001566 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001567 }
1568
Andy Green6c939552011-03-08 08:56:57 +00001569 /* Disable Nagle */
1570 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08001571 setsockopt(accept_fd, IPPROTO_TCP, TCP_NODELAY,
1572 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00001573
Andy Green07034092011-02-13 08:37:12 +00001574 /*
1575 * look at who we connected to and give user code a chance
1576 * to reject based on client IP. There's no protocol selected
1577 * yet so we issue this to protocols[0]
1578 */
1579
Peter Hinz56885f32011-03-02 22:03:47 +00001580 if ((context->protocols[0].callback)(context, wsi,
Andy Green07034092011-02-13 08:37:12 +00001581 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
Andy Green6ee372f2012-04-09 15:09:01 +08001582 (void *)(long)accept_fd, NULL, 0)) {
Andy Green43db0452013-01-10 19:50:35 +08001583 lwsl_debug("Callback denied network connection\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001584#ifdef WIN32
1585 closesocket(accept_fd);
1586#else
Andy Green07034092011-02-13 08:37:12 +00001587 close(accept_fd);
Peter Hinz56885f32011-03-02 22:03:47 +00001588#endif
Andy Green07034092011-02-13 08:37:12 +00001589 break;
1590 }
1591
Andy Green0d338332011-02-12 11:57:43 +00001592 /* accepting connection to main listener */
1593
Andy Greena41314f2011-05-23 10:00:03 +01001594 new_wsi = libwebsocket_create_new_server_wsi(context);
David Galeanoed3c8402013-01-10 10:45:24 +08001595 if (new_wsi == NULL) {
1596#ifdef WIN32
1597 closesocket(accept_fd);
1598#else
1599 close(accept_fd);
1600#endif
Andy Green0d338332011-02-12 11:57:43 +00001601 break;
David Galeanoed3c8402013-01-10 10:45:24 +08001602 }
Andy Green0d338332011-02-12 11:57:43 +00001603
Andy Green0d338332011-02-12 11:57:43 +00001604 new_wsi->sock = accept_fd;
Andy Greena41314f2011-05-23 10:00:03 +01001605
Andy Green0d338332011-02-12 11:57:43 +00001606
1607#ifdef LWS_OPENSSL_SUPPORT
1608 new_wsi->ssl = NULL;
Andy Green0d338332011-02-12 11:57:43 +00001609
Peter Hinz56885f32011-03-02 22:03:47 +00001610 if (context->use_ssl) {
Andy Green0d338332011-02-12 11:57:43 +00001611
Peter Hinz56885f32011-03-02 22:03:47 +00001612 new_wsi->ssl = SSL_new(context->ssl_ctx);
Andy Green0d338332011-02-12 11:57:43 +00001613 if (new_wsi->ssl == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08001614 lwsl_err("SSL_new failed: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001615 ERR_error_string(SSL_get_error(
1616 new_wsi->ssl, 0), NULL));
Andy Green1f9bf522011-02-14 21:14:37 +00001617 libwebsockets_decode_ssl_error();
Andy Green0d338332011-02-12 11:57:43 +00001618 free(new_wsi);
David Galeanoed3c8402013-01-10 10:45:24 +08001619#ifdef WIN32
1620 closesocket(accept_fd);
1621#else
1622 close(accept_fd);
1623#endif
Andy Green0d338332011-02-12 11:57:43 +00001624 break;
1625 }
1626
1627 SSL_set_fd(new_wsi->ssl, accept_fd);
1628
1629 n = SSL_accept(new_wsi->ssl);
1630 if (n != 1) {
1631 /*
1632 * browsers seem to probe with various
1633 * ssl params which fail then retry
1634 * and succeed
1635 */
Andy Green43db0452013-01-10 19:50:35 +08001636 lwsl_debug("SSL_accept failed skt %u: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001637 pollfd->fd,
1638 ERR_error_string(SSL_get_error(
1639 new_wsi->ssl, n), NULL));
1640 SSL_free(
1641 new_wsi->ssl);
1642 free(new_wsi);
David Galeanoed3c8402013-01-10 10:45:24 +08001643#ifdef WIN32
1644 closesocket(accept_fd);
1645#else
1646 close(accept_fd);
1647#endif
Andy Green0d338332011-02-12 11:57:43 +00001648 break;
1649 }
Andy Green6ee372f2012-04-09 15:09:01 +08001650
Andy Green43db0452013-01-10 19:50:35 +08001651 lwsl_debug("accepted new SSL conn "
Andy Green0d338332011-02-12 11:57:43 +00001652 "port %u on fd=%d SSL ver %s\n",
1653 ntohs(cli_addr.sin_port), accept_fd,
1654 SSL_get_version(new_wsi->ssl));
1655
1656 } else
1657#endif
Andy Green43db0452013-01-10 19:50:35 +08001658 lwsl_debug("accepted new conn port %u on fd=%d\n",
Andy Green0d338332011-02-12 11:57:43 +00001659 ntohs(cli_addr.sin_port), accept_fd);
1660
Peter Hinz56885f32011-03-02 22:03:47 +00001661 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001662
Andy Green0d338332011-02-12 11:57:43 +00001663 /*
1664 * make sure NO events are seen yet on this new socket
1665 * (otherwise we inherit old fds[client].revents from
1666 * previous socket there and die mysteriously! )
1667 */
Peter Hinz56885f32011-03-02 22:03:47 +00001668 context->fds[context->fds_count].revents = 0;
Andy Green0d338332011-02-12 11:57:43 +00001669
Peter Hinz56885f32011-03-02 22:03:47 +00001670 context->fds[context->fds_count].events = POLLIN;
1671 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001672
Andy Green3221f922011-02-12 13:14:11 +00001673 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001674 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001675 LWS_CALLBACK_ADD_POLL_FD,
1676 (void *)(long)accept_fd, NULL, POLLIN);
1677
Andy Green0d338332011-02-12 11:57:43 +00001678 break;
1679
1680 case LWS_CONNMODE_BROADCAST_PROXY_LISTENER:
1681
1682 /* as we are listening, POLLIN means accept() is needed */
Andy Green6ee372f2012-04-09 15:09:01 +08001683
David Galeanob88e0962013-01-10 09:54:10 +08001684 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001685 break;
1686
1687 /* listen socket got an unencrypted connection... */
1688
1689 clilen = sizeof(cli_addr);
1690 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1691 &clilen);
1692 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001693 lwsl_warn("ERROR on accept %d\n", accept_fd);
Andy Green3928f612012-07-20 12:58:38 +08001694 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001695 }
1696
Peter Hinz56885f32011-03-02 22:03:47 +00001697 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001698 lwsl_err("too busy to accept new broadcast "
Andy Green3221f922011-02-12 13:14:11 +00001699 "proxy client\n");
Andy Green41c58032013-01-12 13:21:08 +08001700 goto bail_prox_listener;
Andy Green0d338332011-02-12 11:57:43 +00001701 }
1702
1703 /* create a dummy wsi for the connection and add it */
1704
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001705 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08001706 if (new_wsi == NULL) {
1707 lwsl_err("Out of mem\n");
1708 goto bail_prox_listener;
1709 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001710 memset(new_wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00001711 new_wsi->sock = accept_fd;
1712 new_wsi->mode = LWS_CONNMODE_BROADCAST_PROXY;
1713 new_wsi->state = WSI_STATE_ESTABLISHED;
Andy Greend6e09112011-03-05 16:12:15 +00001714 new_wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00001715 /* note which protocol we are proxying */
1716 new_wsi->protocol_index_for_broadcast_proxy =
1717 wsi->protocol_index_for_broadcast_proxy;
Peter Hinz56885f32011-03-02 22:03:47 +00001718 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001719
1720 /* add connected socket to internal poll array */
1721
Peter Hinz56885f32011-03-02 22:03:47 +00001722 context->fds[context->fds_count].revents = 0;
1723 context->fds[context->fds_count].events = POLLIN;
1724 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001725
Andy Green3221f922011-02-12 13:14:11 +00001726 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001727 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001728 LWS_CALLBACK_ADD_POLL_FD,
1729 (void *)(long)accept_fd, NULL, POLLIN);
1730
Andy Green0d338332011-02-12 11:57:43 +00001731 break;
1732
Andy Green41c58032013-01-12 13:21:08 +08001733bail_prox_listener:
1734#ifdef WIN32
1735 closesocket(accept_fd);
1736#else
1737 close(accept_fd);
1738#endif
1739 break;
1740
Andy Green0d338332011-02-12 11:57:43 +00001741 case LWS_CONNMODE_BROADCAST_PROXY:
Andy Green8f037e42010-12-19 22:13:26 +00001742
Andy Greenb45993c2010-12-18 15:13:50 +00001743 /* handle session socket closed */
Andy Green8f037e42010-12-19 22:13:26 +00001744
Andy Green0d338332011-02-12 11:57:43 +00001745 if (pollfd->revents & (POLLERR | POLLHUP)) {
Andy Green8f037e42010-12-19 22:13:26 +00001746
Andy Green43db0452013-01-10 19:50:35 +08001747 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Timothy J Fontaineb86d64e2011-02-14 17:55:27 +00001748 (void *)wsi, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001749
Peter Hinz56885f32011-03-02 22:03:47 +00001750 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001751 LWS_CLOSE_STATUS_NORMAL);
Andy Green4b6fbe12011-02-14 08:03:48 +00001752 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00001753 }
Andy Green8f037e42010-12-19 22:13:26 +00001754
Andy Green3b84c002011-03-06 13:14:42 +00001755 /*
1756 * either extension code with stuff to spill, or the user code,
1757 * requested a callback when it was OK to write
1758 */
Andy Green90c7cbc2011-01-27 06:26:52 +00001759
Andy Green3b84c002011-03-06 13:14:42 +00001760 if (pollfd->revents & POLLOUT)
Andy Green6ee372f2012-04-09 15:09:01 +08001761 if (lws_handle_POLLOUT_event(context, wsi,
1762 pollfd) < 0) {
1763 libwebsocket_close_and_free_session(
1764 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00001765 return 1;
1766 }
Andy Green90c7cbc2011-01-27 06:26:52 +00001767
Andy Greenb45993c2010-12-18 15:13:50 +00001768 /* any incoming data ready? */
1769
Andy Green0d338332011-02-12 11:57:43 +00001770 if (!(pollfd->revents & POLLIN))
1771 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001772
Andy Green0d338332011-02-12 11:57:43 +00001773 /* get the issued broadcast payload from the socket */
Andy Greenb45993c2010-12-18 15:13:50 +00001774
Andy Green0d338332011-02-12 11:57:43 +00001775 len = read(pollfd->fd, buf + LWS_SEND_BUFFER_PRE_PADDING,
1776 MAX_BROADCAST_PAYLOAD);
1777 if (len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001778 lwsl_err("Error reading broadcast payload\n");
Andy Green4b6fbe12011-02-14 08:03:48 +00001779 break;
Andy Green0d338332011-02-12 11:57:43 +00001780 }
Andy Greenb45993c2010-12-18 15:13:50 +00001781
Andy Green0d338332011-02-12 11:57:43 +00001782 /* broadcast it to all guys with this protocol index */
Andy Green8f037e42010-12-19 22:13:26 +00001783
Andy Green0d338332011-02-12 11:57:43 +00001784 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Green8f037e42010-12-19 22:13:26 +00001785
Peter Hinz56885f32011-03-02 22:03:47 +00001786 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00001787
Peter Hinz56885f32011-03-02 22:03:47 +00001788 new_wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00001789
Andy Green0d338332011-02-12 11:57:43 +00001790 /* only to clients we are serving to */
Andy Greenb45993c2010-12-18 15:13:50 +00001791
Andy Green0d338332011-02-12 11:57:43 +00001792 if (new_wsi->mode != LWS_CONNMODE_WS_SERVING)
Andy Greenb45993c2010-12-18 15:13:50 +00001793 continue;
1794
1795 /*
1796 * never broadcast to non-established
1797 * connection
1798 */
1799
Andy Green0d338332011-02-12 11:57:43 +00001800 if (new_wsi->state != WSI_STATE_ESTABLISHED)
Andy Green4739e5c2011-01-22 12:51:57 +00001801 continue;
1802
Andy Greenb45993c2010-12-18 15:13:50 +00001803 /*
1804 * only broadcast to connections using
1805 * the requested protocol
1806 */
1807
Andy Green0d338332011-02-12 11:57:43 +00001808 if (new_wsi->protocol->protocol_index !=
1809 wsi->protocol_index_for_broadcast_proxy)
Andy Greenb45993c2010-12-18 15:13:50 +00001810 continue;
1811
Andy Green8f037e42010-12-19 22:13:26 +00001812 /* broadcast it to this connection */
1813
Peter Hinz56885f32011-03-02 22:03:47 +00001814 new_wsi->protocol->callback(context, new_wsi,
Andy Green8f037e42010-12-19 22:13:26 +00001815 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00001816 new_wsi->user_space,
Andy Green0ca6a172010-12-19 20:50:01 +00001817 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
Andy Greenb45993c2010-12-18 15:13:50 +00001818 }
Andy Green0d338332011-02-12 11:57:43 +00001819 }
1820 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001821
Andy Greenbe93fef2011-02-14 20:25:43 +00001822 case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
1823
1824 /* handle proxy hung up on us */
1825
1826 if (pollfd->revents & (POLLERR | POLLHUP)) {
1827
Andy Green43db0452013-01-10 19:50:35 +08001828 lwsl_warn("Proxy connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00001829 (void *)wsi, pollfd->fd);
1830
Peter Hinz56885f32011-03-02 22:03:47 +00001831 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001832 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001833 return 1;
1834 }
1835
Andy Green72c34322011-04-16 10:46:21 +01001836 n = recv(wsi->sock, pkt, sizeof pkt, 0);
Andy Greenbe93fef2011-02-14 20:25:43 +00001837 if (n < 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001838 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001839 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001840 lwsl_err("ERROR reading from proxy socket\n");
Andy Greenbe93fef2011-02-14 20:25:43 +00001841 return 1;
1842 }
1843
1844 pkt[13] = '\0';
1845 if (strcmp(pkt, "HTTP/1.0 200 ") != 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001846 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001847 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001848 lwsl_err("ERROR from proxy: %s\n", pkt);
Andy Greenbe93fef2011-02-14 20:25:43 +00001849 return 1;
1850 }
1851
1852 /* clear his proxy connection timeout */
1853
1854 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1855
1856 /* fallthru */
1857
1858 case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
1859
1860 #ifdef LWS_OPENSSL_SUPPORT
Ken Atherton8360a472012-05-03 11:45:04 +08001861 if (wsi->use_ssl && !wsi->ssl) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001862
Peter Hinz56885f32011-03-02 22:03:47 +00001863 wsi->ssl = SSL_new(context->ssl_client_ctx);
1864 wsi->client_bio = BIO_new_socket(wsi->sock,
1865 BIO_NOCLOSE);
Andy Greenbe93fef2011-02-14 20:25:43 +00001866 SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
1867
Andy Green6901cb32011-02-21 08:06:47 +00001868 SSL_set_ex_data(wsi->ssl,
Andy Green2e24da02011-03-05 16:12:04 +00001869 openssl_websocket_private_data_index,
Peter Hinz56885f32011-03-02 22:03:47 +00001870 context);
Ken Atherton8360a472012-05-03 11:45:04 +08001871 }
Andy Green6901cb32011-02-21 08:06:47 +00001872
Ken Atherton8360a472012-05-03 11:45:04 +08001873 if (wsi->use_ssl) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001874 if (SSL_connect(wsi->ssl) <= 0) {
Ken Atherton8360a472012-05-03 11:45:04 +08001875
1876 /*
1877 * retry if new data comes until we
1878 * run into the connection timeout or win
1879 */
1880
Andy Green43db0452013-01-10 19:50:35 +08001881 lwsl_err("SSL connect error %s\n",
Andy Green687b0182011-02-26 11:04:01 +00001882 ERR_error_string(ERR_get_error(),
1883 ssl_err_buf));
Ken Atherton8360a472012-05-03 11:45:04 +08001884 return 0;
Andy Greenbe93fef2011-02-14 20:25:43 +00001885 }
1886
1887 n = SSL_get_verify_result(wsi->ssl);
Andy Green2e24da02011-03-05 16:12:04 +00001888 if ((n != X509_V_OK) && (
Andy Green687b0182011-02-26 11:04:01 +00001889 n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
1890 wsi->use_ssl != 2)) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001891
Andy Green43db0452013-01-10 19:50:35 +08001892 lwsl_err("server's cert didn't "
Andy Green687b0182011-02-26 11:04:01 +00001893 "look good %d\n", n);
Peter Hinz56885f32011-03-02 22:03:47 +00001894 libwebsocket_close_and_free_session(context,
1895 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Green687b0182011-02-26 11:04:01 +00001896 return 1;
Andy Greenbe93fef2011-02-14 20:25:43 +00001897 }
Ken Atherton8360a472012-05-03 11:45:04 +08001898 } else
Andy Greenbe93fef2011-02-14 20:25:43 +00001899 wsi->ssl = NULL;
1900 #endif
1901
Andy Greena41314f2011-05-23 10:00:03 +01001902 p = libwebsockets_generate_client_handshake(context, wsi, p);
Andy Green6ee372f2012-04-09 15:09:01 +08001903 if (p == NULL)
Andy Greenbe93fef2011-02-14 20:25:43 +00001904 return 1;
Andy Greeneeaacb32011-03-01 20:44:24 +00001905
Andy Greenbe93fef2011-02-14 20:25:43 +00001906 /* send our request to the server */
1907
1908 #ifdef LWS_OPENSSL_SUPPORT
1909 if (wsi->use_ssl)
1910 n = SSL_write(wsi->ssl, pkt, p - pkt);
1911 else
1912 #endif
1913 n = send(wsi->sock, pkt, p - pkt, 0);
1914
1915 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001916 lwsl_debug("ERROR writing to client socket\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001917 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001918 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001919 return 1;
1920 }
1921
1922 wsi->parser_state = WSI_TOKEN_NAME_PART;
1923 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
1924 libwebsocket_set_timeout(wsi,
David Galeanoc9f1ff82013-01-09 18:01:23 +08001925 PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, AWAITING_TIMEOUT);
Andy Greenbe93fef2011-02-14 20:25:43 +00001926
1927 break;
1928
1929 case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
1930
1931 /* handle server hung up on us */
1932
1933 if (pollfd->revents & (POLLERR | POLLHUP)) {
1934
Andy Green43db0452013-01-10 19:50:35 +08001935 lwsl_debug("Server connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00001936 (void *)wsi, pollfd->fd);
1937
1938 goto bail3;
1939 }
1940
1941
1942 /* interpret the server response */
1943
1944 /*
1945 * HTTP/1.1 101 Switching Protocols
1946 * Upgrade: websocket
1947 * Connection: Upgrade
1948 * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
1949 * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
1950 * Sec-WebSocket-Protocol: chat
1951 */
1952
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001953 /*
1954 * we have to take some care here to only take from the
1955 * socket bytewise. The browser may (and has been seen to
1956 * in the case that onopen() performs websocket traffic)
1957 * coalesce both handshake response and websocket traffic
1958 * in one packet, since at that point the connection is
1959 * definitively ready from browser pov.
1960 */
Andy Greenbe93fef2011-02-14 20:25:43 +00001961
Andy Green7b5af9a2012-04-09 15:23:47 +08001962 len = 1;
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001963 while (wsi->parser_state != WSI_PARSING_COMPLETE && len > 0) {
1964#ifdef LWS_OPENSSL_SUPPORT
1965 if (wsi->use_ssl)
1966 len = SSL_read(wsi->ssl, &c, 1);
1967 else
1968#endif
1969 len = recv(wsi->sock, &c, 1, 0);
1970
1971 libwebsocket_parse(wsi, c);
Andy Greenbe93fef2011-02-14 20:25:43 +00001972 }
1973
Andy Green27a0b912011-04-16 10:54:28 +01001974 /*
Andy Green6ee372f2012-04-09 15:09:01 +08001975 * hs may also be coming in multiple packets, there is a 5-sec
Andy Green27a0b912011-04-16 10:54:28 +01001976 * libwebsocket timeout still active here too, so if parsing did
1977 * not complete just wait for next packet coming in this state
1978 */
1979
1980 if (wsi->parser_state != WSI_PARSING_COMPLETE)
1981 break;
Andy Greenbe93fef2011-02-14 20:25:43 +00001982
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001983 /*
1984 * otherwise deal with the handshake. If there's any
1985 * packet traffic already arrived we'll trigger poll() again
1986 * right away and deal with it that way
1987 */
1988
Andy Greena41314f2011-05-23 10:00:03 +01001989 return lws_client_interpret_server_handshake(context, wsi);
Andy Greenbe93fef2011-02-14 20:25:43 +00001990
1991bail3:
1992 if (wsi->c_protocol)
1993 free(wsi->c_protocol);
Peter Hinz56885f32011-03-02 22:03:47 +00001994 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08001995 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001996 return 1;
Andy Greena41314f2011-05-23 10:00:03 +01001997
1998 case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
Andy Green43db0452013-01-10 19:50:35 +08001999 lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
Andy Greena41314f2011-05-23 10:00:03 +01002000 break;
2001
2002 case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
Andy Green43db0452013-01-10 19:50:35 +08002003 lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
Andy Greena41314f2011-05-23 10:00:03 +01002004 break;
2005
Andy Greenbe93fef2011-02-14 20:25:43 +00002006
Andy Green0d338332011-02-12 11:57:43 +00002007 case LWS_CONNMODE_WS_SERVING:
2008 case LWS_CONNMODE_WS_CLIENT:
2009
2010 /* handle session socket closed */
2011
2012 if (pollfd->revents & (POLLERR | POLLHUP)) {
2013
Andy Green43db0452013-01-10 19:50:35 +08002014 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Andy Green0d338332011-02-12 11:57:43 +00002015 (void *)wsi, pollfd->fd);
2016
Peter Hinz56885f32011-03-02 22:03:47 +00002017 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002018 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green4b6fbe12011-02-14 08:03:48 +00002019 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002020 }
2021
Andy Green0d338332011-02-12 11:57:43 +00002022 /* the guy requested a callback when it was OK to write */
2023
Andy Greenda527df2011-03-07 07:08:12 +00002024 if ((pollfd->revents & POLLOUT) &&
2025 wsi->state == WSI_STATE_ESTABLISHED)
2026 if (lws_handle_POLLOUT_event(context, wsi,
2027 pollfd) < 0) {
2028 libwebsocket_close_and_free_session(
2029 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00002030 return 1;
2031 }
Andy Green0d338332011-02-12 11:57:43 +00002032
Andy Green0d338332011-02-12 11:57:43 +00002033
2034 /* any incoming data ready? */
2035
2036 if (!(pollfd->revents & POLLIN))
2037 break;
2038
Andy Greenb45993c2010-12-18 15:13:50 +00002039#ifdef LWS_OPENSSL_SUPPORT
David Galeano7ffbe1b2013-01-10 10:35:32 +08002040read_pending:
Andy Green0d338332011-02-12 11:57:43 +00002041 if (wsi->ssl)
Andy Green98a717c2011-03-06 13:14:15 +00002042 eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);
Andy Greenb45993c2010-12-18 15:13:50 +00002043 else
2044#endif
Andy Green98a717c2011-03-06 13:14:15 +00002045 eff_buf.token_len =
Andy Green72c34322011-04-16 10:46:21 +01002046 recv(pollfd->fd, buf, sizeof buf, 0);
Andy Greenb45993c2010-12-18 15:13:50 +00002047
Andy Green98a717c2011-03-06 13:14:15 +00002048 if (eff_buf.token_len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002049 lwsl_debug("Socket read returned %d\n",
Andy Green98a717c2011-03-06 13:14:15 +00002050 eff_buf.token_len);
Alon Levydc93b7f2012-10-19 11:21:57 +02002051 if (errno != EINTR && errno != EAGAIN)
Andy Green6ee372f2012-04-09 15:09:01 +08002052 libwebsocket_close_and_free_session(context,
2053 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Nick Dowellc04c1932012-04-05 10:29:39 +08002054 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002055 }
Andy Green98a717c2011-03-06 13:14:15 +00002056 if (!eff_buf.token_len) {
Peter Hinz56885f32011-03-02 22:03:47 +00002057 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002058 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenfa3f4052012-10-07 20:40:35 +08002059 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00002060 }
2061
Andy Green98a717c2011-03-06 13:14:15 +00002062 /*
2063 * give any active extensions a chance to munge the buffer
2064 * before parse. We pass in a pointer to an lws_tokens struct
2065 * prepared with the default buffer and content length that's in
2066 * there. Rather than rewrite the default buffer, extensions
2067 * that expect to grow the buffer can adapt .token to
2068 * point to their own per-connection buffer in the extension
2069 * user allocation. By default with no extensions or no
2070 * extension callback handling, just the normal input buffer is
2071 * used then so it is efficient.
2072 */
Andy Greenb45993c2010-12-18 15:13:50 +00002073
Andy Green98a717c2011-03-06 13:14:15 +00002074 eff_buf.token = (char *)buf;
Andy Greenb45993c2010-12-18 15:13:50 +00002075
Andy Green98a717c2011-03-06 13:14:15 +00002076 more = 1;
2077 while (more) {
Andy Green0d338332011-02-12 11:57:43 +00002078
Andy Green98a717c2011-03-06 13:14:15 +00002079 more = 0;
2080
2081 for (n = 0; n < wsi->count_active_extensions; n++) {
Andy Green46c2ea02011-03-22 09:04:01 +00002082 m = wsi->active_extensions[n]->callback(context,
2083 wsi->active_extensions[n], wsi,
Andy Green98a717c2011-03-06 13:14:15 +00002084 LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
Andy Green46c2ea02011-03-22 09:04:01 +00002085 wsi->active_extensions_user[n],
2086 &eff_buf, 0);
Andy Green98a717c2011-03-06 13:14:15 +00002087 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002088 lwsl_ext(
Andy Green6ee372f2012-04-09 15:09:01 +08002089 "Extension reports fatal error\n");
2090 libwebsocket_close_and_free_session(
2091 context, wsi,
2092 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green98a717c2011-03-06 13:14:15 +00002093 return 1;
2094 }
2095 if (m)
2096 more = 1;
2097 }
2098
2099 /* service incoming data */
2100
2101 if (eff_buf.token_len) {
2102 n = libwebsocket_read(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002103 (unsigned char *)eff_buf.token,
2104 eff_buf.token_len);
Andy Green98a717c2011-03-06 13:14:15 +00002105 if (n < 0)
2106 /* we closed wsi */
2107 return 1;
2108 }
2109
2110 eff_buf.token = NULL;
2111 eff_buf.token_len = 0;
2112 }
David Galeano7ffbe1b2013-01-10 10:35:32 +08002113
2114#ifdef LWS_OPENSSL_SUPPORT
2115 if (wsi->ssl && SSL_pending(wsi->ssl))
2116 goto read_pending;
2117#endif
Andy Green98a717c2011-03-06 13:14:15 +00002118 break;
Andy Greenb45993c2010-12-18 15:13:50 +00002119 }
2120
2121 return 0;
2122}
2123
Andy Green0d338332011-02-12 11:57:43 +00002124
Andy Green6964bb52011-01-23 16:50:33 +00002125/**
2126 * libwebsocket_context_destroy() - Destroy the websocket context
Peter Hinz56885f32011-03-02 22:03:47 +00002127 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002128 *
2129 * This function closes any active connections and then frees the
2130 * context. After calling this, any further use of the context is
2131 * undefined.
2132 */
2133void
Peter Hinz56885f32011-03-02 22:03:47 +00002134libwebsocket_context_destroy(struct libwebsocket_context *context)
Andy Green6964bb52011-01-23 16:50:33 +00002135{
Andy Green0d338332011-02-12 11:57:43 +00002136 int n;
2137 int m;
2138 struct libwebsocket *wsi;
Andy Greena41314f2011-05-23 10:00:03 +01002139 struct libwebsocket_extension *ext;
Andy Green6964bb52011-01-23 16:50:33 +00002140
Andy Green4b6fbe12011-02-14 08:03:48 +00002141 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002142 for (m = 0; m < context->fd_hashtable[n].length; m++) {
2143 wsi = context->fd_hashtable[n].wsi[m];
2144 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002145 LWS_CLOSE_STATUS_GOINGAWAY);
Andy Greenf3d3b402011-02-09 07:16:34 +00002146 }
Andy Green6964bb52011-01-23 16:50:33 +00002147
Andy Greena41314f2011-05-23 10:00:03 +01002148 /*
2149 * give all extensions a chance to clean up any per-context
2150 * allocations they might have made
2151 */
2152
2153 ext = context->extensions;
2154 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
2155 if (context->listen_port)
2156 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
Paulo Roberto Urio1f680ab2012-06-04 08:40:28 +08002157 while (ext && ext->callback) {
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002158 ext->callback(context, ext, NULL, (enum libwebsocket_extension_callback_reasons)m, NULL, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01002159 ext++;
2160 }
2161
Peter Hinz56885f32011-03-02 22:03:47 +00002162#ifdef WIN32
2163#else
2164 close(context->fd_random);
Andy Green6964bb52011-01-23 16:50:33 +00002165#endif
2166
Peter Hinz56885f32011-03-02 22:03:47 +00002167#ifdef LWS_OPENSSL_SUPPORT
2168 if (context->ssl_ctx)
2169 SSL_CTX_free(context->ssl_ctx);
2170 if (context->ssl_client_ctx)
2171 SSL_CTX_free(context->ssl_client_ctx);
2172#endif
2173
2174 free(context);
2175
2176#ifdef WIN32
2177 WSACleanup();
2178#endif
Andy Green6964bb52011-01-23 16:50:33 +00002179}
2180
Alon Levy0291eb32012-10-19 11:21:56 +02002181LWS_EXTERN void *
2182libwebsocket_context_user(struct libwebsocket_context *context)
2183{
2184 return context->user_space;
2185}
2186
Andy Green6964bb52011-01-23 16:50:33 +00002187/**
2188 * libwebsocket_service() - Service any pending websocket activity
Peter Hinz56885f32011-03-02 22:03:47 +00002189 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002190 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
2191 * service otherwise block and service immediately, returning
2192 * after the timeout if nothing needed service.
2193 *
2194 * This function deals with any pending websocket traffic, for three
2195 * kinds of event. It handles these events on both server and client
2196 * types of connection the same.
2197 *
2198 * 1) Accept new connections to our context's server
2199 *
2200 * 2) Perform pending broadcast writes initiated from other forked
2201 * processes (effectively serializing asynchronous broadcasts)
2202 *
2203 * 3) Call the receive callback for incoming frame data received by
2204 * server or client connections.
2205 *
2206 * You need to call this service function periodically to all the above
2207 * functions to happen; if your application is single-threaded you can
2208 * just call it in your main event loop.
2209 *
2210 * Alternatively you can fork a new process that asynchronously handles
2211 * calling this service in a loop. In that case you are happy if this
2212 * call blocks your thread until it needs to take care of something and
2213 * would call it with a large nonzero timeout. Your loop then takes no
2214 * CPU while there is nothing happening.
2215 *
2216 * If you are calling it in a single-threaded app, you don't want it to
2217 * wait around blocking other things in your loop from happening, so you
2218 * would call it with a timeout_ms of 0, so it returns immediately if
2219 * nothing is pending, or as soon as it services whatever was pending.
2220 */
2221
Andy Greenb45993c2010-12-18 15:13:50 +00002222
Andy Greene92cd172011-01-19 13:11:55 +00002223int
Peter Hinz56885f32011-03-02 22:03:47 +00002224libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
Andy Greene92cd172011-01-19 13:11:55 +00002225{
2226 int n;
Andy Greene92cd172011-01-19 13:11:55 +00002227
2228 /* stay dead once we are dead */
2229
Peter Hinz56885f32011-03-02 22:03:47 +00002230 if (context == NULL)
Andy Greene92cd172011-01-19 13:11:55 +00002231 return 1;
2232
Andy Green0d338332011-02-12 11:57:43 +00002233 /* wait for something to need service */
Andy Green4739e5c2011-01-22 12:51:57 +00002234
Peter Hinz56885f32011-03-02 22:03:47 +00002235 n = poll(context->fds, context->fds_count, timeout_ms);
Andy Green3221f922011-02-12 13:14:11 +00002236 if (n == 0) /* poll timeout */
2237 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002238
Andy Green62c54d22011-02-14 09:14:25 +00002239 if (n < 0) {
Andy Green5e1fa172011-02-10 09:07:05 +00002240 /*
Andy Green43db0452013-01-10 19:50:35 +08002241 lwsl_err("Listen Socket dead\n");
Andy Green5e1fa172011-02-10 09:07:05 +00002242 */
Andy Green3928f612012-07-20 12:58:38 +08002243 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002244 }
Andy Greene92cd172011-01-19 13:11:55 +00002245
2246 /* handle accept on listening socket? */
2247
Peter Hinz56885f32011-03-02 22:03:47 +00002248 for (n = 0; n < context->fds_count; n++)
2249 if (context->fds[n].revents)
Andy Green3928f612012-07-20 12:58:38 +08002250 if (libwebsocket_service_fd(context,
2251 &context->fds[n]) < 0)
2252 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002253 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002254}
2255
Andy Greena41314f2011-05-23 10:00:03 +01002256int
2257lws_any_extension_handled(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002258 struct libwebsocket *wsi,
2259 enum libwebsocket_extension_callback_reasons r,
Andy Greena41314f2011-05-23 10:00:03 +01002260 void *v, size_t len)
2261{
2262 int n;
2263 int handled = 0;
2264
2265 /* maybe an extension will take care of it for us */
2266
2267 for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
2268 if (!wsi->active_extensions[n]->callback)
2269 continue;
2270
2271 handled |= wsi->active_extensions[n]->callback(context,
2272 wsi->active_extensions[n], wsi,
2273 r, wsi->active_extensions_user[n], v, len);
2274 }
2275
2276 return handled;
2277}
2278
2279
2280void *
2281lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002282 struct libwebsocket_extension *ext)
Andy Greena41314f2011-05-23 10:00:03 +01002283{
2284 int n = 0;
2285
Andy Green68b45042011-05-25 21:41:57 +01002286 if (wsi == NULL)
2287 return NULL;
2288
Andy Greena41314f2011-05-23 10:00:03 +01002289 while (n < wsi->count_active_extensions) {
2290 if (wsi->active_extensions[n] != ext) {
2291 n++;
2292 continue;
2293 }
2294 return wsi->active_extensions_user[n];
2295 }
2296
2297 return NULL;
2298}
2299
Andy Green90c7cbc2011-01-27 06:26:52 +00002300/**
2301 * libwebsocket_callback_on_writable() - Request a callback when this socket
2302 * becomes able to be written to without
2303 * blocking
Andy Green32375b72011-02-19 08:32:53 +00002304 *
Peter Hinz56885f32011-03-02 22:03:47 +00002305 * @context: libwebsockets context
Andy Green90c7cbc2011-01-27 06:26:52 +00002306 * @wsi: Websocket connection instance to get callback for
2307 */
2308
2309int
Peter Hinz56885f32011-03-02 22:03:47 +00002310libwebsocket_callback_on_writable(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002311 struct libwebsocket *wsi)
Andy Green90c7cbc2011-01-27 06:26:52 +00002312{
Andy Green90c7cbc2011-01-27 06:26:52 +00002313 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002314 int handled = 0;
2315
2316 /* maybe an extension will take care of it for us */
2317
2318 for (n = 0; n < wsi->count_active_extensions; n++) {
2319 if (!wsi->active_extensions[n]->callback)
2320 continue;
2321
2322 handled |= wsi->active_extensions[n]->callback(context,
2323 wsi->active_extensions[n], wsi,
2324 LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
2325 wsi->active_extensions_user[n], NULL, 0);
2326 }
2327
2328 if (handled)
2329 return 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002330
Peter Hinz56885f32011-03-02 22:03:47 +00002331 for (n = 0; n < context->fds_count; n++)
2332 if (context->fds[n].fd == wsi->sock) {
2333 context->fds[n].events |= POLLOUT;
Andy Greena41314f2011-05-23 10:00:03 +01002334 n = context->fds_count + 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002335 }
2336
Andy Greena41314f2011-05-23 10:00:03 +01002337 if (n == context->fds_count)
Andy Green43db0452013-01-10 19:50:35 +08002338 lwsl_err("libwebsocket_callback_on_writable: "
Andy Green6ee372f2012-04-09 15:09:01 +08002339 "failed to find socket %d\n", wsi->sock);
Andy Greena41314f2011-05-23 10:00:03 +01002340
Andy Green3221f922011-02-12 13:14:11 +00002341 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002342 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002343 LWS_CALLBACK_SET_MODE_POLL_FD,
2344 (void *)(long)wsi->sock, NULL, POLLOUT);
2345
Andy Green90c7cbc2011-01-27 06:26:52 +00002346 return 1;
2347}
2348
2349/**
2350 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
2351 * all connections using the given protocol when it
2352 * becomes possible to write to each socket without
2353 * blocking in turn.
2354 *
2355 * @protocol: Protocol whose connections will get callbacks
2356 */
2357
2358int
2359libwebsocket_callback_on_writable_all_protocol(
2360 const struct libwebsocket_protocols *protocol)
2361{
Peter Hinz56885f32011-03-02 22:03:47 +00002362 struct libwebsocket_context *context = protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002363 int n;
Andy Green0d338332011-02-12 11:57:43 +00002364 int m;
2365 struct libwebsocket *wsi;
Andy Green90c7cbc2011-01-27 06:26:52 +00002366
Andy Green0d338332011-02-12 11:57:43 +00002367 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
2368
Peter Hinz56885f32011-03-02 22:03:47 +00002369 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Green0d338332011-02-12 11:57:43 +00002370
Peter Hinz56885f32011-03-02 22:03:47 +00002371 wsi = context->fd_hashtable[n].wsi[m];
Andy Green0d338332011-02-12 11:57:43 +00002372
2373 if (wsi->protocol == protocol)
Peter Hinz56885f32011-03-02 22:03:47 +00002374 libwebsocket_callback_on_writable(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002375 }
2376 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002377
2378 return 0;
2379}
2380
Andy Greenbe93fef2011-02-14 20:25:43 +00002381/**
2382 * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
2383 *
2384 * You will not need this unless you are doing something special
2385 *
2386 * @wsi: Websocket connection instance
2387 * @reason: timeout reason
2388 * @secs: how many seconds
2389 */
2390
2391void
2392libwebsocket_set_timeout(struct libwebsocket *wsi,
2393 enum pending_timeout reason, int secs)
2394{
2395 struct timeval tv;
2396
2397 gettimeofday(&tv, NULL);
2398
2399 wsi->pending_timeout_limit = tv.tv_sec + secs;
2400 wsi->pending_timeout = reason;
2401}
2402
Andy Greena6cbece2011-01-27 20:06:03 +00002403
2404/**
2405 * libwebsocket_get_socket_fd() - returns the socket file descriptor
2406 *
2407 * You will not need this unless you are doing something special
2408 *
2409 * @wsi: Websocket connection instance
2410 */
2411
2412int
2413libwebsocket_get_socket_fd(struct libwebsocket *wsi)
2414{
2415 return wsi->sock;
2416}
2417
Andy Green90c7cbc2011-01-27 06:26:52 +00002418/**
2419 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
2420 * receieved packets.
2421 *
2422 * If the output side of a server process becomes choked, this allows flow
2423 * control for the input side.
2424 *
2425 * @wsi: Websocket connection instance to get callback for
2426 * @enable: 0 = disable read servicing for this connection, 1 = enable
2427 */
2428
2429int
2430libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
2431{
Peter Hinz56885f32011-03-02 22:03:47 +00002432 struct libwebsocket_context *context = wsi->protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002433 int n;
2434
Peter Hinz56885f32011-03-02 22:03:47 +00002435 for (n = 0; n < context->fds_count; n++)
2436 if (context->fds[n].fd == wsi->sock) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002437 if (enable)
Peter Hinz56885f32011-03-02 22:03:47 +00002438 context->fds[n].events |= POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002439 else
Peter Hinz56885f32011-03-02 22:03:47 +00002440 context->fds[n].events &= ~POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002441
2442 return 0;
2443 }
2444
Andy Green3221f922011-02-12 13:14:11 +00002445 if (enable)
2446 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002447 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002448 LWS_CALLBACK_SET_MODE_POLL_FD,
2449 (void *)(long)wsi->sock, NULL, POLLIN);
2450 else
2451 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002452 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002453 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
2454 (void *)(long)wsi->sock, NULL, POLLIN);
2455
Andy Greena41314f2011-05-23 10:00:03 +01002456#if 0
Andy Green43db0452013-01-10 19:50:35 +08002457 lwsl_err("libwebsocket_rx_flow_control unable to find socket\n");
Andy Greena41314f2011-05-23 10:00:03 +01002458#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002459 return 1;
2460}
2461
Andy Green2ac5a6f2011-01-28 10:00:18 +00002462/**
2463 * libwebsocket_canonical_hostname() - returns this host's hostname
2464 *
2465 * This is typically used by client code to fill in the host parameter
2466 * when making a client connection. You can only call it after the context
2467 * has been created.
2468 *
Peter Hinz56885f32011-03-02 22:03:47 +00002469 * @context: Websocket context
Andy Green2ac5a6f2011-01-28 10:00:18 +00002470 */
2471
2472
2473extern const char *
Peter Hinz56885f32011-03-02 22:03:47 +00002474libwebsocket_canonical_hostname(struct libwebsocket_context *context)
Andy Green2ac5a6f2011-01-28 10:00:18 +00002475{
Peter Hinz56885f32011-03-02 22:03:47 +00002476 return (const char *)context->canonical_hostname;
Andy Green2ac5a6f2011-01-28 10:00:18 +00002477}
2478
2479
Andy Green90c7cbc2011-01-27 06:26:52 +00002480static void sigpipe_handler(int x)
2481{
2482}
2483
Andy Green6901cb32011-02-21 08:06:47 +00002484#ifdef LWS_OPENSSL_SUPPORT
2485static int
2486OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
2487{
2488
2489 SSL *ssl;
2490 int n;
Andy Green2e24da02011-03-05 16:12:04 +00002491 struct libwebsocket_context *context;
Andy Green6901cb32011-02-21 08:06:47 +00002492
2493 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
2494 SSL_get_ex_data_X509_STORE_CTX_idx());
2495
2496 /*
Andy Green2e24da02011-03-05 16:12:04 +00002497 * !!! nasty openssl requires the index to come as a library-scope
2498 * static
Andy Green6901cb32011-02-21 08:06:47 +00002499 */
Andy Green2e24da02011-03-05 16:12:04 +00002500 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
Andy Green6ee372f2012-04-09 15:09:01 +08002501
Peter Hinz56885f32011-03-02 22:03:47 +00002502 n = context->protocols[0].callback(NULL, NULL,
Andy Green6901cb32011-02-21 08:06:47 +00002503 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
2504 x509_ctx, ssl, preverify_ok);
2505
2506 /* convert return code from 0 = OK to 1 = OK */
2507
2508 if (!n)
2509 n = 1;
2510 else
2511 n = 0;
2512
2513 return n;
2514}
2515#endif
2516
Andy Greenb45993c2010-12-18 15:13:50 +00002517
Andy Greenab990e42010-10-31 12:42:52 +00002518/**
Andy Green4739e5c2011-01-22 12:51:57 +00002519 * libwebsocket_create_context() - Create the websocket handler
2520 * @port: Port to listen on... you can use 0 to suppress listening on
Andy Green6964bb52011-01-23 16:50:33 +00002521 * any port, that's what you want if you are not running a
2522 * websocket server at all but just using it as a client
Peter Hinz56885f32011-03-02 22:03:47 +00002523 * @interf: NULL to bind the listen socket to all interfaces, or the
Andy Green32375b72011-02-19 08:32:53 +00002524 * interface name, eg, "eth2"
Andy Green4f3943a2010-11-12 10:44:16 +00002525 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +00002526 * specific callback for each one. The list is ended with an
2527 * entry that has a NULL callback pointer.
Andy Green6964bb52011-01-23 16:50:33 +00002528 * It's not const because we write the owning_server member
Andy Greenc5114822011-03-06 10:29:35 +00002529 * @extensions: NULL or array of libwebsocket_extension structs listing the
Andy Green6ee372f2012-04-09 15:09:01 +08002530 * extensions this context supports
Andy Green3faa9c72010-11-08 17:03:03 +00002531 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +00002532 * to listen using SSL, set to the filepath to fetch the
2533 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +00002534 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +00002535 * else ignored
David Galeano2f82be82013-01-09 16:25:54 +08002536 * @ssl_ca_filepath: CA certificate filepath or NULL
Andy Green3faa9c72010-11-08 17:03:03 +00002537 * @gid: group id to change to after setting listen socket, or -1.
2538 * @uid: user id to change to after setting listen socket, or -1.
Andy Greenbfb051f2011-02-09 08:49:14 +00002539 * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
Andy Green15e31f32012-10-19 18:36:28 +08002540 * @user: optional user pointer that can be recovered via the context
2541 * pointer using libwebsocket_context_user
Andy Green05464c62010-11-12 10:44:18 +00002542 *
Andy Green8f037e42010-12-19 22:13:26 +00002543 * This function creates the listening socket and takes care
2544 * of all initialization in one step.
2545 *
Andy Greene92cd172011-01-19 13:11:55 +00002546 * After initialization, it returns a struct libwebsocket_context * that
2547 * represents this server. After calling, user code needs to take care
2548 * of calling libwebsocket_service() with the context pointer to get the
2549 * server's sockets serviced. This can be done in the same process context
2550 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +00002551 *
Andy Green8f037e42010-12-19 22:13:26 +00002552 * The protocol callback functions are called for a handful of events
2553 * including http requests coming in, websocket connections becoming
2554 * established, and data arriving; it's also called periodically to allow
2555 * async transmission.
2556 *
2557 * HTTP requests are sent always to the FIRST protocol in @protocol, since
2558 * at that time websocket protocol has not been negotiated. Other
2559 * protocols after the first one never see any HTTP callack activity.
2560 *
2561 * The server created is a simple http server by default; part of the
2562 * websocket standard is upgrading this http connection to a websocket one.
2563 *
2564 * This allows the same server to provide files like scripts and favicon /
2565 * images or whatever over http and dynamic data over websockets all in
2566 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +00002567 */
Andy Green4ea60062010-10-30 12:15:07 +01002568
Andy Greene92cd172011-01-19 13:11:55 +00002569struct libwebsocket_context *
Peter Hinz56885f32011-03-02 22:03:47 +00002570libwebsocket_create_context(int port, const char *interf,
Andy Greenb45993c2010-12-18 15:13:50 +00002571 struct libwebsocket_protocols *protocols,
Andy Greend6e09112011-03-05 16:12:15 +00002572 struct libwebsocket_extension *extensions,
Andy Green8f037e42010-12-19 22:13:26 +00002573 const char *ssl_cert_filepath,
2574 const char *ssl_private_key_filepath,
David Galeano2f82be82013-01-09 16:25:54 +08002575 const char *ssl_ca_filepath,
Alon Levy0291eb32012-10-19 11:21:56 +02002576 int gid, int uid, unsigned int options,
David Galeano2f82be82013-01-09 16:25:54 +08002577 void *user)
Andy Greenff95d7a2010-10-28 22:36:01 +01002578{
2579 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002580 int m;
Andy Green4739e5c2011-01-22 12:51:57 +00002581 int sockfd = 0;
Andy Green251f6fa2010-11-03 11:13:06 +00002582 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +01002583 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +00002584 int opt = 1;
Peter Hinz56885f32011-03-02 22:03:47 +00002585 struct libwebsocket_context *context = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002586 unsigned int slen;
Andy Green9659f372011-01-27 22:01:43 +00002587 char *p;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002588 char hostname[1024] = "";
Andy Greena69f0512012-05-03 12:32:38 +08002589// struct hostent *he;
Andy Green0d338332011-02-12 11:57:43 +00002590 struct libwebsocket *wsi;
Andy Greena69f0512012-05-03 12:32:38 +08002591 struct sockaddr sa;
Andy Greenff95d7a2010-10-28 22:36:01 +01002592
Andy Green3faa9c72010-11-08 17:03:03 +00002593#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +00002594 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +00002595 char ssl_err_buf[512];
Andy Green3faa9c72010-11-08 17:03:03 +00002596#endif
2597
Andy Green43db0452013-01-10 19:50:35 +08002598 lwsl_info("Initial logging level %d\n", log_level);
2599
Peter Hinz56885f32011-03-02 22:03:47 +00002600#ifdef _WIN32
2601 {
2602 WORD wVersionRequested;
2603 WSADATA wsaData;
2604 int err;
Andy Green6ee372f2012-04-09 15:09:01 +08002605 HMODULE wsdll;
Peter Hinz56885f32011-03-02 22:03:47 +00002606
2607 /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
2608 wVersionRequested = MAKEWORD(2, 2);
2609
2610 err = WSAStartup(wVersionRequested, &wsaData);
2611 if (err != 0) {
2612 /* Tell the user that we could not find a usable */
2613 /* Winsock DLL. */
Andy Green43db0452013-01-10 19:50:35 +08002614 lwsl_err("WSAStartup failed with error: %d\n", err);
Peter Hinz56885f32011-03-02 22:03:47 +00002615 return NULL;
2616 }
David Galeano7b11fec2011-10-04 19:55:18 +08002617
Andy Green6ee372f2012-04-09 15:09:01 +08002618 /* default to a poll() made out of select() */
2619 poll = emulated_poll;
David Galeano7b11fec2011-10-04 19:55:18 +08002620
Andy Green6ee372f2012-04-09 15:09:01 +08002621 /* if windows socket lib available, use his WSAPoll */
David Galeanocb193682013-01-09 15:29:00 +08002622 wsdll = GetModuleHandle(_T("Ws2_32.dll"));
Andy Green6ee372f2012-04-09 15:09:01 +08002623 if (wsdll)
2624 poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
Peter Hinz56885f32011-03-02 22:03:47 +00002625 }
2626#endif
2627
2628
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002629 context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context));
Peter Hinz56885f32011-03-02 22:03:47 +00002630 if (!context) {
Andy Green43db0452013-01-10 19:50:35 +08002631 lwsl_err("No memory for websocket context\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002632 return NULL;
2633 }
Peter Hinz56885f32011-03-02 22:03:47 +00002634 context->protocols = protocols;
2635 context->listen_port = port;
2636 context->http_proxy_port = 0;
2637 context->http_proxy_address[0] = '\0';
2638 context->options = options;
2639 context->fds_count = 0;
Andy Greend6e09112011-03-05 16:12:15 +00002640 context->extensions = extensions;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002641 context->last_timeout_check_s = 0;
Alon Levy0291eb32012-10-19 11:21:56 +02002642 context->user_space = user;
Andy Green9659f372011-01-27 22:01:43 +00002643
Peter Hinz56885f32011-03-02 22:03:47 +00002644#ifdef WIN32
2645 context->fd_random = 0;
2646#else
2647 context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
2648 if (context->fd_random < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002649 lwsl_err("Unable to open random device %s %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002650 SYSTEM_RANDOM_FILEPATH, context->fd_random);
Andy Green44eee682011-02-10 09:32:24 +00002651 return NULL;
2652 }
Peter Hinz56885f32011-03-02 22:03:47 +00002653#endif
Andy Green44eee682011-02-10 09:32:24 +00002654
Peter Hinz56885f32011-03-02 22:03:47 +00002655#ifdef LWS_OPENSSL_SUPPORT
2656 context->use_ssl = 0;
2657 context->ssl_ctx = NULL;
2658 context->ssl_client_ctx = NULL;
Andy Green2e24da02011-03-05 16:12:04 +00002659 openssl_websocket_private_data_index = 0;
Peter Hinz56885f32011-03-02 22:03:47 +00002660#endif
Andy Green2ac5a6f2011-01-28 10:00:18 +00002661
Andy Green788c4a82012-10-22 12:29:57 +01002662 if (options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME) {
Andy Greena69f0512012-05-03 12:32:38 +08002663
Andy Green788c4a82012-10-22 12:29:57 +01002664 strcpy(context->canonical_hostname, "unknown");
Andy Greena69f0512012-05-03 12:32:38 +08002665
Andy Green788c4a82012-10-22 12:29:57 +01002666 } else {
2667
2668 /* find canonical hostname */
2669
2670 hostname[(sizeof hostname) - 1] = '\0';
2671 memset(&sa, 0, sizeof(sa));
2672 sa.sa_family = AF_INET;
2673 sa.sa_data[(sizeof sa.sa_data) - 1] = '\0';
2674 gethostname(hostname, (sizeof hostname) - 1);
2675
2676 n = 0;
2677
David Galeanoed3c8402013-01-10 10:45:24 +08002678 if (strlen(hostname) < sizeof(sa.sa_data) - 1) {
Andy Green788c4a82012-10-22 12:29:57 +01002679 strcpy(sa.sa_data, hostname);
Andy Green43db0452013-01-10 19:50:35 +08002680 // lwsl_debug("my host name is %s\n", sa.sa_data);
Andy Green788c4a82012-10-22 12:29:57 +01002681 n = getnameinfo(&sa, sizeof(sa), hostname,
2682 (sizeof hostname) - 1, NULL, 0, 0);
2683 }
2684
2685 if (!n) {
2686 strncpy(context->canonical_hostname, hostname,
2687 sizeof context->canonical_hostname - 1);
2688 context->canonical_hostname[
2689 sizeof context->canonical_hostname - 1] = '\0';
2690 } else
2691 strncpy(context->canonical_hostname, hostname,
2692 sizeof context->canonical_hostname - 1);
2693
Andy Green43db0452013-01-10 19:50:35 +08002694 // lwsl_debug("context->canonical_hostname = %s\n",
Andy Green788c4a82012-10-22 12:29:57 +01002695 // context->canonical_hostname);
Andy Greena69f0512012-05-03 12:32:38 +08002696 }
2697
Andy Green9659f372011-01-27 22:01:43 +00002698 /* split the proxy ads:port if given */
2699
2700 p = getenv("http_proxy");
2701 if (p) {
Peter Hinz56885f32011-03-02 22:03:47 +00002702 strncpy(context->http_proxy_address, p,
Andy Green6ee372f2012-04-09 15:09:01 +08002703 sizeof context->http_proxy_address - 1);
Peter Hinz56885f32011-03-02 22:03:47 +00002704 context->http_proxy_address[
2705 sizeof context->http_proxy_address - 1] = '\0';
Andy Green9659f372011-01-27 22:01:43 +00002706
Peter Hinz56885f32011-03-02 22:03:47 +00002707 p = strchr(context->http_proxy_address, ':');
Andy Green9659f372011-01-27 22:01:43 +00002708 if (p == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002709 lwsl_err("http_proxy needs to be ads:port\n");
Andy Green9659f372011-01-27 22:01:43 +00002710 return NULL;
2711 }
2712 *p = '\0';
Peter Hinz56885f32011-03-02 22:03:47 +00002713 context->http_proxy_port = atoi(p + 1);
Andy Green9659f372011-01-27 22:01:43 +00002714
Andy Green43db0452013-01-10 19:50:35 +08002715 lwsl_debug("Using proxy %s:%u\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002716 context->http_proxy_address,
2717 context->http_proxy_port);
Andy Green9659f372011-01-27 22:01:43 +00002718 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002719
2720 if (port) {
2721
Andy Green3faa9c72010-11-08 17:03:03 +00002722#ifdef LWS_OPENSSL_SUPPORT
Peter Hinz56885f32011-03-02 22:03:47 +00002723 context->use_ssl = ssl_cert_filepath != NULL &&
Andy Green90c7cbc2011-01-27 06:26:52 +00002724 ssl_private_key_filepath != NULL;
Peter Hinz56885f32011-03-02 22:03:47 +00002725 if (context->use_ssl)
Andy Green43db0452013-01-10 19:50:35 +08002726 lwsl_info(" Compiled with SSL support, using it\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002727 else
Andy Green43db0452013-01-10 19:50:35 +08002728 lwsl_info(" Compiled with SSL support, not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +00002729
Andy Green90c7cbc2011-01-27 06:26:52 +00002730#else
2731 if (ssl_cert_filepath != NULL &&
2732 ssl_private_key_filepath != NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002733 lwsl_info(" Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +00002734 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002735 }
Andy Green43db0452013-01-10 19:50:35 +08002736 lwsl_info(" Compiled without SSL support, "
Andy Green90c7cbc2011-01-27 06:26:52 +00002737 "serving unencrypted\n");
2738#endif
2739 }
2740
2741 /* ignore SIGPIPE */
Peter Hinz56885f32011-03-02 22:03:47 +00002742#ifdef WIN32
2743#else
Andy Green90c7cbc2011-01-27 06:26:52 +00002744 signal(SIGPIPE, sigpipe_handler);
Peter Hinz56885f32011-03-02 22:03:47 +00002745#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002746
2747
2748#ifdef LWS_OPENSSL_SUPPORT
2749
2750 /* basic openssl init */
2751
2752 SSL_library_init();
2753
2754 OpenSSL_add_all_algorithms();
2755 SSL_load_error_strings();
2756
Andy Green2e24da02011-03-05 16:12:04 +00002757 openssl_websocket_private_data_index =
Andy Green6901cb32011-02-21 08:06:47 +00002758 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
2759
Andy Green90c7cbc2011-01-27 06:26:52 +00002760 /*
2761 * Firefox insists on SSLv23 not SSLv3
2762 * Konq disables SSLv2 by default now, SSLv23 works
2763 */
2764
2765 method = (SSL_METHOD *)SSLv23_server_method();
2766 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002767 lwsl_err("problem creating ssl method: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002768 ERR_error_string(ERR_get_error(), ssl_err_buf));
2769 return NULL;
2770 }
Peter Hinz56885f32011-03-02 22:03:47 +00002771 context->ssl_ctx = SSL_CTX_new(method); /* create context */
2772 if (!context->ssl_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002773 lwsl_err("problem creating ssl context: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002774 ERR_error_string(ERR_get_error(), ssl_err_buf));
2775 return NULL;
2776 }
2777
David Galeanocc148e42013-01-10 10:18:59 +08002778#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002779 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002780#endif
David Galeano77a677c2013-01-10 10:14:12 +08002781 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002782 SSL_CTX_set_cipher_list(context->ssl_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002783
Andy Green90c7cbc2011-01-27 06:26:52 +00002784 /* client context */
Andy Green6ee372f2012-04-09 15:09:01 +08002785
2786 if (port == CONTEXT_PORT_NO_LISTEN) {
Peter Hinz56885f32011-03-02 22:03:47 +00002787 method = (SSL_METHOD *)SSLv23_client_method();
2788 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002789 lwsl_err("problem creating ssl method: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002790 ERR_error_string(ERR_get_error(), ssl_err_buf));
2791 return NULL;
2792 }
2793 /* create context */
2794 context->ssl_client_ctx = SSL_CTX_new(method);
2795 if (!context->ssl_client_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002796 lwsl_err("problem creating ssl context: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002797 ERR_error_string(ERR_get_error(), ssl_err_buf));
2798 return NULL;
2799 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002800
David Galeanocc148e42013-01-10 10:18:59 +08002801#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002802 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002803#endif
David Galeano77a677c2013-01-10 10:14:12 +08002804 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002805 SSL_CTX_set_cipher_list(context->ssl_client_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002806
Peter Hinz56885f32011-03-02 22:03:47 +00002807 /* openssl init for cert verification (for client sockets) */
David Galeano2f82be82013-01-09 16:25:54 +08002808 if (!ssl_ca_filepath) {
2809 if (!SSL_CTX_load_verify_locations(
2810 context->ssl_client_ctx, NULL,
2811 LWS_OPENSSL_CLIENT_CERTS))
Andy Green43db0452013-01-10 19:50:35 +08002812 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002813 "Unable to load SSL Client certs from %s "
2814 "(set by --with-client-cert-dir= in configure) -- "
2815 " client ssl isn't going to work",
2816 LWS_OPENSSL_CLIENT_CERTS);
2817 } else
2818 if (!SSL_CTX_load_verify_locations(
2819 context->ssl_client_ctx, ssl_ca_filepath,
2820 NULL))
Andy Green43db0452013-01-10 19:50:35 +08002821 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002822 "Unable to load SSL Client certs "
2823 "file from %s -- client ssl isn't "
2824 "going to work", ssl_ca_filepath);
Peter Hinz56885f32011-03-02 22:03:47 +00002825
2826 /*
2827 * callback allowing user code to load extra verification certs
2828 * helping the client to verify server identity
2829 */
2830
2831 context->protocols[0].callback(context, NULL,
2832 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
2833 context->ssl_client_ctx, NULL, 0);
Andy Green90c7cbc2011-01-27 06:26:52 +00002834 }
Andy Green6ee372f2012-04-09 15:09:01 +08002835
Andy Greenc6bf2c22011-02-20 11:10:47 +00002836 /* as a server, are we requiring clients to identify themselves? */
2837
2838 if (options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
2839
2840 /* absolutely require the client cert */
Andy Green6ee372f2012-04-09 15:09:01 +08002841
Peter Hinz56885f32011-03-02 22:03:47 +00002842 SSL_CTX_set_verify(context->ssl_ctx,
Andy Green6901cb32011-02-21 08:06:47 +00002843 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2844 OpenSSL_verify_callback);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002845
2846 /*
2847 * give user code a chance to load certs into the server
2848 * allowing it to verify incoming client certs
2849 */
2850
Peter Hinz56885f32011-03-02 22:03:47 +00002851 context->protocols[0].callback(context, NULL,
Andy Greenc6bf2c22011-02-20 11:10:47 +00002852 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
Peter Hinz56885f32011-03-02 22:03:47 +00002853 context->ssl_ctx, NULL, 0);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002854 }
2855
Peter Hinz56885f32011-03-02 22:03:47 +00002856 if (context->use_ssl) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002857
2858 /* openssl init for server sockets */
2859
Andy Green3faa9c72010-11-08 17:03:03 +00002860 /* set the local certificate from CertFile */
David Galeano9b3d4b22013-01-10 10:11:21 +08002861 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
2862 ssl_cert_filepath);
Andy Green3faa9c72010-11-08 17:03:03 +00002863 if (n != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002864 lwsl_err("problem getting cert '%s': %s\n",
Andy Green3faa9c72010-11-08 17:03:03 +00002865 ssl_cert_filepath,
2866 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002867 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002868 }
2869 /* set the private key from KeyFile */
Peter Hinz56885f32011-03-02 22:03:47 +00002870 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
2871 ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002872 lwsl_err("ssl problem getting key '%s': %s\n",
Andy Green018d8eb2010-11-08 21:04:23 +00002873 ssl_private_key_filepath,
2874 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002875 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002876 }
2877 /* verify private key */
Peter Hinz56885f32011-03-02 22:03:47 +00002878 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
Andy Green43db0452013-01-10 19:50:35 +08002879 lwsl_err("Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +00002880 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002881 }
2882
2883 /* SSL is happy and has a cert it's content with */
2884 }
2885#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002886
Andy Greendf736162011-01-18 15:39:02 +00002887 /* selftest */
2888
2889 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +00002890 return NULL;
Andy Greendf736162011-01-18 15:39:02 +00002891
Andy Green0d338332011-02-12 11:57:43 +00002892 /* fd hashtable init */
2893
2894 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002895 context->fd_hashtable[n].length = 0;
Andy Green0d338332011-02-12 11:57:43 +00002896
Andy Greenb45993c2010-12-18 15:13:50 +00002897 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +00002898
Andy Green4739e5c2011-01-22 12:51:57 +00002899 if (port) {
Andy Green8f037e42010-12-19 22:13:26 +00002900
Andy Green4739e5c2011-01-22 12:51:57 +00002901 sockfd = socket(AF_INET, SOCK_STREAM, 0);
2902 if (sockfd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002903 lwsl_err("ERROR opening socket");
Andy Green4739e5c2011-01-22 12:51:57 +00002904 return NULL;
2905 }
Andy Green775c0dd2010-10-29 14:15:22 +01002906
Andy Green4739e5c2011-01-22 12:51:57 +00002907 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08002908 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
2909 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00002910
2911 /* Disable Nagle */
2912 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08002913 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
2914 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00002915
Andy Green4739e5c2011-01-22 12:51:57 +00002916 bzero((char *) &serv_addr, sizeof(serv_addr));
2917 serv_addr.sin_family = AF_INET;
Peter Hinz56885f32011-03-02 22:03:47 +00002918 if (interf == NULL)
Andy Green32375b72011-02-19 08:32:53 +00002919 serv_addr.sin_addr.s_addr = INADDR_ANY;
2920 else
Peter Hinz56885f32011-03-02 22:03:47 +00002921 interface_to_sa(interf, &serv_addr,
Andy Green32375b72011-02-19 08:32:53 +00002922 sizeof(serv_addr));
Andy Green4739e5c2011-01-22 12:51:57 +00002923 serv_addr.sin_port = htons(port);
2924
2925 n = bind(sockfd, (struct sockaddr *) &serv_addr,
2926 sizeof(serv_addr));
2927 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002928 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Green8f037e42010-12-19 22:13:26 +00002929 port, n, errno);
Andy Green41c58032013-01-12 13:21:08 +08002930 close(sockfd);
Andy Green4739e5c2011-01-22 12:51:57 +00002931 return NULL;
2932 }
Andy Green0d338332011-02-12 11:57:43 +00002933
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002934 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08002935 if (wsi == NULL) {
2936 lwsl_err("Out of mem\n");
2937 close(sockfd);
2938 return NULL;
2939 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002940 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00002941 wsi->sock = sockfd;
Andy Greend6e09112011-03-05 16:12:15 +00002942 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00002943 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
Peter Hinz56885f32011-03-02 22:03:47 +00002944 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002945
David Galeano36973092013-01-10 09:58:24 +08002946 listen(sockfd, SOMAXCONN);
Andy Green43db0452013-01-10 19:50:35 +08002947 lwsl_info(" Listening on port %d\n", port);
Andy Green0d338332011-02-12 11:57:43 +00002948
2949 /* list in the internal poll array */
Andy Green6ee372f2012-04-09 15:09:01 +08002950
Peter Hinz56885f32011-03-02 22:03:47 +00002951 context->fds[context->fds_count].fd = sockfd;
2952 context->fds[context->fds_count++].events = POLLIN;
Andy Green3221f922011-02-12 13:14:11 +00002953
2954 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002955 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002956 LWS_CALLBACK_ADD_POLL_FD,
2957 (void *)(long)sockfd, NULL, POLLIN);
2958
Andy Green8f037e42010-12-19 22:13:26 +00002959 }
Andy Greenb45993c2010-12-18 15:13:50 +00002960
Andy Green6ee372f2012-04-09 15:09:01 +08002961 /*
2962 * drop any root privs for this process
2963 * to listen on port < 1023 we would have needed root, but now we are
2964 * listening, we don't want the power for anything else
2965 */
Peter Hinz56885f32011-03-02 22:03:47 +00002966#ifdef WIN32
2967#else
Andy Green3faa9c72010-11-08 17:03:03 +00002968 if (gid != -1)
2969 if (setgid(gid))
Andy Green43db0452013-01-10 19:50:35 +08002970 lwsl_warn("setgid: %s\n", strerror(errno));
Andy Green3faa9c72010-11-08 17:03:03 +00002971 if (uid != -1)
2972 if (setuid(uid))
Andy Green43db0452013-01-10 19:50:35 +08002973 lwsl_warn("setuid: %s\n", strerror(errno));
Peter Hinz56885f32011-03-02 22:03:47 +00002974#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002975
2976 /* set up our internal broadcast trigger sockets per-protocol */
2977
Peter Hinz56885f32011-03-02 22:03:47 +00002978 for (context->count_protocols = 0;
2979 protocols[context->count_protocols].callback;
2980 context->count_protocols++) {
Andy Green2d1301e2011-05-24 10:14:41 +01002981
Andy Green43db0452013-01-10 19:50:35 +08002982 lwsl_parser(" Protocol: %s\n",
2983 protocols[context->count_protocols].name);
Andy Green2d1301e2011-05-24 10:14:41 +01002984
Peter Hinz56885f32011-03-02 22:03:47 +00002985 protocols[context->count_protocols].owning_server = context;
2986 protocols[context->count_protocols].protocol_index =
2987 context->count_protocols;
Andy Greenb45993c2010-12-18 15:13:50 +00002988
2989 fd = socket(AF_INET, SOCK_STREAM, 0);
2990 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002991 lwsl_err("ERROR opening socket");
Andy Greene92cd172011-01-19 13:11:55 +00002992 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002993 }
Andy Green8f037e42010-12-19 22:13:26 +00002994
Andy Greenb45993c2010-12-18 15:13:50 +00002995 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08002996 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt,
2997 sizeof(opt));
Andy Greenb45993c2010-12-18 15:13:50 +00002998
2999 bzero((char *) &serv_addr, sizeof(serv_addr));
3000 serv_addr.sin_family = AF_INET;
3001 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3002 serv_addr.sin_port = 0; /* pick the port for us */
3003
3004 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
3005 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003006 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Greenb45993c2010-12-18 15:13:50 +00003007 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +00003008 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003009 }
3010
3011 slen = sizeof cli_addr;
3012 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
3013 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003014 lwsl_err("getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +00003015 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00003016 }
Peter Hinz56885f32011-03-02 22:03:47 +00003017 protocols[context->count_protocols].broadcast_socket_port =
Andy Greenb45993c2010-12-18 15:13:50 +00003018 ntohs(cli_addr.sin_port);
3019 listen(fd, 5);
3020
Andy Green43db0452013-01-10 19:50:35 +08003021 lwsl_debug(" Protocol %s broadcast socket %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00003022 protocols[context->count_protocols].name,
Andy Greenb45993c2010-12-18 15:13:50 +00003023 ntohs(cli_addr.sin_port));
3024
Andy Green0d338332011-02-12 11:57:43 +00003025 /* dummy wsi per broadcast proxy socket */
3026
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003027 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08003028 if (wsi == NULL) {
3029 lwsl_err("Out of mem\n");
3030 close(fd);
3031 return NULL;
3032 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003033 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00003034 wsi->sock = fd;
3035 wsi->mode = LWS_CONNMODE_BROADCAST_PROXY_LISTENER;
Andy Greend6e09112011-03-05 16:12:15 +00003036 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00003037 /* note which protocol we are proxying */
Peter Hinz56885f32011-03-02 22:03:47 +00003038 wsi->protocol_index_for_broadcast_proxy =
3039 context->count_protocols;
3040 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00003041
3042 /* list in internal poll array */
3043
Peter Hinz56885f32011-03-02 22:03:47 +00003044 context->fds[context->fds_count].fd = fd;
3045 context->fds[context->fds_count].events = POLLIN;
3046 context->fds[context->fds_count].revents = 0;
3047 context->fds_count++;
Andy Green3221f922011-02-12 13:14:11 +00003048
3049 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00003050 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00003051 LWS_CALLBACK_ADD_POLL_FD,
3052 (void *)(long)fd, NULL, POLLIN);
Andy Greenb45993c2010-12-18 15:13:50 +00003053 }
3054
Andy Greena41314f2011-05-23 10:00:03 +01003055 /*
3056 * give all extensions a chance to create any per-context
3057 * allocations they need
3058 */
3059
3060 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
3061 if (port)
3062 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
Andrew Chambersd5512172012-05-20 08:17:09 +08003063
3064 if (extensions) {
3065 while (extensions->callback) {
Andy Green43db0452013-01-10 19:50:35 +08003066 lwsl_ext(" Extension: %s\n", extensions->name);
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003067 extensions->callback(context, extensions, NULL,
3068 (enum libwebsocket_extension_callback_reasons)m,
3069 NULL, NULL, 0);
Andrew Chambersd5512172012-05-20 08:17:09 +08003070 extensions++;
3071 }
Andy Greena41314f2011-05-23 10:00:03 +01003072 }
3073
Peter Hinz56885f32011-03-02 22:03:47 +00003074 return context;
Andy Greene92cd172011-01-19 13:11:55 +00003075}
Andy Greenb45993c2010-12-18 15:13:50 +00003076
Andy Green4739e5c2011-01-22 12:51:57 +00003077
Andy Greened11a022011-01-20 10:23:50 +00003078#ifndef LWS_NO_FORK
3079
Andy Greene92cd172011-01-19 13:11:55 +00003080/**
3081 * libwebsockets_fork_service_loop() - Optional helper function forks off
3082 * a process for the websocket server loop.
Andy Green6964bb52011-01-23 16:50:33 +00003083 * You don't have to use this but if not, you
3084 * have to make sure you are calling
3085 * libwebsocket_service periodically to service
3086 * the websocket traffic
Peter Hinz56885f32011-03-02 22:03:47 +00003087 * @context: server context returned by creation function
Andy Greene92cd172011-01-19 13:11:55 +00003088 */
Andy Greenb45993c2010-12-18 15:13:50 +00003089
Andy Greene92cd172011-01-19 13:11:55 +00003090int
Peter Hinz56885f32011-03-02 22:03:47 +00003091libwebsockets_fork_service_loop(struct libwebsocket_context *context)
Andy Greene92cd172011-01-19 13:11:55 +00003092{
Andy Greene92cd172011-01-19 13:11:55 +00003093 int fd;
3094 struct sockaddr_in cli_addr;
3095 int n;
Andy Green3221f922011-02-12 13:14:11 +00003096 int p;
Andy Greenb45993c2010-12-18 15:13:50 +00003097
Andy Greened11a022011-01-20 10:23:50 +00003098 n = fork();
3099 if (n < 0)
3100 return n;
3101
3102 if (!n) {
3103
3104 /* main process context */
3105
Andy Green3221f922011-02-12 13:14:11 +00003106 /*
3107 * set up the proxy sockets to allow broadcast from
3108 * service process context
3109 */
3110
Peter Hinz56885f32011-03-02 22:03:47 +00003111 for (p = 0; p < context->count_protocols; p++) {
Andy Greened11a022011-01-20 10:23:50 +00003112 fd = socket(AF_INET, SOCK_STREAM, 0);
3113 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003114 lwsl_err("Unable to create socket\n");
Andy Greened11a022011-01-20 10:23:50 +00003115 return -1;
3116 }
3117 cli_addr.sin_family = AF_INET;
3118 cli_addr.sin_port = htons(
Peter Hinz56885f32011-03-02 22:03:47 +00003119 context->protocols[p].broadcast_socket_port);
Andy Greened11a022011-01-20 10:23:50 +00003120 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3121 n = connect(fd, (struct sockaddr *)&cli_addr,
3122 sizeof cli_addr);
3123 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003124 lwsl_err("Unable to connect to "
Andy Greened11a022011-01-20 10:23:50 +00003125 "broadcast socket %d, %s\n",
Andy Green3221f922011-02-12 13:14:11 +00003126 n, strerror(errno));
Andy Greened11a022011-01-20 10:23:50 +00003127 return -1;
3128 }
3129
Peter Hinz56885f32011-03-02 22:03:47 +00003130 context->protocols[p].broadcast_socket_user_fd = fd;
Andy Greened11a022011-01-20 10:23:50 +00003131 }
3132
Andy Greene92cd172011-01-19 13:11:55 +00003133 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00003134 }
3135
Artem Baguinski91531662011-12-14 22:14:03 +01003136#ifdef HAVE_SYS_PRCTL_H
Andy Greenb45993c2010-12-18 15:13:50 +00003137 /* we want a SIGHUP when our parent goes down */
3138 prctl(PR_SET_PDEATHSIG, SIGHUP);
Artem Baguinski91531662011-12-14 22:14:03 +01003139#endif
Andy Greenb45993c2010-12-18 15:13:50 +00003140
3141 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +00003142
Artem Baguinski91531662011-12-14 22:14:03 +01003143 while (1) {
Peter Hinz56885f32011-03-02 22:03:47 +00003144 if (libwebsocket_service(context, 1000))
Andy Green3928f612012-07-20 12:58:38 +08003145 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003146//#ifndef HAVE_SYS_PRCTL_H
Artem Baguinski91531662011-12-14 22:14:03 +01003147/*
3148 * on systems without prctl() (i.e. anything but linux) we can notice that our
3149 * parent is dead if getppid() returns 1. FIXME apparently this is not true for
3150 * solaris, could remember ppid right after fork and wait for it to change.
3151 */
3152
3153 if (getppid() == 1)
3154 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003155//#endif
Artem Baguinski91531662011-12-14 22:14:03 +01003156 }
3157
Andy Green8f037e42010-12-19 22:13:26 +00003158
Andy Green3928f612012-07-20 12:58:38 +08003159 return 1;
Andy Greenff95d7a2010-10-28 22:36:01 +01003160}
3161
Andy Greened11a022011-01-20 10:23:50 +00003162#endif
3163
Andy Greenb45993c2010-12-18 15:13:50 +00003164/**
3165 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +00003166 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +00003167 * @wsi: pointer to struct websocket you want to know the protocol of
3168 *
Andy Green8f037e42010-12-19 22:13:26 +00003169 *
3170 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +00003171 * the callback.
3172 */
Andy Greenab990e42010-10-31 12:42:52 +00003173
Andy Greenb45993c2010-12-18 15:13:50 +00003174const struct libwebsocket_protocols *
3175libwebsockets_get_protocol(struct libwebsocket *wsi)
3176{
3177 return wsi->protocol;
3178}
3179
3180/**
Andy Greene92cd172011-01-19 13:11:55 +00003181 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +00003182 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +00003183 * @protocol: pointer to the protocol you will broadcast to all members of
3184 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +00003185 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
3186 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
3187 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +00003188 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +00003189 *
3190 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +00003191 * the given protocol. It does not send the data directly; instead it calls
3192 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
3193 * wants to actually send the data for that connection, the callback itself
3194 * should call libwebsocket_write().
3195 *
3196 * libwebsockets_broadcast() can be called from another fork context without
3197 * having to take any care about data visibility between the processes, it'll
3198 * "just work".
3199 */
3200
3201
3202int
Andy Green8f037e42010-12-19 22:13:26 +00003203libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +00003204 unsigned char *buf, size_t len)
3205{
Peter Hinz56885f32011-03-02 22:03:47 +00003206 struct libwebsocket_context *context = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +00003207 int n;
Andy Green0d338332011-02-12 11:57:43 +00003208 int m;
Andy Green6ee372f2012-04-09 15:09:01 +08003209 struct libwebsocket *wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00003210
3211 if (!protocol->broadcast_socket_user_fd) {
3212 /*
Andy Greene92cd172011-01-19 13:11:55 +00003213 * We are either running unforked / flat, or we are being
3214 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +00003215 * eg, from a callback. In that case don't use sockets for
3216 * broadcast IPC (since we can't open a socket connection to
3217 * a socket listening on our own thread) but directly do the
3218 * send action.
3219 *
3220 * Locking is not needed because we are by definition being
3221 * called in the poll thread context and are serialized.
3222 */
3223
Andy Green0d338332011-02-12 11:57:43 +00003224 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003225
Peter Hinz56885f32011-03-02 22:03:47 +00003226 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003227
Peter Hinz56885f32011-03-02 22:03:47 +00003228 wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00003229
Andy Green0d338332011-02-12 11:57:43 +00003230 if (wsi->mode != LWS_CONNMODE_WS_SERVING)
3231 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00003232
Andy Green0d338332011-02-12 11:57:43 +00003233 /*
3234 * never broadcast to
3235 * non-established connections
3236 */
3237 if (wsi->state != WSI_STATE_ESTABLISHED)
3238 continue;
3239
3240 /* only broadcast to guys using
3241 * requested protocol
3242 */
3243 if (wsi->protocol != protocol)
3244 continue;
3245
Peter Hinz56885f32011-03-02 22:03:47 +00003246 wsi->protocol->callback(context, wsi,
Andy Green8f037e42010-12-19 22:13:26 +00003247 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00003248 wsi->user_space,
Andy Greenb45993c2010-12-18 15:13:50 +00003249 buf, len);
Andy Green0d338332011-02-12 11:57:43 +00003250 }
Andy Greenb45993c2010-12-18 15:13:50 +00003251 }
3252
3253 return 0;
3254 }
3255
Andy Green0ca6a172010-12-19 20:50:01 +00003256 /*
3257 * We're being called from a different process context than the server
3258 * loop. Instead of broadcasting directly, we send our
3259 * payload on a socket to do the IPC; the server process will serialize
3260 * the broadcast action in its main poll() loop.
3261 *
3262 * There's one broadcast socket listening for each protocol supported
3263 * set up when the websocket server initializes
3264 */
3265
Andy Green6964bb52011-01-23 16:50:33 +00003266 n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
Andy Greenb45993c2010-12-18 15:13:50 +00003267
3268 return n;
3269}
Andy Green82c3d542011-03-07 21:16:31 +00003270
3271int
3272libwebsocket_is_final_fragment(struct libwebsocket *wsi)
3273{
3274 return wsi->final;
3275}
Alex Bligh49146db2011-11-07 17:19:25 +08003276
David Galeanoe2cf9922013-01-09 18:06:55 +08003277unsigned char
3278libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
3279{
3280 return wsi->rsv;
3281}
3282
Alex Bligh49146db2011-11-07 17:19:25 +08003283void *
3284libwebsocket_ensure_user_space(struct libwebsocket *wsi)
3285{
3286 /* allocate the per-connection user memory (if any) */
3287
3288 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
3289 wsi->user_space = malloc(
3290 wsi->protocol->per_session_data_size);
3291 if (wsi->user_space == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08003292 lwsl_err("Out of memory for conn user space\n");
Alex Bligh49146db2011-11-07 17:19:25 +08003293 return NULL;
3294 }
Andy Green6ee372f2012-04-09 15:09:01 +08003295 memset(wsi->user_space, 0,
3296 wsi->protocol->per_session_data_size);
Alex Bligh49146db2011-11-07 17:19:25 +08003297 }
3298 return wsi->user_space;
3299}
Andy Green43db0452013-01-10 19:50:35 +08003300
Andy Greende8f27a2013-01-12 09:17:42 +08003301
3302static void lwsl_emit_stderr(const char *line)
3303{
3304 fprintf(stderr, "%s", line);
3305}
3306
Andy Green43db0452013-01-10 19:50:35 +08003307void _lws_log(int filter, const char *format, ...)
3308{
Andy Greende8f27a2013-01-12 09:17:42 +08003309 char buf[256];
Andy Green43db0452013-01-10 19:50:35 +08003310 va_list ap;
3311 int n;
Andy Greende8f27a2013-01-12 09:17:42 +08003312 int pos = 0;
Andy Green8a265092013-01-12 09:25:07 +08003313 struct timeval tv;
Andy Green43db0452013-01-10 19:50:35 +08003314
3315 if (!(log_level & filter))
3316 return;
3317
Andy Green8a265092013-01-12 09:25:07 +08003318 gettimeofday(&tv, NULL);
3319
Andy Green43db0452013-01-10 19:50:35 +08003320 for (n = 0; n < LLL_COUNT; n++)
3321 if (filter == (1 << n)) {
Andy Green8a265092013-01-12 09:25:07 +08003322 pos = sprintf(buf, "[%ld:%04ld] %s: ", tv.tv_sec,
3323 tv.tv_usec / 100, log_level_names[n]);
Andy Green43db0452013-01-10 19:50:35 +08003324 break;
3325 }
3326
3327 va_start(ap, format);
Andy Greende8f27a2013-01-12 09:17:42 +08003328 vsnprintf(buf + pos, (sizeof buf) - pos, format, ap);
3329 buf[(sizeof buf) - 1] = '\0';
3330 va_end(ap);
3331
3332 lwsl_emit(buf);
Andy Green43db0452013-01-10 19:50:35 +08003333}
3334
3335/**
3336 * lws_set_log_level() - Set the logging bitfield
3337 * @level: OR together the LLL_ debug contexts you want output from
Andy Greende8f27a2013-01-12 09:17:42 +08003338 * @log_emit_function: NULL to leave it as it is, or a user-supplied
3339 * function to perform log string emission instead of
3340 * the default stderr one.
Andy Green43db0452013-01-10 19:50:35 +08003341 *
Andy Greende8f27a2013-01-12 09:17:42 +08003342 * log level defaults to "err" and "warn" contexts enabled only and
3343 * emission on stderr.
Andy Green43db0452013-01-10 19:50:35 +08003344 */
3345
Andy Greende8f27a2013-01-12 09:17:42 +08003346void lws_set_log_level(int level, void (*log_emit_function)(const char *line))
Andy Green43db0452013-01-10 19:50:35 +08003347{
3348 log_level = level;
Andy Greende8f27a2013-01-12 09:17:42 +08003349 if (log_emit_function)
3350 lwsl_emit = log_emit_function;
Andy Green43db0452013-01-10 19:50:35 +08003351}