blob: 53e71e0f72324758f7a0267cd13d5e848cfa02ee [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 Greenf6652412011-05-25 20:46:18 +01001339 memset(wsi->active_extensions_user[
1340 wsi->count_active_extensions], 0,
1341 ext->per_session_data_size);
Andy Greena41314f2011-05-23 10:00:03 +01001342 wsi->active_extensions[
1343 wsi->count_active_extensions] = ext;
1344
1345 /* allow him to construct his context */
1346
1347 ext->callback(wsi->protocol->owning_server,
1348 ext, wsi,
1349 LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
1350 wsi->active_extensions_user[
1351 wsi->count_active_extensions],
1352 NULL, 0);
1353
1354 wsi->count_active_extensions++;
1355
1356 ext++;
1357 }
1358
1359 if (n == 0) {
Andy Green43db0452013-01-10 19:50:35 +08001360 lwsl_warn("Server said we should use"
Andy Greena41314f2011-05-23 10:00:03 +01001361 "an unknown extension '%s'!\n", ext_name);
1362 goto bail2;
1363 }
1364
1365 n = 0;
1366 }
1367
1368
1369check_accept:
1370
1371 if (wsi->ietf_spec_revision == 0) {
1372
1373 if (memcmp(wsi->initial_handshake_hash_base64,
1374 wsi->utf8_token[WSI_TOKEN_CHALLENGE].token, 16)) {
Andy Green43db0452013-01-10 19:50:35 +08001375 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001376 "failed 00 challenge compare\n");
1377 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001378 lwsl_warn("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001379 goto bail2;
1380 }
1381
1382 goto accept_ok;
1383 }
1384
1385 /*
1386 * Confirm his accept token is the one we precomputed
1387 */
1388
1389 if (strcmp(wsi->utf8_token[WSI_TOKEN_ACCEPT].token,
1390 wsi->initial_handshake_hash_base64)) {
Andy Green43db0452013-01-10 19:50:35 +08001391 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001392 "sent bad ACCEPT '%s' vs computed '%s'\n",
1393 wsi->utf8_token[WSI_TOKEN_ACCEPT].token,
1394 wsi->initial_handshake_hash_base64);
1395 goto bail2;
1396 }
1397
1398 if (wsi->ietf_spec_revision == 4) {
1399 /*
1400 * Calculate the 04 masking key to use when
1401 * sending data to server
1402 */
1403
1404 strcpy((char *)buf, wsi->key_b64);
1405 p = (char *)buf + strlen(wsi->key_b64);
1406 strcpy(p, wsi->utf8_token[WSI_TOKEN_NONCE].token);
1407 p += wsi->utf8_token[WSI_TOKEN_NONCE].token_len;
1408 strcpy(p, magic_websocket_04_masking_guid);
1409 SHA1(buf, strlen((char *)buf), wsi->masking_key_04);
1410 }
Andy Green6ee372f2012-04-09 15:09:01 +08001411accept_ok:
Andy Greena41314f2011-05-23 10:00:03 +01001412
1413 /* allocate the per-connection user memory (if any) */
Andy Green6ee372f2012-04-09 15:09:01 +08001414 if (wsi->protocol->per_session_data_size &&
1415 !libwebsocket_ensure_user_space(wsi))
1416 goto bail2;
Andy Greena41314f2011-05-23 10:00:03 +01001417
1418 /* clear his proxy connection timeout */
1419
1420 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1421
1422 /* mark him as being alive */
1423
1424 wsi->state = WSI_STATE_ESTABLISHED;
1425 wsi->mode = LWS_CONNMODE_WS_CLIENT;
1426
Andy Green43db0452013-01-10 19:50:35 +08001427 lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
Andy Greena41314f2011-05-23 10:00:03 +01001428
1429 /* call him back to inform him he is up */
1430
1431 wsi->protocol->callback(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08001432 LWS_CALLBACK_CLIENT_ESTABLISHED,
1433 wsi->user_space, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01001434
1435 /*
1436 * inform all extensions, not just active ones since they
1437 * already know
1438 */
1439
1440 ext = context->extensions;
1441
1442 while (ext && ext->callback) {
1443 v = NULL;
1444 for (n = 0; n < wsi->count_active_extensions; n++)
1445 if (wsi->active_extensions[n] == ext)
1446 v = wsi->active_extensions_user[n];
1447
1448 ext->callback(context, ext, wsi,
1449 LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED, v, NULL, 0);
1450 ext++;
1451 }
1452
1453 return 0;
1454
1455bail3:
1456 if (wsi->c_protocol)
1457 free(wsi->c_protocol);
1458
1459bail2:
David Brooks80a44972012-04-20 12:18:47 +08001460 if (wsi->c_callback) wsi->c_callback(context, wsi,
1461 LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
1462 wsi->user_space,
1463 NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01001464 libwebsocket_close_and_free_session(context, wsi,
David Brooks80a44972012-04-20 12:18:47 +08001465 LWS_CLOSE_STATUS_NOSTATUS); // But this should be LWS_CLOSE_STATUS_PROTOCOL_ERR
1466
Andy Greena41314f2011-05-23 10:00:03 +01001467 return 1;
1468}
1469
1470
1471
Andy Green9f990342011-02-12 11:57:45 +00001472/**
1473 * libwebsocket_service_fd() - Service polled socket with something waiting
Peter Hinz56885f32011-03-02 22:03:47 +00001474 * @context: Websocket context
Andy Green9f990342011-02-12 11:57:45 +00001475 * @pollfd: The pollfd entry describing the socket fd and which events
Andy Green6ee372f2012-04-09 15:09:01 +08001476 * happened.
Andy Green9f990342011-02-12 11:57:45 +00001477 *
1478 * This function closes any active connections and then frees the
1479 * context. After calling this, any further use of the context is
1480 * undefined.
1481 */
1482
1483int
Peter Hinz56885f32011-03-02 22:03:47 +00001484libwebsocket_service_fd(struct libwebsocket_context *context,
Andy Green0d338332011-02-12 11:57:43 +00001485 struct pollfd *pollfd)
Andy Greenb45993c2010-12-18 15:13:50 +00001486{
Andy Green6ee372f2012-04-09 15:09:01 +08001487 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
1488 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena71eafc2011-02-14 17:59:43 +00001489 struct libwebsocket *wsi;
Andy Green0d338332011-02-12 11:57:43 +00001490 struct libwebsocket *new_wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00001491 int n;
Andy Green0d338332011-02-12 11:57:43 +00001492 int m;
Tobias Maiere8c9b562012-04-05 11:57:12 +02001493 ssize_t len;
Andy Green0d338332011-02-12 11:57:43 +00001494 int accept_fd;
1495 unsigned int clilen;
1496 struct sockaddr_in cli_addr;
Andy Greena71eafc2011-02-14 17:59:43 +00001497 struct timeval tv;
Andy Greenbe93fef2011-02-14 20:25:43 +00001498 char pkt[1024];
1499 char *p = &pkt[0];
Andy Green2366b1c2011-03-06 13:15:31 +00001500 int more = 1;
Andy Green98a717c2011-03-06 13:14:15 +00001501 struct lws_tokens eff_buf;
Andy Green6c939552011-03-08 08:56:57 +00001502 int opt = 1;
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001503 char c;
Andy Greenc6517fa2011-03-06 13:15:29 +00001504
Andy Greenbe93fef2011-02-14 20:25:43 +00001505#ifdef LWS_OPENSSL_SUPPORT
1506 char ssl_err_buf[512];
1507#endif
Andy Greena71eafc2011-02-14 17:59:43 +00001508 /*
1509 * you can call us with pollfd = NULL to just allow the once-per-second
1510 * global timeout checks; if less than a second since the last check
1511 * it returns immediately then.
1512 */
1513
1514 gettimeofday(&tv, NULL);
1515
Peter Hinz56885f32011-03-02 22:03:47 +00001516 if (context->last_timeout_check_s != tv.tv_sec) {
1517 context->last_timeout_check_s = tv.tv_sec;
Andy Greena71eafc2011-02-14 17:59:43 +00001518
1519 /* global timeout check once per second */
1520
Peter Hinz56885f32011-03-02 22:03:47 +00001521 for (n = 0; n < context->fds_count; n++) {
1522 wsi = wsi_from_fd(context, context->fds[n].fd);
Andy Greena71eafc2011-02-14 17:59:43 +00001523
Andy Greena41314f2011-05-23 10:00:03 +01001524 libwebsocket_service_timeout_check(context, wsi,
1525 tv.tv_sec);
Andy Greena71eafc2011-02-14 17:59:43 +00001526 }
1527 }
1528
1529 /* just here for timeout management? */
1530
1531 if (pollfd == NULL)
1532 return 0;
1533
1534 /* no, here to service a socket descriptor */
1535
Peter Hinz56885f32011-03-02 22:03:47 +00001536 wsi = wsi_from_fd(context, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001537
Andy Green0d338332011-02-12 11:57:43 +00001538 if (wsi == NULL)
Andy Greenfa3f4052012-10-07 20:40:35 +08001539 return 0;
Andy Green8f037e42010-12-19 22:13:26 +00001540
Andy Green0d338332011-02-12 11:57:43 +00001541 switch (wsi->mode) {
1542 case LWS_CONNMODE_SERVER_LISTENER:
1543
1544 /* pollin means a client has connected to us then */
1545
David Galeanob88e0962013-01-10 09:54:10 +08001546 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001547 break;
1548
David Galeanof7009352011-09-26 12:09:54 +01001549 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001550 lwsl_warn("too busy to accept new client\n");
David Galeanof7009352011-09-26 12:09:54 +01001551 break;
1552 }
1553
Andy Green0d338332011-02-12 11:57:43 +00001554 /* listen socket got an unencrypted connection... */
1555
1556 clilen = sizeof(cli_addr);
1557 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1558 &clilen);
1559 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001560 lwsl_warn("ERROR on accept: %d\n", strerror(errno));
Andy Green3928f612012-07-20 12:58:38 +08001561 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001562 }
1563
Andy Green6c939552011-03-08 08:56:57 +00001564 /* Disable Nagle */
1565 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08001566 setsockopt(accept_fd, IPPROTO_TCP, TCP_NODELAY,
1567 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00001568
Andy Green07034092011-02-13 08:37:12 +00001569 /*
1570 * look at who we connected to and give user code a chance
1571 * to reject based on client IP. There's no protocol selected
1572 * yet so we issue this to protocols[0]
1573 */
1574
Peter Hinz56885f32011-03-02 22:03:47 +00001575 if ((context->protocols[0].callback)(context, wsi,
Andy Green07034092011-02-13 08:37:12 +00001576 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
Andy Green6ee372f2012-04-09 15:09:01 +08001577 (void *)(long)accept_fd, NULL, 0)) {
Andy Green43db0452013-01-10 19:50:35 +08001578 lwsl_debug("Callback denied network connection\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001579#ifdef WIN32
1580 closesocket(accept_fd);
1581#else
Andy Green07034092011-02-13 08:37:12 +00001582 close(accept_fd);
Peter Hinz56885f32011-03-02 22:03:47 +00001583#endif
Andy Green07034092011-02-13 08:37:12 +00001584 break;
1585 }
1586
Andy Green0d338332011-02-12 11:57:43 +00001587 /* accepting connection to main listener */
1588
Andy Greena41314f2011-05-23 10:00:03 +01001589 new_wsi = libwebsocket_create_new_server_wsi(context);
David Galeanoed3c8402013-01-10 10:45:24 +08001590 if (new_wsi == NULL) {
1591#ifdef WIN32
1592 closesocket(accept_fd);
1593#else
1594 close(accept_fd);
1595#endif
Andy Green0d338332011-02-12 11:57:43 +00001596 break;
David Galeanoed3c8402013-01-10 10:45:24 +08001597 }
Andy Green0d338332011-02-12 11:57:43 +00001598
Andy Green0d338332011-02-12 11:57:43 +00001599 new_wsi->sock = accept_fd;
Andy Greena41314f2011-05-23 10:00:03 +01001600
Andy Green0d338332011-02-12 11:57:43 +00001601
1602#ifdef LWS_OPENSSL_SUPPORT
1603 new_wsi->ssl = NULL;
Andy Green0d338332011-02-12 11:57:43 +00001604
Peter Hinz56885f32011-03-02 22:03:47 +00001605 if (context->use_ssl) {
Andy Green0d338332011-02-12 11:57:43 +00001606
Peter Hinz56885f32011-03-02 22:03:47 +00001607 new_wsi->ssl = SSL_new(context->ssl_ctx);
Andy Green0d338332011-02-12 11:57:43 +00001608 if (new_wsi->ssl == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08001609 lwsl_err("SSL_new failed: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001610 ERR_error_string(SSL_get_error(
1611 new_wsi->ssl, 0), NULL));
Andy Green1f9bf522011-02-14 21:14:37 +00001612 libwebsockets_decode_ssl_error();
Andy Green0d338332011-02-12 11:57:43 +00001613 free(new_wsi);
David Galeanoed3c8402013-01-10 10:45:24 +08001614#ifdef WIN32
1615 closesocket(accept_fd);
1616#else
1617 close(accept_fd);
1618#endif
Andy Green0d338332011-02-12 11:57:43 +00001619 break;
1620 }
1621
1622 SSL_set_fd(new_wsi->ssl, accept_fd);
1623
1624 n = SSL_accept(new_wsi->ssl);
1625 if (n != 1) {
1626 /*
1627 * browsers seem to probe with various
1628 * ssl params which fail then retry
1629 * and succeed
1630 */
Andy Green43db0452013-01-10 19:50:35 +08001631 lwsl_debug("SSL_accept failed skt %u: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001632 pollfd->fd,
1633 ERR_error_string(SSL_get_error(
1634 new_wsi->ssl, n), NULL));
1635 SSL_free(
1636 new_wsi->ssl);
1637 free(new_wsi);
David Galeanoed3c8402013-01-10 10:45:24 +08001638#ifdef WIN32
1639 closesocket(accept_fd);
1640#else
1641 close(accept_fd);
1642#endif
Andy Green0d338332011-02-12 11:57:43 +00001643 break;
1644 }
Andy Green6ee372f2012-04-09 15:09:01 +08001645
Andy Green43db0452013-01-10 19:50:35 +08001646 lwsl_debug("accepted new SSL conn "
Andy Green0d338332011-02-12 11:57:43 +00001647 "port %u on fd=%d SSL ver %s\n",
1648 ntohs(cli_addr.sin_port), accept_fd,
1649 SSL_get_version(new_wsi->ssl));
1650
1651 } else
1652#endif
Andy Green43db0452013-01-10 19:50:35 +08001653 lwsl_debug("accepted new conn port %u on fd=%d\n",
Andy Green0d338332011-02-12 11:57:43 +00001654 ntohs(cli_addr.sin_port), accept_fd);
1655
Peter Hinz56885f32011-03-02 22:03:47 +00001656 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001657
Andy Green0d338332011-02-12 11:57:43 +00001658 /*
1659 * make sure NO events are seen yet on this new socket
1660 * (otherwise we inherit old fds[client].revents from
1661 * previous socket there and die mysteriously! )
1662 */
Peter Hinz56885f32011-03-02 22:03:47 +00001663 context->fds[context->fds_count].revents = 0;
Andy Green0d338332011-02-12 11:57:43 +00001664
Peter Hinz56885f32011-03-02 22:03:47 +00001665 context->fds[context->fds_count].events = POLLIN;
1666 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001667
Andy Green3221f922011-02-12 13:14:11 +00001668 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001669 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001670 LWS_CALLBACK_ADD_POLL_FD,
1671 (void *)(long)accept_fd, NULL, POLLIN);
1672
Andy Green0d338332011-02-12 11:57:43 +00001673 break;
1674
1675 case LWS_CONNMODE_BROADCAST_PROXY_LISTENER:
1676
1677 /* as we are listening, POLLIN means accept() is needed */
Andy Green6ee372f2012-04-09 15:09:01 +08001678
David Galeanob88e0962013-01-10 09:54:10 +08001679 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001680 break;
1681
1682 /* listen socket got an unencrypted connection... */
1683
1684 clilen = sizeof(cli_addr);
1685 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1686 &clilen);
1687 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001688 lwsl_warn("ERROR on accept %d\n", accept_fd);
Andy Green3928f612012-07-20 12:58:38 +08001689 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001690 }
1691
Peter Hinz56885f32011-03-02 22:03:47 +00001692 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001693 lwsl_err("too busy to accept new broadcast "
Andy Green3221f922011-02-12 13:14:11 +00001694 "proxy client\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001695#ifdef WIN32
1696 closesocket(accept_fd);
1697#else
Andy Green0d338332011-02-12 11:57:43 +00001698 close(accept_fd);
Peter Hinz56885f32011-03-02 22:03:47 +00001699#endif
Andy Green0d338332011-02-12 11:57:43 +00001700 break;
1701 }
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));
1706 memset(new_wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00001707 new_wsi->sock = accept_fd;
1708 new_wsi->mode = LWS_CONNMODE_BROADCAST_PROXY;
1709 new_wsi->state = WSI_STATE_ESTABLISHED;
Andy Greend6e09112011-03-05 16:12:15 +00001710 new_wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00001711 /* note which protocol we are proxying */
1712 new_wsi->protocol_index_for_broadcast_proxy =
1713 wsi->protocol_index_for_broadcast_proxy;
Peter Hinz56885f32011-03-02 22:03:47 +00001714 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001715
1716 /* add connected socket to internal poll array */
1717
Peter Hinz56885f32011-03-02 22:03:47 +00001718 context->fds[context->fds_count].revents = 0;
1719 context->fds[context->fds_count].events = POLLIN;
1720 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001721
Andy Green3221f922011-02-12 13:14:11 +00001722 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001723 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001724 LWS_CALLBACK_ADD_POLL_FD,
1725 (void *)(long)accept_fd, NULL, POLLIN);
1726
Andy Green0d338332011-02-12 11:57:43 +00001727 break;
1728
1729 case LWS_CONNMODE_BROADCAST_PROXY:
Andy Green8f037e42010-12-19 22:13:26 +00001730
Andy Greenb45993c2010-12-18 15:13:50 +00001731 /* handle session socket closed */
Andy Green8f037e42010-12-19 22:13:26 +00001732
Andy Green0d338332011-02-12 11:57:43 +00001733 if (pollfd->revents & (POLLERR | POLLHUP)) {
Andy Green8f037e42010-12-19 22:13:26 +00001734
Andy Green43db0452013-01-10 19:50:35 +08001735 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Timothy J Fontaineb86d64e2011-02-14 17:55:27 +00001736 (void *)wsi, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001737
Peter Hinz56885f32011-03-02 22:03:47 +00001738 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001739 LWS_CLOSE_STATUS_NORMAL);
Andy Green4b6fbe12011-02-14 08:03:48 +00001740 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00001741 }
Andy Green8f037e42010-12-19 22:13:26 +00001742
Andy Green3b84c002011-03-06 13:14:42 +00001743 /*
1744 * either extension code with stuff to spill, or the user code,
1745 * requested a callback when it was OK to write
1746 */
Andy Green90c7cbc2011-01-27 06:26:52 +00001747
Andy Green3b84c002011-03-06 13:14:42 +00001748 if (pollfd->revents & POLLOUT)
Andy Green6ee372f2012-04-09 15:09:01 +08001749 if (lws_handle_POLLOUT_event(context, wsi,
1750 pollfd) < 0) {
1751 libwebsocket_close_and_free_session(
1752 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00001753 return 1;
1754 }
Andy Green90c7cbc2011-01-27 06:26:52 +00001755
Andy Greenb45993c2010-12-18 15:13:50 +00001756 /* any incoming data ready? */
1757
Andy Green0d338332011-02-12 11:57:43 +00001758 if (!(pollfd->revents & POLLIN))
1759 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001760
Andy Green0d338332011-02-12 11:57:43 +00001761 /* get the issued broadcast payload from the socket */
Andy Greenb45993c2010-12-18 15:13:50 +00001762
Andy Green0d338332011-02-12 11:57:43 +00001763 len = read(pollfd->fd, buf + LWS_SEND_BUFFER_PRE_PADDING,
1764 MAX_BROADCAST_PAYLOAD);
1765 if (len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001766 lwsl_err("Error reading broadcast payload\n");
Andy Green4b6fbe12011-02-14 08:03:48 +00001767 break;
Andy Green0d338332011-02-12 11:57:43 +00001768 }
Andy Greenb45993c2010-12-18 15:13:50 +00001769
Andy Green0d338332011-02-12 11:57:43 +00001770 /* broadcast it to all guys with this protocol index */
Andy Green8f037e42010-12-19 22:13:26 +00001771
Andy Green0d338332011-02-12 11:57:43 +00001772 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Green8f037e42010-12-19 22:13:26 +00001773
Peter Hinz56885f32011-03-02 22:03:47 +00001774 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00001775
Peter Hinz56885f32011-03-02 22:03:47 +00001776 new_wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00001777
Andy Green0d338332011-02-12 11:57:43 +00001778 /* only to clients we are serving to */
Andy Greenb45993c2010-12-18 15:13:50 +00001779
Andy Green0d338332011-02-12 11:57:43 +00001780 if (new_wsi->mode != LWS_CONNMODE_WS_SERVING)
Andy Greenb45993c2010-12-18 15:13:50 +00001781 continue;
1782
1783 /*
1784 * never broadcast to non-established
1785 * connection
1786 */
1787
Andy Green0d338332011-02-12 11:57:43 +00001788 if (new_wsi->state != WSI_STATE_ESTABLISHED)
Andy Green4739e5c2011-01-22 12:51:57 +00001789 continue;
1790
Andy Greenb45993c2010-12-18 15:13:50 +00001791 /*
1792 * only broadcast to connections using
1793 * the requested protocol
1794 */
1795
Andy Green0d338332011-02-12 11:57:43 +00001796 if (new_wsi->protocol->protocol_index !=
1797 wsi->protocol_index_for_broadcast_proxy)
Andy Greenb45993c2010-12-18 15:13:50 +00001798 continue;
1799
Andy Green8f037e42010-12-19 22:13:26 +00001800 /* broadcast it to this connection */
1801
Peter Hinz56885f32011-03-02 22:03:47 +00001802 new_wsi->protocol->callback(context, new_wsi,
Andy Green8f037e42010-12-19 22:13:26 +00001803 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00001804 new_wsi->user_space,
Andy Green0ca6a172010-12-19 20:50:01 +00001805 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
Andy Greenb45993c2010-12-18 15:13:50 +00001806 }
Andy Green0d338332011-02-12 11:57:43 +00001807 }
1808 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001809
Andy Greenbe93fef2011-02-14 20:25:43 +00001810 case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
1811
1812 /* handle proxy hung up on us */
1813
1814 if (pollfd->revents & (POLLERR | POLLHUP)) {
1815
Andy Green43db0452013-01-10 19:50:35 +08001816 lwsl_warn("Proxy connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00001817 (void *)wsi, pollfd->fd);
1818
Peter Hinz56885f32011-03-02 22:03:47 +00001819 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001820 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001821 return 1;
1822 }
1823
Andy Green72c34322011-04-16 10:46:21 +01001824 n = recv(wsi->sock, pkt, sizeof pkt, 0);
Andy Greenbe93fef2011-02-14 20:25:43 +00001825 if (n < 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001826 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001827 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001828 lwsl_err("ERROR reading from proxy socket\n");
Andy Greenbe93fef2011-02-14 20:25:43 +00001829 return 1;
1830 }
1831
1832 pkt[13] = '\0';
1833 if (strcmp(pkt, "HTTP/1.0 200 ") != 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001834 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001835 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001836 lwsl_err("ERROR from proxy: %s\n", pkt);
Andy Greenbe93fef2011-02-14 20:25:43 +00001837 return 1;
1838 }
1839
1840 /* clear his proxy connection timeout */
1841
1842 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1843
1844 /* fallthru */
1845
1846 case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
1847
1848 #ifdef LWS_OPENSSL_SUPPORT
Ken Atherton8360a472012-05-03 11:45:04 +08001849 if (wsi->use_ssl && !wsi->ssl) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001850
Peter Hinz56885f32011-03-02 22:03:47 +00001851 wsi->ssl = SSL_new(context->ssl_client_ctx);
1852 wsi->client_bio = BIO_new_socket(wsi->sock,
1853 BIO_NOCLOSE);
Andy Greenbe93fef2011-02-14 20:25:43 +00001854 SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
1855
Andy Green6901cb32011-02-21 08:06:47 +00001856 SSL_set_ex_data(wsi->ssl,
Andy Green2e24da02011-03-05 16:12:04 +00001857 openssl_websocket_private_data_index,
Peter Hinz56885f32011-03-02 22:03:47 +00001858 context);
Ken Atherton8360a472012-05-03 11:45:04 +08001859 }
Andy Green6901cb32011-02-21 08:06:47 +00001860
Ken Atherton8360a472012-05-03 11:45:04 +08001861 if (wsi->use_ssl) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001862 if (SSL_connect(wsi->ssl) <= 0) {
Ken Atherton8360a472012-05-03 11:45:04 +08001863
1864 /*
1865 * retry if new data comes until we
1866 * run into the connection timeout or win
1867 */
1868
Andy Green43db0452013-01-10 19:50:35 +08001869 lwsl_err("SSL connect error %s\n",
Andy Green687b0182011-02-26 11:04:01 +00001870 ERR_error_string(ERR_get_error(),
1871 ssl_err_buf));
Ken Atherton8360a472012-05-03 11:45:04 +08001872 return 0;
Andy Greenbe93fef2011-02-14 20:25:43 +00001873 }
1874
1875 n = SSL_get_verify_result(wsi->ssl);
Andy Green2e24da02011-03-05 16:12:04 +00001876 if ((n != X509_V_OK) && (
Andy Green687b0182011-02-26 11:04:01 +00001877 n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
1878 wsi->use_ssl != 2)) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001879
Andy Green43db0452013-01-10 19:50:35 +08001880 lwsl_err("server's cert didn't "
Andy Green687b0182011-02-26 11:04:01 +00001881 "look good %d\n", n);
Peter Hinz56885f32011-03-02 22:03:47 +00001882 libwebsocket_close_and_free_session(context,
1883 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Green687b0182011-02-26 11:04:01 +00001884 return 1;
Andy Greenbe93fef2011-02-14 20:25:43 +00001885 }
Ken Atherton8360a472012-05-03 11:45:04 +08001886 } else
Andy Greenbe93fef2011-02-14 20:25:43 +00001887 wsi->ssl = NULL;
1888 #endif
1889
Andy Greena41314f2011-05-23 10:00:03 +01001890 p = libwebsockets_generate_client_handshake(context, wsi, p);
Andy Green6ee372f2012-04-09 15:09:01 +08001891 if (p == NULL)
Andy Greenbe93fef2011-02-14 20:25:43 +00001892 return 1;
Andy Greeneeaacb32011-03-01 20:44:24 +00001893
Andy Greenbe93fef2011-02-14 20:25:43 +00001894 /* send our request to the server */
1895
1896 #ifdef LWS_OPENSSL_SUPPORT
1897 if (wsi->use_ssl)
1898 n = SSL_write(wsi->ssl, pkt, p - pkt);
1899 else
1900 #endif
1901 n = send(wsi->sock, pkt, p - pkt, 0);
1902
1903 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001904 lwsl_debug("ERROR writing to client socket\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001905 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001906 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001907 return 1;
1908 }
1909
1910 wsi->parser_state = WSI_TOKEN_NAME_PART;
1911 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
1912 libwebsocket_set_timeout(wsi,
David Galeanoc9f1ff82013-01-09 18:01:23 +08001913 PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, AWAITING_TIMEOUT);
Andy Greenbe93fef2011-02-14 20:25:43 +00001914
1915 break;
1916
1917 case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
1918
1919 /* handle server hung up on us */
1920
1921 if (pollfd->revents & (POLLERR | POLLHUP)) {
1922
Andy Green43db0452013-01-10 19:50:35 +08001923 lwsl_debug("Server connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00001924 (void *)wsi, pollfd->fd);
1925
1926 goto bail3;
1927 }
1928
1929
1930 /* interpret the server response */
1931
1932 /*
1933 * HTTP/1.1 101 Switching Protocols
1934 * Upgrade: websocket
1935 * Connection: Upgrade
1936 * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
1937 * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
1938 * Sec-WebSocket-Protocol: chat
1939 */
1940
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001941 /*
1942 * we have to take some care here to only take from the
1943 * socket bytewise. The browser may (and has been seen to
1944 * in the case that onopen() performs websocket traffic)
1945 * coalesce both handshake response and websocket traffic
1946 * in one packet, since at that point the connection is
1947 * definitively ready from browser pov.
1948 */
Andy Greenbe93fef2011-02-14 20:25:43 +00001949
Andy Green7b5af9a2012-04-09 15:23:47 +08001950 len = 1;
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001951 while (wsi->parser_state != WSI_PARSING_COMPLETE && len > 0) {
1952#ifdef LWS_OPENSSL_SUPPORT
1953 if (wsi->use_ssl)
1954 len = SSL_read(wsi->ssl, &c, 1);
1955 else
1956#endif
1957 len = recv(wsi->sock, &c, 1, 0);
1958
1959 libwebsocket_parse(wsi, c);
Andy Greenbe93fef2011-02-14 20:25:43 +00001960 }
1961
Andy Green27a0b912011-04-16 10:54:28 +01001962 /*
Andy Green6ee372f2012-04-09 15:09:01 +08001963 * hs may also be coming in multiple packets, there is a 5-sec
Andy Green27a0b912011-04-16 10:54:28 +01001964 * libwebsocket timeout still active here too, so if parsing did
1965 * not complete just wait for next packet coming in this state
1966 */
1967
1968 if (wsi->parser_state != WSI_PARSING_COMPLETE)
1969 break;
Andy Greenbe93fef2011-02-14 20:25:43 +00001970
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001971 /*
1972 * otherwise deal with the handshake. If there's any
1973 * packet traffic already arrived we'll trigger poll() again
1974 * right away and deal with it that way
1975 */
1976
Andy Greena41314f2011-05-23 10:00:03 +01001977 return lws_client_interpret_server_handshake(context, wsi);
Andy Greenbe93fef2011-02-14 20:25:43 +00001978
1979bail3:
1980 if (wsi->c_protocol)
1981 free(wsi->c_protocol);
Peter Hinz56885f32011-03-02 22:03:47 +00001982 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08001983 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001984 return 1;
Andy Greena41314f2011-05-23 10:00:03 +01001985
1986 case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
Andy Green43db0452013-01-10 19:50:35 +08001987 lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
Andy Greena41314f2011-05-23 10:00:03 +01001988 break;
1989
1990 case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
Andy Green43db0452013-01-10 19:50:35 +08001991 lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
Andy Greena41314f2011-05-23 10:00:03 +01001992 break;
1993
Andy Greenbe93fef2011-02-14 20:25:43 +00001994
Andy Green0d338332011-02-12 11:57:43 +00001995 case LWS_CONNMODE_WS_SERVING:
1996 case LWS_CONNMODE_WS_CLIENT:
1997
1998 /* handle session socket closed */
1999
2000 if (pollfd->revents & (POLLERR | POLLHUP)) {
2001
Andy Green43db0452013-01-10 19:50:35 +08002002 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Andy Green0d338332011-02-12 11:57:43 +00002003 (void *)wsi, pollfd->fd);
2004
Peter Hinz56885f32011-03-02 22:03:47 +00002005 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002006 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green4b6fbe12011-02-14 08:03:48 +00002007 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002008 }
2009
Andy Green0d338332011-02-12 11:57:43 +00002010 /* the guy requested a callback when it was OK to write */
2011
Andy Greenda527df2011-03-07 07:08:12 +00002012 if ((pollfd->revents & POLLOUT) &&
2013 wsi->state == WSI_STATE_ESTABLISHED)
2014 if (lws_handle_POLLOUT_event(context, wsi,
2015 pollfd) < 0) {
2016 libwebsocket_close_and_free_session(
2017 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00002018 return 1;
2019 }
Andy Green0d338332011-02-12 11:57:43 +00002020
Andy Green0d338332011-02-12 11:57:43 +00002021
2022 /* any incoming data ready? */
2023
2024 if (!(pollfd->revents & POLLIN))
2025 break;
2026
Andy Greenb45993c2010-12-18 15:13:50 +00002027#ifdef LWS_OPENSSL_SUPPORT
David Galeano7ffbe1b2013-01-10 10:35:32 +08002028read_pending:
Andy Green0d338332011-02-12 11:57:43 +00002029 if (wsi->ssl)
Andy Green98a717c2011-03-06 13:14:15 +00002030 eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);
Andy Greenb45993c2010-12-18 15:13:50 +00002031 else
2032#endif
Andy Green98a717c2011-03-06 13:14:15 +00002033 eff_buf.token_len =
Andy Green72c34322011-04-16 10:46:21 +01002034 recv(pollfd->fd, buf, sizeof buf, 0);
Andy Greenb45993c2010-12-18 15:13:50 +00002035
Andy Green98a717c2011-03-06 13:14:15 +00002036 if (eff_buf.token_len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002037 lwsl_debug("Socket read returned %d\n",
Andy Green98a717c2011-03-06 13:14:15 +00002038 eff_buf.token_len);
Alon Levydc93b7f2012-10-19 11:21:57 +02002039 if (errno != EINTR && errno != EAGAIN)
Andy Green6ee372f2012-04-09 15:09:01 +08002040 libwebsocket_close_and_free_session(context,
2041 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Nick Dowellc04c1932012-04-05 10:29:39 +08002042 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002043 }
Andy Green98a717c2011-03-06 13:14:15 +00002044 if (!eff_buf.token_len) {
Peter Hinz56885f32011-03-02 22:03:47 +00002045 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002046 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenfa3f4052012-10-07 20:40:35 +08002047 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00002048 }
2049
Andy Green98a717c2011-03-06 13:14:15 +00002050 /*
2051 * give any active extensions a chance to munge the buffer
2052 * before parse. We pass in a pointer to an lws_tokens struct
2053 * prepared with the default buffer and content length that's in
2054 * there. Rather than rewrite the default buffer, extensions
2055 * that expect to grow the buffer can adapt .token to
2056 * point to their own per-connection buffer in the extension
2057 * user allocation. By default with no extensions or no
2058 * extension callback handling, just the normal input buffer is
2059 * used then so it is efficient.
2060 */
Andy Greenb45993c2010-12-18 15:13:50 +00002061
Andy Green98a717c2011-03-06 13:14:15 +00002062 eff_buf.token = (char *)buf;
Andy Greenb45993c2010-12-18 15:13:50 +00002063
Andy Green98a717c2011-03-06 13:14:15 +00002064 more = 1;
2065 while (more) {
Andy Green0d338332011-02-12 11:57:43 +00002066
Andy Green98a717c2011-03-06 13:14:15 +00002067 more = 0;
2068
2069 for (n = 0; n < wsi->count_active_extensions; n++) {
Andy Green46c2ea02011-03-22 09:04:01 +00002070 m = wsi->active_extensions[n]->callback(context,
2071 wsi->active_extensions[n], wsi,
Andy Green98a717c2011-03-06 13:14:15 +00002072 LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
Andy Green46c2ea02011-03-22 09:04:01 +00002073 wsi->active_extensions_user[n],
2074 &eff_buf, 0);
Andy Green98a717c2011-03-06 13:14:15 +00002075 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002076 lwsl_ext(
Andy Green6ee372f2012-04-09 15:09:01 +08002077 "Extension reports fatal error\n");
2078 libwebsocket_close_and_free_session(
2079 context, wsi,
2080 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green98a717c2011-03-06 13:14:15 +00002081 return 1;
2082 }
2083 if (m)
2084 more = 1;
2085 }
2086
2087 /* service incoming data */
2088
2089 if (eff_buf.token_len) {
2090 n = libwebsocket_read(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002091 (unsigned char *)eff_buf.token,
2092 eff_buf.token_len);
Andy Green98a717c2011-03-06 13:14:15 +00002093 if (n < 0)
2094 /* we closed wsi */
2095 return 1;
2096 }
2097
2098 eff_buf.token = NULL;
2099 eff_buf.token_len = 0;
2100 }
David Galeano7ffbe1b2013-01-10 10:35:32 +08002101
2102#ifdef LWS_OPENSSL_SUPPORT
2103 if (wsi->ssl && SSL_pending(wsi->ssl))
2104 goto read_pending;
2105#endif
Andy Green98a717c2011-03-06 13:14:15 +00002106 break;
Andy Greenb45993c2010-12-18 15:13:50 +00002107 }
2108
2109 return 0;
2110}
2111
Andy Green0d338332011-02-12 11:57:43 +00002112
Andy Green6964bb52011-01-23 16:50:33 +00002113/**
2114 * libwebsocket_context_destroy() - Destroy the websocket context
Peter Hinz56885f32011-03-02 22:03:47 +00002115 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002116 *
2117 * This function closes any active connections and then frees the
2118 * context. After calling this, any further use of the context is
2119 * undefined.
2120 */
2121void
Peter Hinz56885f32011-03-02 22:03:47 +00002122libwebsocket_context_destroy(struct libwebsocket_context *context)
Andy Green6964bb52011-01-23 16:50:33 +00002123{
Andy Green0d338332011-02-12 11:57:43 +00002124 int n;
2125 int m;
2126 struct libwebsocket *wsi;
Andy Greena41314f2011-05-23 10:00:03 +01002127 struct libwebsocket_extension *ext;
Andy Green6964bb52011-01-23 16:50:33 +00002128
Andy Green4b6fbe12011-02-14 08:03:48 +00002129 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002130 for (m = 0; m < context->fd_hashtable[n].length; m++) {
2131 wsi = context->fd_hashtable[n].wsi[m];
2132 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002133 LWS_CLOSE_STATUS_GOINGAWAY);
Andy Greenf3d3b402011-02-09 07:16:34 +00002134 }
Andy Green6964bb52011-01-23 16:50:33 +00002135
Andy Greena41314f2011-05-23 10:00:03 +01002136 /*
2137 * give all extensions a chance to clean up any per-context
2138 * allocations they might have made
2139 */
2140
2141 ext = context->extensions;
2142 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
2143 if (context->listen_port)
2144 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
Paulo Roberto Urio1f680ab2012-06-04 08:40:28 +08002145 while (ext && ext->callback) {
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002146 ext->callback(context, ext, NULL, (enum libwebsocket_extension_callback_reasons)m, NULL, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01002147 ext++;
2148 }
2149
Peter Hinz56885f32011-03-02 22:03:47 +00002150#ifdef WIN32
2151#else
2152 close(context->fd_random);
Andy Green6964bb52011-01-23 16:50:33 +00002153#endif
2154
Peter Hinz56885f32011-03-02 22:03:47 +00002155#ifdef LWS_OPENSSL_SUPPORT
2156 if (context->ssl_ctx)
2157 SSL_CTX_free(context->ssl_ctx);
2158 if (context->ssl_client_ctx)
2159 SSL_CTX_free(context->ssl_client_ctx);
2160#endif
2161
2162 free(context);
2163
2164#ifdef WIN32
2165 WSACleanup();
2166#endif
Andy Green6964bb52011-01-23 16:50:33 +00002167}
2168
Alon Levy0291eb32012-10-19 11:21:56 +02002169LWS_EXTERN void *
2170libwebsocket_context_user(struct libwebsocket_context *context)
2171{
2172 return context->user_space;
2173}
2174
Andy Green6964bb52011-01-23 16:50:33 +00002175/**
2176 * libwebsocket_service() - Service any pending websocket activity
Peter Hinz56885f32011-03-02 22:03:47 +00002177 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002178 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
2179 * service otherwise block and service immediately, returning
2180 * after the timeout if nothing needed service.
2181 *
2182 * This function deals with any pending websocket traffic, for three
2183 * kinds of event. It handles these events on both server and client
2184 * types of connection the same.
2185 *
2186 * 1) Accept new connections to our context's server
2187 *
2188 * 2) Perform pending broadcast writes initiated from other forked
2189 * processes (effectively serializing asynchronous broadcasts)
2190 *
2191 * 3) Call the receive callback for incoming frame data received by
2192 * server or client connections.
2193 *
2194 * You need to call this service function periodically to all the above
2195 * functions to happen; if your application is single-threaded you can
2196 * just call it in your main event loop.
2197 *
2198 * Alternatively you can fork a new process that asynchronously handles
2199 * calling this service in a loop. In that case you are happy if this
2200 * call blocks your thread until it needs to take care of something and
2201 * would call it with a large nonzero timeout. Your loop then takes no
2202 * CPU while there is nothing happening.
2203 *
2204 * If you are calling it in a single-threaded app, you don't want it to
2205 * wait around blocking other things in your loop from happening, so you
2206 * would call it with a timeout_ms of 0, so it returns immediately if
2207 * nothing is pending, or as soon as it services whatever was pending.
2208 */
2209
Andy Greenb45993c2010-12-18 15:13:50 +00002210
Andy Greene92cd172011-01-19 13:11:55 +00002211int
Peter Hinz56885f32011-03-02 22:03:47 +00002212libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
Andy Greene92cd172011-01-19 13:11:55 +00002213{
2214 int n;
Andy Greene92cd172011-01-19 13:11:55 +00002215
2216 /* stay dead once we are dead */
2217
Peter Hinz56885f32011-03-02 22:03:47 +00002218 if (context == NULL)
Andy Greene92cd172011-01-19 13:11:55 +00002219 return 1;
2220
Andy Green0d338332011-02-12 11:57:43 +00002221 /* wait for something to need service */
Andy Green4739e5c2011-01-22 12:51:57 +00002222
Peter Hinz56885f32011-03-02 22:03:47 +00002223 n = poll(context->fds, context->fds_count, timeout_ms);
Andy Green3221f922011-02-12 13:14:11 +00002224 if (n == 0) /* poll timeout */
2225 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002226
Andy Green62c54d22011-02-14 09:14:25 +00002227 if (n < 0) {
Andy Green5e1fa172011-02-10 09:07:05 +00002228 /*
Andy Green43db0452013-01-10 19:50:35 +08002229 lwsl_err("Listen Socket dead\n");
Andy Green5e1fa172011-02-10 09:07:05 +00002230 */
Andy Green3928f612012-07-20 12:58:38 +08002231 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002232 }
Andy Greene92cd172011-01-19 13:11:55 +00002233
2234 /* handle accept on listening socket? */
2235
Peter Hinz56885f32011-03-02 22:03:47 +00002236 for (n = 0; n < context->fds_count; n++)
2237 if (context->fds[n].revents)
Andy Green3928f612012-07-20 12:58:38 +08002238 if (libwebsocket_service_fd(context,
2239 &context->fds[n]) < 0)
2240 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002241 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002242}
2243
Andy Greena41314f2011-05-23 10:00:03 +01002244int
2245lws_any_extension_handled(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002246 struct libwebsocket *wsi,
2247 enum libwebsocket_extension_callback_reasons r,
Andy Greena41314f2011-05-23 10:00:03 +01002248 void *v, size_t len)
2249{
2250 int n;
2251 int handled = 0;
2252
2253 /* maybe an extension will take care of it for us */
2254
2255 for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
2256 if (!wsi->active_extensions[n]->callback)
2257 continue;
2258
2259 handled |= wsi->active_extensions[n]->callback(context,
2260 wsi->active_extensions[n], wsi,
2261 r, wsi->active_extensions_user[n], v, len);
2262 }
2263
2264 return handled;
2265}
2266
2267
2268void *
2269lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002270 struct libwebsocket_extension *ext)
Andy Greena41314f2011-05-23 10:00:03 +01002271{
2272 int n = 0;
2273
Andy Green68b45042011-05-25 21:41:57 +01002274 if (wsi == NULL)
2275 return NULL;
2276
Andy Greena41314f2011-05-23 10:00:03 +01002277 while (n < wsi->count_active_extensions) {
2278 if (wsi->active_extensions[n] != ext) {
2279 n++;
2280 continue;
2281 }
2282 return wsi->active_extensions_user[n];
2283 }
2284
2285 return NULL;
2286}
2287
Andy Green90c7cbc2011-01-27 06:26:52 +00002288/**
2289 * libwebsocket_callback_on_writable() - Request a callback when this socket
2290 * becomes able to be written to without
2291 * blocking
Andy Green32375b72011-02-19 08:32:53 +00002292 *
Peter Hinz56885f32011-03-02 22:03:47 +00002293 * @context: libwebsockets context
Andy Green90c7cbc2011-01-27 06:26:52 +00002294 * @wsi: Websocket connection instance to get callback for
2295 */
2296
2297int
Peter Hinz56885f32011-03-02 22:03:47 +00002298libwebsocket_callback_on_writable(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002299 struct libwebsocket *wsi)
Andy Green90c7cbc2011-01-27 06:26:52 +00002300{
Andy Green90c7cbc2011-01-27 06:26:52 +00002301 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002302 int handled = 0;
2303
2304 /* maybe an extension will take care of it for us */
2305
2306 for (n = 0; n < wsi->count_active_extensions; n++) {
2307 if (!wsi->active_extensions[n]->callback)
2308 continue;
2309
2310 handled |= wsi->active_extensions[n]->callback(context,
2311 wsi->active_extensions[n], wsi,
2312 LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
2313 wsi->active_extensions_user[n], NULL, 0);
2314 }
2315
2316 if (handled)
2317 return 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002318
Peter Hinz56885f32011-03-02 22:03:47 +00002319 for (n = 0; n < context->fds_count; n++)
2320 if (context->fds[n].fd == wsi->sock) {
2321 context->fds[n].events |= POLLOUT;
Andy Greena41314f2011-05-23 10:00:03 +01002322 n = context->fds_count + 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002323 }
2324
Andy Greena41314f2011-05-23 10:00:03 +01002325 if (n == context->fds_count)
Andy Green43db0452013-01-10 19:50:35 +08002326 lwsl_err("libwebsocket_callback_on_writable: "
Andy Green6ee372f2012-04-09 15:09:01 +08002327 "failed to find socket %d\n", wsi->sock);
Andy Greena41314f2011-05-23 10:00:03 +01002328
Andy Green3221f922011-02-12 13:14:11 +00002329 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002330 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002331 LWS_CALLBACK_SET_MODE_POLL_FD,
2332 (void *)(long)wsi->sock, NULL, POLLOUT);
2333
Andy Green90c7cbc2011-01-27 06:26:52 +00002334 return 1;
2335}
2336
2337/**
2338 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
2339 * all connections using the given protocol when it
2340 * becomes possible to write to each socket without
2341 * blocking in turn.
2342 *
2343 * @protocol: Protocol whose connections will get callbacks
2344 */
2345
2346int
2347libwebsocket_callback_on_writable_all_protocol(
2348 const struct libwebsocket_protocols *protocol)
2349{
Peter Hinz56885f32011-03-02 22:03:47 +00002350 struct libwebsocket_context *context = protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002351 int n;
Andy Green0d338332011-02-12 11:57:43 +00002352 int m;
2353 struct libwebsocket *wsi;
Andy Green90c7cbc2011-01-27 06:26:52 +00002354
Andy Green0d338332011-02-12 11:57:43 +00002355 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
2356
Peter Hinz56885f32011-03-02 22:03:47 +00002357 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Green0d338332011-02-12 11:57:43 +00002358
Peter Hinz56885f32011-03-02 22:03:47 +00002359 wsi = context->fd_hashtable[n].wsi[m];
Andy Green0d338332011-02-12 11:57:43 +00002360
2361 if (wsi->protocol == protocol)
Peter Hinz56885f32011-03-02 22:03:47 +00002362 libwebsocket_callback_on_writable(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002363 }
2364 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002365
2366 return 0;
2367}
2368
Andy Greenbe93fef2011-02-14 20:25:43 +00002369/**
2370 * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
2371 *
2372 * You will not need this unless you are doing something special
2373 *
2374 * @wsi: Websocket connection instance
2375 * @reason: timeout reason
2376 * @secs: how many seconds
2377 */
2378
2379void
2380libwebsocket_set_timeout(struct libwebsocket *wsi,
2381 enum pending_timeout reason, int secs)
2382{
2383 struct timeval tv;
2384
2385 gettimeofday(&tv, NULL);
2386
2387 wsi->pending_timeout_limit = tv.tv_sec + secs;
2388 wsi->pending_timeout = reason;
2389}
2390
Andy Greena6cbece2011-01-27 20:06:03 +00002391
2392/**
2393 * libwebsocket_get_socket_fd() - returns the socket file descriptor
2394 *
2395 * You will not need this unless you are doing something special
2396 *
2397 * @wsi: Websocket connection instance
2398 */
2399
2400int
2401libwebsocket_get_socket_fd(struct libwebsocket *wsi)
2402{
2403 return wsi->sock;
2404}
2405
Andy Green90c7cbc2011-01-27 06:26:52 +00002406/**
2407 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
2408 * receieved packets.
2409 *
2410 * If the output side of a server process becomes choked, this allows flow
2411 * control for the input side.
2412 *
2413 * @wsi: Websocket connection instance to get callback for
2414 * @enable: 0 = disable read servicing for this connection, 1 = enable
2415 */
2416
2417int
2418libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
2419{
Peter Hinz56885f32011-03-02 22:03:47 +00002420 struct libwebsocket_context *context = wsi->protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002421 int n;
2422
Peter Hinz56885f32011-03-02 22:03:47 +00002423 for (n = 0; n < context->fds_count; n++)
2424 if (context->fds[n].fd == wsi->sock) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002425 if (enable)
Peter Hinz56885f32011-03-02 22:03:47 +00002426 context->fds[n].events |= POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002427 else
Peter Hinz56885f32011-03-02 22:03:47 +00002428 context->fds[n].events &= ~POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002429
2430 return 0;
2431 }
2432
Andy Green3221f922011-02-12 13:14:11 +00002433 if (enable)
2434 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002435 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002436 LWS_CALLBACK_SET_MODE_POLL_FD,
2437 (void *)(long)wsi->sock, NULL, POLLIN);
2438 else
2439 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002440 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002441 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
2442 (void *)(long)wsi->sock, NULL, POLLIN);
2443
Andy Greena41314f2011-05-23 10:00:03 +01002444#if 0
Andy Green43db0452013-01-10 19:50:35 +08002445 lwsl_err("libwebsocket_rx_flow_control unable to find socket\n");
Andy Greena41314f2011-05-23 10:00:03 +01002446#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002447 return 1;
2448}
2449
Andy Green2ac5a6f2011-01-28 10:00:18 +00002450/**
2451 * libwebsocket_canonical_hostname() - returns this host's hostname
2452 *
2453 * This is typically used by client code to fill in the host parameter
2454 * when making a client connection. You can only call it after the context
2455 * has been created.
2456 *
Peter Hinz56885f32011-03-02 22:03:47 +00002457 * @context: Websocket context
Andy Green2ac5a6f2011-01-28 10:00:18 +00002458 */
2459
2460
2461extern const char *
Peter Hinz56885f32011-03-02 22:03:47 +00002462libwebsocket_canonical_hostname(struct libwebsocket_context *context)
Andy Green2ac5a6f2011-01-28 10:00:18 +00002463{
Peter Hinz56885f32011-03-02 22:03:47 +00002464 return (const char *)context->canonical_hostname;
Andy Green2ac5a6f2011-01-28 10:00:18 +00002465}
2466
2467
Andy Green90c7cbc2011-01-27 06:26:52 +00002468static void sigpipe_handler(int x)
2469{
2470}
2471
Andy Green6901cb32011-02-21 08:06:47 +00002472#ifdef LWS_OPENSSL_SUPPORT
2473static int
2474OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
2475{
2476
2477 SSL *ssl;
2478 int n;
Andy Green2e24da02011-03-05 16:12:04 +00002479 struct libwebsocket_context *context;
Andy Green6901cb32011-02-21 08:06:47 +00002480
2481 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
2482 SSL_get_ex_data_X509_STORE_CTX_idx());
2483
2484 /*
Andy Green2e24da02011-03-05 16:12:04 +00002485 * !!! nasty openssl requires the index to come as a library-scope
2486 * static
Andy Green6901cb32011-02-21 08:06:47 +00002487 */
Andy Green2e24da02011-03-05 16:12:04 +00002488 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
Andy Green6ee372f2012-04-09 15:09:01 +08002489
Peter Hinz56885f32011-03-02 22:03:47 +00002490 n = context->protocols[0].callback(NULL, NULL,
Andy Green6901cb32011-02-21 08:06:47 +00002491 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
2492 x509_ctx, ssl, preverify_ok);
2493
2494 /* convert return code from 0 = OK to 1 = OK */
2495
2496 if (!n)
2497 n = 1;
2498 else
2499 n = 0;
2500
2501 return n;
2502}
2503#endif
2504
Andy Greenb45993c2010-12-18 15:13:50 +00002505
Andy Greenab990e42010-10-31 12:42:52 +00002506/**
Andy Green4739e5c2011-01-22 12:51:57 +00002507 * libwebsocket_create_context() - Create the websocket handler
2508 * @port: Port to listen on... you can use 0 to suppress listening on
Andy Green6964bb52011-01-23 16:50:33 +00002509 * any port, that's what you want if you are not running a
2510 * websocket server at all but just using it as a client
Peter Hinz56885f32011-03-02 22:03:47 +00002511 * @interf: NULL to bind the listen socket to all interfaces, or the
Andy Green32375b72011-02-19 08:32:53 +00002512 * interface name, eg, "eth2"
Andy Green4f3943a2010-11-12 10:44:16 +00002513 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +00002514 * specific callback for each one. The list is ended with an
2515 * entry that has a NULL callback pointer.
Andy Green6964bb52011-01-23 16:50:33 +00002516 * It's not const because we write the owning_server member
Andy Greenc5114822011-03-06 10:29:35 +00002517 * @extensions: NULL or array of libwebsocket_extension structs listing the
Andy Green6ee372f2012-04-09 15:09:01 +08002518 * extensions this context supports
Andy Green3faa9c72010-11-08 17:03:03 +00002519 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +00002520 * to listen using SSL, set to the filepath to fetch the
2521 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +00002522 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +00002523 * else ignored
David Galeano2f82be82013-01-09 16:25:54 +08002524 * @ssl_ca_filepath: CA certificate filepath or NULL
Andy Green3faa9c72010-11-08 17:03:03 +00002525 * @gid: group id to change to after setting listen socket, or -1.
2526 * @uid: user id to change to after setting listen socket, or -1.
Andy Greenbfb051f2011-02-09 08:49:14 +00002527 * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
Andy Green15e31f32012-10-19 18:36:28 +08002528 * @user: optional user pointer that can be recovered via the context
2529 * pointer using libwebsocket_context_user
Andy Green05464c62010-11-12 10:44:18 +00002530 *
Andy Green8f037e42010-12-19 22:13:26 +00002531 * This function creates the listening socket and takes care
2532 * of all initialization in one step.
2533 *
Andy Greene92cd172011-01-19 13:11:55 +00002534 * After initialization, it returns a struct libwebsocket_context * that
2535 * represents this server. After calling, user code needs to take care
2536 * of calling libwebsocket_service() with the context pointer to get the
2537 * server's sockets serviced. This can be done in the same process context
2538 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +00002539 *
Andy Green8f037e42010-12-19 22:13:26 +00002540 * The protocol callback functions are called for a handful of events
2541 * including http requests coming in, websocket connections becoming
2542 * established, and data arriving; it's also called periodically to allow
2543 * async transmission.
2544 *
2545 * HTTP requests are sent always to the FIRST protocol in @protocol, since
2546 * at that time websocket protocol has not been negotiated. Other
2547 * protocols after the first one never see any HTTP callack activity.
2548 *
2549 * The server created is a simple http server by default; part of the
2550 * websocket standard is upgrading this http connection to a websocket one.
2551 *
2552 * This allows the same server to provide files like scripts and favicon /
2553 * images or whatever over http and dynamic data over websockets all in
2554 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +00002555 */
Andy Green4ea60062010-10-30 12:15:07 +01002556
Andy Greene92cd172011-01-19 13:11:55 +00002557struct libwebsocket_context *
Peter Hinz56885f32011-03-02 22:03:47 +00002558libwebsocket_create_context(int port, const char *interf,
Andy Greenb45993c2010-12-18 15:13:50 +00002559 struct libwebsocket_protocols *protocols,
Andy Greend6e09112011-03-05 16:12:15 +00002560 struct libwebsocket_extension *extensions,
Andy Green8f037e42010-12-19 22:13:26 +00002561 const char *ssl_cert_filepath,
2562 const char *ssl_private_key_filepath,
David Galeano2f82be82013-01-09 16:25:54 +08002563 const char *ssl_ca_filepath,
Alon Levy0291eb32012-10-19 11:21:56 +02002564 int gid, int uid, unsigned int options,
David Galeano2f82be82013-01-09 16:25:54 +08002565 void *user)
Andy Greenff95d7a2010-10-28 22:36:01 +01002566{
2567 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002568 int m;
Andy Green4739e5c2011-01-22 12:51:57 +00002569 int sockfd = 0;
Andy Green251f6fa2010-11-03 11:13:06 +00002570 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +01002571 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +00002572 int opt = 1;
Peter Hinz56885f32011-03-02 22:03:47 +00002573 struct libwebsocket_context *context = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002574 unsigned int slen;
Andy Green9659f372011-01-27 22:01:43 +00002575 char *p;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002576 char hostname[1024] = "";
Andy Greena69f0512012-05-03 12:32:38 +08002577// struct hostent *he;
Andy Green0d338332011-02-12 11:57:43 +00002578 struct libwebsocket *wsi;
Andy Greena69f0512012-05-03 12:32:38 +08002579 struct sockaddr sa;
Andy Greenff95d7a2010-10-28 22:36:01 +01002580
Andy Green3faa9c72010-11-08 17:03:03 +00002581#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +00002582 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +00002583 char ssl_err_buf[512];
Andy Green3faa9c72010-11-08 17:03:03 +00002584#endif
2585
Andy Green43db0452013-01-10 19:50:35 +08002586 lwsl_info("Initial logging level %d\n", log_level);
2587
Peter Hinz56885f32011-03-02 22:03:47 +00002588#ifdef _WIN32
2589 {
2590 WORD wVersionRequested;
2591 WSADATA wsaData;
2592 int err;
Andy Green6ee372f2012-04-09 15:09:01 +08002593 HMODULE wsdll;
Peter Hinz56885f32011-03-02 22:03:47 +00002594
2595 /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
2596 wVersionRequested = MAKEWORD(2, 2);
2597
2598 err = WSAStartup(wVersionRequested, &wsaData);
2599 if (err != 0) {
2600 /* Tell the user that we could not find a usable */
2601 /* Winsock DLL. */
Andy Green43db0452013-01-10 19:50:35 +08002602 lwsl_err("WSAStartup failed with error: %d\n", err);
Peter Hinz56885f32011-03-02 22:03:47 +00002603 return NULL;
2604 }
David Galeano7b11fec2011-10-04 19:55:18 +08002605
Andy Green6ee372f2012-04-09 15:09:01 +08002606 /* default to a poll() made out of select() */
2607 poll = emulated_poll;
David Galeano7b11fec2011-10-04 19:55:18 +08002608
Andy Green6ee372f2012-04-09 15:09:01 +08002609 /* if windows socket lib available, use his WSAPoll */
David Galeanocb193682013-01-09 15:29:00 +08002610 wsdll = GetModuleHandle(_T("Ws2_32.dll"));
Andy Green6ee372f2012-04-09 15:09:01 +08002611 if (wsdll)
2612 poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
Peter Hinz56885f32011-03-02 22:03:47 +00002613 }
2614#endif
2615
2616
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002617 context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context));
Peter Hinz56885f32011-03-02 22:03:47 +00002618 if (!context) {
Andy Green43db0452013-01-10 19:50:35 +08002619 lwsl_err("No memory for websocket context\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002620 return NULL;
2621 }
Peter Hinz56885f32011-03-02 22:03:47 +00002622 context->protocols = protocols;
2623 context->listen_port = port;
2624 context->http_proxy_port = 0;
2625 context->http_proxy_address[0] = '\0';
2626 context->options = options;
2627 context->fds_count = 0;
Andy Greend6e09112011-03-05 16:12:15 +00002628 context->extensions = extensions;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002629 context->last_timeout_check_s = 0;
Alon Levy0291eb32012-10-19 11:21:56 +02002630 context->user_space = user;
Andy Green9659f372011-01-27 22:01:43 +00002631
Peter Hinz56885f32011-03-02 22:03:47 +00002632#ifdef WIN32
2633 context->fd_random = 0;
2634#else
2635 context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
2636 if (context->fd_random < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002637 lwsl_err("Unable to open random device %s %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002638 SYSTEM_RANDOM_FILEPATH, context->fd_random);
Andy Green44eee682011-02-10 09:32:24 +00002639 return NULL;
2640 }
Peter Hinz56885f32011-03-02 22:03:47 +00002641#endif
Andy Green44eee682011-02-10 09:32:24 +00002642
Peter Hinz56885f32011-03-02 22:03:47 +00002643#ifdef LWS_OPENSSL_SUPPORT
2644 context->use_ssl = 0;
2645 context->ssl_ctx = NULL;
2646 context->ssl_client_ctx = NULL;
Andy Green2e24da02011-03-05 16:12:04 +00002647 openssl_websocket_private_data_index = 0;
Peter Hinz56885f32011-03-02 22:03:47 +00002648#endif
Andy Green2ac5a6f2011-01-28 10:00:18 +00002649
Andy Green788c4a82012-10-22 12:29:57 +01002650 if (options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME) {
Andy Greena69f0512012-05-03 12:32:38 +08002651
Andy Green788c4a82012-10-22 12:29:57 +01002652 strcpy(context->canonical_hostname, "unknown");
Andy Greena69f0512012-05-03 12:32:38 +08002653
Andy Green788c4a82012-10-22 12:29:57 +01002654 } else {
2655
2656 /* find canonical hostname */
2657
2658 hostname[(sizeof hostname) - 1] = '\0';
2659 memset(&sa, 0, sizeof(sa));
2660 sa.sa_family = AF_INET;
2661 sa.sa_data[(sizeof sa.sa_data) - 1] = '\0';
2662 gethostname(hostname, (sizeof hostname) - 1);
2663
2664 n = 0;
2665
David Galeanoed3c8402013-01-10 10:45:24 +08002666 if (strlen(hostname) < sizeof(sa.sa_data) - 1) {
Andy Green788c4a82012-10-22 12:29:57 +01002667 strcpy(sa.sa_data, hostname);
Andy Green43db0452013-01-10 19:50:35 +08002668 // lwsl_debug("my host name is %s\n", sa.sa_data);
Andy Green788c4a82012-10-22 12:29:57 +01002669 n = getnameinfo(&sa, sizeof(sa), hostname,
2670 (sizeof hostname) - 1, NULL, 0, 0);
2671 }
2672
2673 if (!n) {
2674 strncpy(context->canonical_hostname, hostname,
2675 sizeof context->canonical_hostname - 1);
2676 context->canonical_hostname[
2677 sizeof context->canonical_hostname - 1] = '\0';
2678 } else
2679 strncpy(context->canonical_hostname, hostname,
2680 sizeof context->canonical_hostname - 1);
2681
Andy Green43db0452013-01-10 19:50:35 +08002682 // lwsl_debug("context->canonical_hostname = %s\n",
Andy Green788c4a82012-10-22 12:29:57 +01002683 // context->canonical_hostname);
Andy Greena69f0512012-05-03 12:32:38 +08002684 }
2685
Andy Green9659f372011-01-27 22:01:43 +00002686 /* split the proxy ads:port if given */
2687
2688 p = getenv("http_proxy");
2689 if (p) {
Peter Hinz56885f32011-03-02 22:03:47 +00002690 strncpy(context->http_proxy_address, p,
Andy Green6ee372f2012-04-09 15:09:01 +08002691 sizeof context->http_proxy_address - 1);
Peter Hinz56885f32011-03-02 22:03:47 +00002692 context->http_proxy_address[
2693 sizeof context->http_proxy_address - 1] = '\0';
Andy Green9659f372011-01-27 22:01:43 +00002694
Peter Hinz56885f32011-03-02 22:03:47 +00002695 p = strchr(context->http_proxy_address, ':');
Andy Green9659f372011-01-27 22:01:43 +00002696 if (p == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002697 lwsl_err("http_proxy needs to be ads:port\n");
Andy Green9659f372011-01-27 22:01:43 +00002698 return NULL;
2699 }
2700 *p = '\0';
Peter Hinz56885f32011-03-02 22:03:47 +00002701 context->http_proxy_port = atoi(p + 1);
Andy Green9659f372011-01-27 22:01:43 +00002702
Andy Green43db0452013-01-10 19:50:35 +08002703 lwsl_debug("Using proxy %s:%u\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002704 context->http_proxy_address,
2705 context->http_proxy_port);
Andy Green9659f372011-01-27 22:01:43 +00002706 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002707
2708 if (port) {
2709
Andy Green3faa9c72010-11-08 17:03:03 +00002710#ifdef LWS_OPENSSL_SUPPORT
Peter Hinz56885f32011-03-02 22:03:47 +00002711 context->use_ssl = ssl_cert_filepath != NULL &&
Andy Green90c7cbc2011-01-27 06:26:52 +00002712 ssl_private_key_filepath != NULL;
Peter Hinz56885f32011-03-02 22:03:47 +00002713 if (context->use_ssl)
Andy Green43db0452013-01-10 19:50:35 +08002714 lwsl_info(" Compiled with SSL support, using it\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002715 else
Andy Green43db0452013-01-10 19:50:35 +08002716 lwsl_info(" Compiled with SSL support, not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +00002717
Andy Green90c7cbc2011-01-27 06:26:52 +00002718#else
2719 if (ssl_cert_filepath != NULL &&
2720 ssl_private_key_filepath != NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002721 lwsl_info(" Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +00002722 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002723 }
Andy Green43db0452013-01-10 19:50:35 +08002724 lwsl_info(" Compiled without SSL support, "
Andy Green90c7cbc2011-01-27 06:26:52 +00002725 "serving unencrypted\n");
2726#endif
2727 }
2728
2729 /* ignore SIGPIPE */
Peter Hinz56885f32011-03-02 22:03:47 +00002730#ifdef WIN32
2731#else
Andy Green90c7cbc2011-01-27 06:26:52 +00002732 signal(SIGPIPE, sigpipe_handler);
Peter Hinz56885f32011-03-02 22:03:47 +00002733#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002734
2735
2736#ifdef LWS_OPENSSL_SUPPORT
2737
2738 /* basic openssl init */
2739
2740 SSL_library_init();
2741
2742 OpenSSL_add_all_algorithms();
2743 SSL_load_error_strings();
2744
Andy Green2e24da02011-03-05 16:12:04 +00002745 openssl_websocket_private_data_index =
Andy Green6901cb32011-02-21 08:06:47 +00002746 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
2747
Andy Green90c7cbc2011-01-27 06:26:52 +00002748 /*
2749 * Firefox insists on SSLv23 not SSLv3
2750 * Konq disables SSLv2 by default now, SSLv23 works
2751 */
2752
2753 method = (SSL_METHOD *)SSLv23_server_method();
2754 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002755 lwsl_err("problem creating ssl method: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002756 ERR_error_string(ERR_get_error(), ssl_err_buf));
2757 return NULL;
2758 }
Peter Hinz56885f32011-03-02 22:03:47 +00002759 context->ssl_ctx = SSL_CTX_new(method); /* create context */
2760 if (!context->ssl_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002761 lwsl_err("problem creating ssl context: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002762 ERR_error_string(ERR_get_error(), ssl_err_buf));
2763 return NULL;
2764 }
2765
David Galeanocc148e42013-01-10 10:18:59 +08002766#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002767 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002768#endif
David Galeano77a677c2013-01-10 10:14:12 +08002769 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002770 SSL_CTX_set_cipher_list(context->ssl_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002771
Andy Green90c7cbc2011-01-27 06:26:52 +00002772 /* client context */
Andy Green6ee372f2012-04-09 15:09:01 +08002773
2774 if (port == CONTEXT_PORT_NO_LISTEN) {
Peter Hinz56885f32011-03-02 22:03:47 +00002775 method = (SSL_METHOD *)SSLv23_client_method();
2776 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002777 lwsl_err("problem creating ssl method: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002778 ERR_error_string(ERR_get_error(), ssl_err_buf));
2779 return NULL;
2780 }
2781 /* create context */
2782 context->ssl_client_ctx = SSL_CTX_new(method);
2783 if (!context->ssl_client_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002784 lwsl_err("problem creating ssl context: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002785 ERR_error_string(ERR_get_error(), ssl_err_buf));
2786 return NULL;
2787 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002788
David Galeanocc148e42013-01-10 10:18:59 +08002789#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002790 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002791#endif
David Galeano77a677c2013-01-10 10:14:12 +08002792 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002793 SSL_CTX_set_cipher_list(context->ssl_client_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002794
Peter Hinz56885f32011-03-02 22:03:47 +00002795 /* openssl init for cert verification (for client sockets) */
David Galeano2f82be82013-01-09 16:25:54 +08002796 if (!ssl_ca_filepath) {
2797 if (!SSL_CTX_load_verify_locations(
2798 context->ssl_client_ctx, NULL,
2799 LWS_OPENSSL_CLIENT_CERTS))
Andy Green43db0452013-01-10 19:50:35 +08002800 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002801 "Unable to load SSL Client certs from %s "
2802 "(set by --with-client-cert-dir= in configure) -- "
2803 " client ssl isn't going to work",
2804 LWS_OPENSSL_CLIENT_CERTS);
2805 } else
2806 if (!SSL_CTX_load_verify_locations(
2807 context->ssl_client_ctx, ssl_ca_filepath,
2808 NULL))
Andy Green43db0452013-01-10 19:50:35 +08002809 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002810 "Unable to load SSL Client certs "
2811 "file from %s -- client ssl isn't "
2812 "going to work", ssl_ca_filepath);
Peter Hinz56885f32011-03-02 22:03:47 +00002813
2814 /*
2815 * callback allowing user code to load extra verification certs
2816 * helping the client to verify server identity
2817 */
2818
2819 context->protocols[0].callback(context, NULL,
2820 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
2821 context->ssl_client_ctx, NULL, 0);
Andy Green90c7cbc2011-01-27 06:26:52 +00002822 }
Andy Green6ee372f2012-04-09 15:09:01 +08002823
Andy Greenc6bf2c22011-02-20 11:10:47 +00002824 /* as a server, are we requiring clients to identify themselves? */
2825
2826 if (options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
2827
2828 /* absolutely require the client cert */
Andy Green6ee372f2012-04-09 15:09:01 +08002829
Peter Hinz56885f32011-03-02 22:03:47 +00002830 SSL_CTX_set_verify(context->ssl_ctx,
Andy Green6901cb32011-02-21 08:06:47 +00002831 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2832 OpenSSL_verify_callback);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002833
2834 /*
2835 * give user code a chance to load certs into the server
2836 * allowing it to verify incoming client certs
2837 */
2838
Peter Hinz56885f32011-03-02 22:03:47 +00002839 context->protocols[0].callback(context, NULL,
Andy Greenc6bf2c22011-02-20 11:10:47 +00002840 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
Peter Hinz56885f32011-03-02 22:03:47 +00002841 context->ssl_ctx, NULL, 0);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002842 }
2843
Peter Hinz56885f32011-03-02 22:03:47 +00002844 if (context->use_ssl) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002845
2846 /* openssl init for server sockets */
2847
Andy Green3faa9c72010-11-08 17:03:03 +00002848 /* set the local certificate from CertFile */
David Galeano9b3d4b22013-01-10 10:11:21 +08002849 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
2850 ssl_cert_filepath);
Andy Green3faa9c72010-11-08 17:03:03 +00002851 if (n != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002852 lwsl_err("problem getting cert '%s': %s\n",
Andy Green3faa9c72010-11-08 17:03:03 +00002853 ssl_cert_filepath,
2854 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002855 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002856 }
2857 /* set the private key from KeyFile */
Peter Hinz56885f32011-03-02 22:03:47 +00002858 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
2859 ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002860 lwsl_err("ssl problem getting key '%s': %s\n",
Andy Green018d8eb2010-11-08 21:04:23 +00002861 ssl_private_key_filepath,
2862 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002863 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002864 }
2865 /* verify private key */
Peter Hinz56885f32011-03-02 22:03:47 +00002866 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
Andy Green43db0452013-01-10 19:50:35 +08002867 lwsl_err("Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +00002868 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002869 }
2870
2871 /* SSL is happy and has a cert it's content with */
2872 }
2873#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002874
Andy Greendf736162011-01-18 15:39:02 +00002875 /* selftest */
2876
2877 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +00002878 return NULL;
Andy Greendf736162011-01-18 15:39:02 +00002879
Andy Green0d338332011-02-12 11:57:43 +00002880 /* fd hashtable init */
2881
2882 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002883 context->fd_hashtable[n].length = 0;
Andy Green0d338332011-02-12 11:57:43 +00002884
Andy Greenb45993c2010-12-18 15:13:50 +00002885 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +00002886
Andy Green4739e5c2011-01-22 12:51:57 +00002887 if (port) {
Andy Green8f037e42010-12-19 22:13:26 +00002888
Andy Green4739e5c2011-01-22 12:51:57 +00002889 sockfd = socket(AF_INET, SOCK_STREAM, 0);
2890 if (sockfd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002891 lwsl_err("ERROR opening socket");
Andy Green4739e5c2011-01-22 12:51:57 +00002892 return NULL;
2893 }
Andy Green775c0dd2010-10-29 14:15:22 +01002894
Andy Green4739e5c2011-01-22 12:51:57 +00002895 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08002896 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
2897 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00002898
2899 /* Disable Nagle */
2900 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08002901 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
2902 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00002903
Andy Green4739e5c2011-01-22 12:51:57 +00002904 bzero((char *) &serv_addr, sizeof(serv_addr));
2905 serv_addr.sin_family = AF_INET;
Peter Hinz56885f32011-03-02 22:03:47 +00002906 if (interf == NULL)
Andy Green32375b72011-02-19 08:32:53 +00002907 serv_addr.sin_addr.s_addr = INADDR_ANY;
2908 else
Peter Hinz56885f32011-03-02 22:03:47 +00002909 interface_to_sa(interf, &serv_addr,
Andy Green32375b72011-02-19 08:32:53 +00002910 sizeof(serv_addr));
Andy Green4739e5c2011-01-22 12:51:57 +00002911 serv_addr.sin_port = htons(port);
2912
2913 n = bind(sockfd, (struct sockaddr *) &serv_addr,
2914 sizeof(serv_addr));
2915 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002916 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Green8f037e42010-12-19 22:13:26 +00002917 port, n, errno);
Andy Green4739e5c2011-01-22 12:51:57 +00002918 return NULL;
2919 }
Andy Green0d338332011-02-12 11:57:43 +00002920
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002921 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
2922 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00002923 wsi->sock = sockfd;
Andy Greend6e09112011-03-05 16:12:15 +00002924 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00002925 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
Peter Hinz56885f32011-03-02 22:03:47 +00002926 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002927
David Galeano36973092013-01-10 09:58:24 +08002928 listen(sockfd, SOMAXCONN);
Andy Green43db0452013-01-10 19:50:35 +08002929 lwsl_info(" Listening on port %d\n", port);
Andy Green0d338332011-02-12 11:57:43 +00002930
2931 /* list in the internal poll array */
Andy Green6ee372f2012-04-09 15:09:01 +08002932
Peter Hinz56885f32011-03-02 22:03:47 +00002933 context->fds[context->fds_count].fd = sockfd;
2934 context->fds[context->fds_count++].events = POLLIN;
Andy Green3221f922011-02-12 13:14:11 +00002935
2936 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002937 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002938 LWS_CALLBACK_ADD_POLL_FD,
2939 (void *)(long)sockfd, NULL, POLLIN);
2940
Andy Green8f037e42010-12-19 22:13:26 +00002941 }
Andy Greenb45993c2010-12-18 15:13:50 +00002942
Andy Green6ee372f2012-04-09 15:09:01 +08002943 /*
2944 * drop any root privs for this process
2945 * to listen on port < 1023 we would have needed root, but now we are
2946 * listening, we don't want the power for anything else
2947 */
Peter Hinz56885f32011-03-02 22:03:47 +00002948#ifdef WIN32
2949#else
Andy Green3faa9c72010-11-08 17:03:03 +00002950 if (gid != -1)
2951 if (setgid(gid))
Andy Green43db0452013-01-10 19:50:35 +08002952 lwsl_warn("setgid: %s\n", strerror(errno));
Andy Green3faa9c72010-11-08 17:03:03 +00002953 if (uid != -1)
2954 if (setuid(uid))
Andy Green43db0452013-01-10 19:50:35 +08002955 lwsl_warn("setuid: %s\n", strerror(errno));
Peter Hinz56885f32011-03-02 22:03:47 +00002956#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002957
2958 /* set up our internal broadcast trigger sockets per-protocol */
2959
Peter Hinz56885f32011-03-02 22:03:47 +00002960 for (context->count_protocols = 0;
2961 protocols[context->count_protocols].callback;
2962 context->count_protocols++) {
Andy Green2d1301e2011-05-24 10:14:41 +01002963
Andy Green43db0452013-01-10 19:50:35 +08002964 lwsl_parser(" Protocol: %s\n",
2965 protocols[context->count_protocols].name);
Andy Green2d1301e2011-05-24 10:14:41 +01002966
Peter Hinz56885f32011-03-02 22:03:47 +00002967 protocols[context->count_protocols].owning_server = context;
2968 protocols[context->count_protocols].protocol_index =
2969 context->count_protocols;
Andy Greenb45993c2010-12-18 15:13:50 +00002970
2971 fd = socket(AF_INET, SOCK_STREAM, 0);
2972 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002973 lwsl_err("ERROR opening socket");
Andy Greene92cd172011-01-19 13:11:55 +00002974 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002975 }
Andy Green8f037e42010-12-19 22:13:26 +00002976
Andy Greenb45993c2010-12-18 15:13:50 +00002977 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08002978 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt,
2979 sizeof(opt));
Andy Greenb45993c2010-12-18 15:13:50 +00002980
2981 bzero((char *) &serv_addr, sizeof(serv_addr));
2982 serv_addr.sin_family = AF_INET;
2983 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
2984 serv_addr.sin_port = 0; /* pick the port for us */
2985
2986 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
2987 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002988 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Greenb45993c2010-12-18 15:13:50 +00002989 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +00002990 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002991 }
2992
2993 slen = sizeof cli_addr;
2994 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
2995 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002996 lwsl_err("getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +00002997 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002998 }
Peter Hinz56885f32011-03-02 22:03:47 +00002999 protocols[context->count_protocols].broadcast_socket_port =
Andy Greenb45993c2010-12-18 15:13:50 +00003000 ntohs(cli_addr.sin_port);
3001 listen(fd, 5);
3002
Andy Green43db0452013-01-10 19:50:35 +08003003 lwsl_debug(" Protocol %s broadcast socket %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00003004 protocols[context->count_protocols].name,
Andy Greenb45993c2010-12-18 15:13:50 +00003005 ntohs(cli_addr.sin_port));
3006
Andy Green0d338332011-02-12 11:57:43 +00003007 /* dummy wsi per broadcast proxy socket */
3008
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003009 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
3010 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00003011 wsi->sock = fd;
3012 wsi->mode = LWS_CONNMODE_BROADCAST_PROXY_LISTENER;
Andy Greend6e09112011-03-05 16:12:15 +00003013 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00003014 /* note which protocol we are proxying */
Peter Hinz56885f32011-03-02 22:03:47 +00003015 wsi->protocol_index_for_broadcast_proxy =
3016 context->count_protocols;
3017 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00003018
3019 /* list in internal poll array */
3020
Peter Hinz56885f32011-03-02 22:03:47 +00003021 context->fds[context->fds_count].fd = fd;
3022 context->fds[context->fds_count].events = POLLIN;
3023 context->fds[context->fds_count].revents = 0;
3024 context->fds_count++;
Andy Green3221f922011-02-12 13:14:11 +00003025
3026 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00003027 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00003028 LWS_CALLBACK_ADD_POLL_FD,
3029 (void *)(long)fd, NULL, POLLIN);
Andy Greenb45993c2010-12-18 15:13:50 +00003030 }
3031
Andy Greena41314f2011-05-23 10:00:03 +01003032 /*
3033 * give all extensions a chance to create any per-context
3034 * allocations they need
3035 */
3036
3037 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
3038 if (port)
3039 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
Andrew Chambersd5512172012-05-20 08:17:09 +08003040
3041 if (extensions) {
3042 while (extensions->callback) {
Andy Green43db0452013-01-10 19:50:35 +08003043 lwsl_ext(" Extension: %s\n", extensions->name);
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003044 extensions->callback(context, extensions, NULL,
3045 (enum libwebsocket_extension_callback_reasons)m,
3046 NULL, NULL, 0);
Andrew Chambersd5512172012-05-20 08:17:09 +08003047 extensions++;
3048 }
Andy Greena41314f2011-05-23 10:00:03 +01003049 }
3050
Peter Hinz56885f32011-03-02 22:03:47 +00003051 return context;
Andy Greene92cd172011-01-19 13:11:55 +00003052}
Andy Greenb45993c2010-12-18 15:13:50 +00003053
Andy Green4739e5c2011-01-22 12:51:57 +00003054
Andy Greened11a022011-01-20 10:23:50 +00003055#ifndef LWS_NO_FORK
3056
Andy Greene92cd172011-01-19 13:11:55 +00003057/**
3058 * libwebsockets_fork_service_loop() - Optional helper function forks off
3059 * a process for the websocket server loop.
Andy Green6964bb52011-01-23 16:50:33 +00003060 * You don't have to use this but if not, you
3061 * have to make sure you are calling
3062 * libwebsocket_service periodically to service
3063 * the websocket traffic
Peter Hinz56885f32011-03-02 22:03:47 +00003064 * @context: server context returned by creation function
Andy Greene92cd172011-01-19 13:11:55 +00003065 */
Andy Greenb45993c2010-12-18 15:13:50 +00003066
Andy Greene92cd172011-01-19 13:11:55 +00003067int
Peter Hinz56885f32011-03-02 22:03:47 +00003068libwebsockets_fork_service_loop(struct libwebsocket_context *context)
Andy Greene92cd172011-01-19 13:11:55 +00003069{
Andy Greene92cd172011-01-19 13:11:55 +00003070 int fd;
3071 struct sockaddr_in cli_addr;
3072 int n;
Andy Green3221f922011-02-12 13:14:11 +00003073 int p;
Andy Greenb45993c2010-12-18 15:13:50 +00003074
Andy Greened11a022011-01-20 10:23:50 +00003075 n = fork();
3076 if (n < 0)
3077 return n;
3078
3079 if (!n) {
3080
3081 /* main process context */
3082
Andy Green3221f922011-02-12 13:14:11 +00003083 /*
3084 * set up the proxy sockets to allow broadcast from
3085 * service process context
3086 */
3087
Peter Hinz56885f32011-03-02 22:03:47 +00003088 for (p = 0; p < context->count_protocols; p++) {
Andy Greened11a022011-01-20 10:23:50 +00003089 fd = socket(AF_INET, SOCK_STREAM, 0);
3090 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003091 lwsl_err("Unable to create socket\n");
Andy Greened11a022011-01-20 10:23:50 +00003092 return -1;
3093 }
3094 cli_addr.sin_family = AF_INET;
3095 cli_addr.sin_port = htons(
Peter Hinz56885f32011-03-02 22:03:47 +00003096 context->protocols[p].broadcast_socket_port);
Andy Greened11a022011-01-20 10:23:50 +00003097 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3098 n = connect(fd, (struct sockaddr *)&cli_addr,
3099 sizeof cli_addr);
3100 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003101 lwsl_err("Unable to connect to "
Andy Greened11a022011-01-20 10:23:50 +00003102 "broadcast socket %d, %s\n",
Andy Green3221f922011-02-12 13:14:11 +00003103 n, strerror(errno));
Andy Greened11a022011-01-20 10:23:50 +00003104 return -1;
3105 }
3106
Peter Hinz56885f32011-03-02 22:03:47 +00003107 context->protocols[p].broadcast_socket_user_fd = fd;
Andy Greened11a022011-01-20 10:23:50 +00003108 }
3109
Andy Greene92cd172011-01-19 13:11:55 +00003110 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00003111 }
3112
Artem Baguinski91531662011-12-14 22:14:03 +01003113#ifdef HAVE_SYS_PRCTL_H
Andy Greenb45993c2010-12-18 15:13:50 +00003114 /* we want a SIGHUP when our parent goes down */
3115 prctl(PR_SET_PDEATHSIG, SIGHUP);
Artem Baguinski91531662011-12-14 22:14:03 +01003116#endif
Andy Greenb45993c2010-12-18 15:13:50 +00003117
3118 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +00003119
Artem Baguinski91531662011-12-14 22:14:03 +01003120 while (1) {
Peter Hinz56885f32011-03-02 22:03:47 +00003121 if (libwebsocket_service(context, 1000))
Andy Green3928f612012-07-20 12:58:38 +08003122 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003123//#ifndef HAVE_SYS_PRCTL_H
Artem Baguinski91531662011-12-14 22:14:03 +01003124/*
3125 * on systems without prctl() (i.e. anything but linux) we can notice that our
3126 * parent is dead if getppid() returns 1. FIXME apparently this is not true for
3127 * solaris, could remember ppid right after fork and wait for it to change.
3128 */
3129
3130 if (getppid() == 1)
3131 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003132//#endif
Artem Baguinski91531662011-12-14 22:14:03 +01003133 }
3134
Andy Green8f037e42010-12-19 22:13:26 +00003135
Andy Green3928f612012-07-20 12:58:38 +08003136 return 1;
Andy Greenff95d7a2010-10-28 22:36:01 +01003137}
3138
Andy Greened11a022011-01-20 10:23:50 +00003139#endif
3140
Andy Greenb45993c2010-12-18 15:13:50 +00003141/**
3142 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +00003143 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +00003144 * @wsi: pointer to struct websocket you want to know the protocol of
3145 *
Andy Green8f037e42010-12-19 22:13:26 +00003146 *
3147 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +00003148 * the callback.
3149 */
Andy Greenab990e42010-10-31 12:42:52 +00003150
Andy Greenb45993c2010-12-18 15:13:50 +00003151const struct libwebsocket_protocols *
3152libwebsockets_get_protocol(struct libwebsocket *wsi)
3153{
3154 return wsi->protocol;
3155}
3156
3157/**
Andy Greene92cd172011-01-19 13:11:55 +00003158 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +00003159 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +00003160 * @protocol: pointer to the protocol you will broadcast to all members of
3161 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +00003162 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
3163 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
3164 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +00003165 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +00003166 *
3167 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +00003168 * the given protocol. It does not send the data directly; instead it calls
3169 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
3170 * wants to actually send the data for that connection, the callback itself
3171 * should call libwebsocket_write().
3172 *
3173 * libwebsockets_broadcast() can be called from another fork context without
3174 * having to take any care about data visibility between the processes, it'll
3175 * "just work".
3176 */
3177
3178
3179int
Andy Green8f037e42010-12-19 22:13:26 +00003180libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +00003181 unsigned char *buf, size_t len)
3182{
Peter Hinz56885f32011-03-02 22:03:47 +00003183 struct libwebsocket_context *context = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +00003184 int n;
Andy Green0d338332011-02-12 11:57:43 +00003185 int m;
Andy Green6ee372f2012-04-09 15:09:01 +08003186 struct libwebsocket *wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00003187
3188 if (!protocol->broadcast_socket_user_fd) {
3189 /*
Andy Greene92cd172011-01-19 13:11:55 +00003190 * We are either running unforked / flat, or we are being
3191 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +00003192 * eg, from a callback. In that case don't use sockets for
3193 * broadcast IPC (since we can't open a socket connection to
3194 * a socket listening on our own thread) but directly do the
3195 * send action.
3196 *
3197 * Locking is not needed because we are by definition being
3198 * called in the poll thread context and are serialized.
3199 */
3200
Andy Green0d338332011-02-12 11:57:43 +00003201 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003202
Peter Hinz56885f32011-03-02 22:03:47 +00003203 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003204
Peter Hinz56885f32011-03-02 22:03:47 +00003205 wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00003206
Andy Green0d338332011-02-12 11:57:43 +00003207 if (wsi->mode != LWS_CONNMODE_WS_SERVING)
3208 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00003209
Andy Green0d338332011-02-12 11:57:43 +00003210 /*
3211 * never broadcast to
3212 * non-established connections
3213 */
3214 if (wsi->state != WSI_STATE_ESTABLISHED)
3215 continue;
3216
3217 /* only broadcast to guys using
3218 * requested protocol
3219 */
3220 if (wsi->protocol != protocol)
3221 continue;
3222
Peter Hinz56885f32011-03-02 22:03:47 +00003223 wsi->protocol->callback(context, wsi,
Andy Green8f037e42010-12-19 22:13:26 +00003224 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00003225 wsi->user_space,
Andy Greenb45993c2010-12-18 15:13:50 +00003226 buf, len);
Andy Green0d338332011-02-12 11:57:43 +00003227 }
Andy Greenb45993c2010-12-18 15:13:50 +00003228 }
3229
3230 return 0;
3231 }
3232
Andy Green0ca6a172010-12-19 20:50:01 +00003233 /*
3234 * We're being called from a different process context than the server
3235 * loop. Instead of broadcasting directly, we send our
3236 * payload on a socket to do the IPC; the server process will serialize
3237 * the broadcast action in its main poll() loop.
3238 *
3239 * There's one broadcast socket listening for each protocol supported
3240 * set up when the websocket server initializes
3241 */
3242
Andy Green6964bb52011-01-23 16:50:33 +00003243 n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
Andy Greenb45993c2010-12-18 15:13:50 +00003244
3245 return n;
3246}
Andy Green82c3d542011-03-07 21:16:31 +00003247
3248int
3249libwebsocket_is_final_fragment(struct libwebsocket *wsi)
3250{
3251 return wsi->final;
3252}
Alex Bligh49146db2011-11-07 17:19:25 +08003253
David Galeanoe2cf9922013-01-09 18:06:55 +08003254unsigned char
3255libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
3256{
3257 return wsi->rsv;
3258}
3259
Alex Bligh49146db2011-11-07 17:19:25 +08003260void *
3261libwebsocket_ensure_user_space(struct libwebsocket *wsi)
3262{
3263 /* allocate the per-connection user memory (if any) */
3264
3265 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
3266 wsi->user_space = malloc(
3267 wsi->protocol->per_session_data_size);
3268 if (wsi->user_space == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08003269 lwsl_err("Out of memory for conn user space\n");
Alex Bligh49146db2011-11-07 17:19:25 +08003270 return NULL;
3271 }
Andy Green6ee372f2012-04-09 15:09:01 +08003272 memset(wsi->user_space, 0,
3273 wsi->protocol->per_session_data_size);
Alex Bligh49146db2011-11-07 17:19:25 +08003274 }
3275 return wsi->user_space;
3276}
Andy Green43db0452013-01-10 19:50:35 +08003277
Andy Greende8f27a2013-01-12 09:17:42 +08003278
3279static void lwsl_emit_stderr(const char *line)
3280{
3281 fprintf(stderr, "%s", line);
3282}
3283
Andy Green43db0452013-01-10 19:50:35 +08003284void _lws_log(int filter, const char *format, ...)
3285{
Andy Greende8f27a2013-01-12 09:17:42 +08003286 char buf[256];
Andy Green43db0452013-01-10 19:50:35 +08003287 va_list ap;
3288 int n;
Andy Greende8f27a2013-01-12 09:17:42 +08003289 int pos = 0;
Andy Green43db0452013-01-10 19:50:35 +08003290
3291 if (!(log_level & filter))
3292 return;
3293
3294 for (n = 0; n < LLL_COUNT; n++)
3295 if (filter == (1 << n)) {
Andy Greende8f27a2013-01-12 09:17:42 +08003296 pos = sprintf(buf, "%s: ", log_level_names[n]);
Andy Green43db0452013-01-10 19:50:35 +08003297 break;
3298 }
3299
3300 va_start(ap, format);
Andy Greende8f27a2013-01-12 09:17:42 +08003301 vsnprintf(buf + pos, (sizeof buf) - pos, format, ap);
3302 buf[(sizeof buf) - 1] = '\0';
3303 va_end(ap);
3304
3305 lwsl_emit(buf);
Andy Green43db0452013-01-10 19:50:35 +08003306}
3307
3308/**
3309 * lws_set_log_level() - Set the logging bitfield
3310 * @level: OR together the LLL_ debug contexts you want output from
Andy Greende8f27a2013-01-12 09:17:42 +08003311 * @log_emit_function: NULL to leave it as it is, or a user-supplied
3312 * function to perform log string emission instead of
3313 * the default stderr one.
Andy Green43db0452013-01-10 19:50:35 +08003314 *
Andy Greende8f27a2013-01-12 09:17:42 +08003315 * log level defaults to "err" and "warn" contexts enabled only and
3316 * emission on stderr.
Andy Green43db0452013-01-10 19:50:35 +08003317 */
3318
Andy Greende8f27a2013-01-12 09:17:42 +08003319void lws_set_log_level(int level, void (*log_emit_function)(const char *line))
Andy Green43db0452013-01-10 19:50:35 +08003320{
3321 log_level = level;
Andy Greende8f27a2013-01-12 09:17:42 +08003322 if (log_emit_function)
3323 lwsl_emit = log_emit_function;
Andy Green43db0452013-01-10 19:50:35 +08003324}