blob: b0e7a6d455f4992fccf52abb44cb21f951b2240b [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;
47static const char *log_level_names[] = {
48 "ERR",
49 "WARN",
50 "INFO",
51 "DEBUG",
52 "PARSER",
53 "HEADER",
54 "EXTENSION",
55 "CLIENT",
56};
57
Andy Greenbe93fef2011-02-14 20:25:43 +000058/*
59 * In-place str to lower case
60 */
61
62static void
63strtolower(char *s)
64{
65 while (*s) {
66 *s = tolower(*s);
67 s++;
68 }
69}
70
Andy Green0d338332011-02-12 11:57:43 +000071/* file descriptor hash management */
72
73struct libwebsocket *
Peter Hinz56885f32011-03-02 22:03:47 +000074wsi_from_fd(struct libwebsocket_context *context, int fd)
Andy Green0d338332011-02-12 11:57:43 +000075{
76 int h = LWS_FD_HASH(fd);
77 int n = 0;
78
Peter Hinz56885f32011-03-02 22:03:47 +000079 for (n = 0; n < context->fd_hashtable[h].length; n++)
80 if (context->fd_hashtable[h].wsi[n]->sock == fd)
81 return context->fd_hashtable[h].wsi[n];
Andy Green0d338332011-02-12 11:57:43 +000082
83 return NULL;
84}
85
86int
Peter Hinz56885f32011-03-02 22:03:47 +000087insert_wsi(struct libwebsocket_context *context, struct libwebsocket *wsi)
Andy Green0d338332011-02-12 11:57:43 +000088{
89 int h = LWS_FD_HASH(wsi->sock);
90
Peter Hinz56885f32011-03-02 22:03:47 +000091 if (context->fd_hashtable[h].length == MAX_CLIENTS - 1) {
Andy Green43db0452013-01-10 19:50:35 +080092 lwsl_err("hash table overflow\n");
Andy Green0d338332011-02-12 11:57:43 +000093 return 1;
94 }
95
Peter Hinz56885f32011-03-02 22:03:47 +000096 context->fd_hashtable[h].wsi[context->fd_hashtable[h].length++] = wsi;
Andy Green0d338332011-02-12 11:57:43 +000097
98 return 0;
99}
100
101int
Peter Hinz56885f32011-03-02 22:03:47 +0000102delete_from_fd(struct libwebsocket_context *context, int fd)
Andy Green0d338332011-02-12 11:57:43 +0000103{
104 int h = LWS_FD_HASH(fd);
105 int n = 0;
106
Peter Hinz56885f32011-03-02 22:03:47 +0000107 for (n = 0; n < context->fd_hashtable[h].length; n++)
108 if (context->fd_hashtable[h].wsi[n]->sock == fd) {
109 while (n < context->fd_hashtable[h].length) {
110 context->fd_hashtable[h].wsi[n] =
111 context->fd_hashtable[h].wsi[n + 1];
Andy Green0d338332011-02-12 11:57:43 +0000112 n++;
113 }
Peter Hinz56885f32011-03-02 22:03:47 +0000114 context->fd_hashtable[h].length--;
Andy Green0d338332011-02-12 11:57:43 +0000115
116 return 0;
117 }
118
Andy Green43db0452013-01-10 19:50:35 +0800119 lwsl_err("Failed to find fd %d requested for "
Andy Green0d338332011-02-12 11:57:43 +0000120 "delete in hashtable\n", fd);
121 return 1;
122}
123
Andy Green1f9bf522011-02-14 21:14:37 +0000124#ifdef LWS_OPENSSL_SUPPORT
125static void
126libwebsockets_decode_ssl_error(void)
127{
128 char buf[256];
129 u_long err;
130
131 while ((err = ERR_get_error()) != 0) {
132 ERR_error_string_n(err, buf, sizeof(buf));
Andy Green43db0452013-01-10 19:50:35 +0800133 lwsl_err("*** %s\n", buf);
Andy Green1f9bf522011-02-14 21:14:37 +0000134 }
135}
136#endif
Andy Green0d338332011-02-12 11:57:43 +0000137
Andy Green32375b72011-02-19 08:32:53 +0000138
139static int
Andy Green6ee372f2012-04-09 15:09:01 +0800140interface_to_sa(const char *ifname, struct sockaddr_in *addr, size_t addrlen)
Andy Green32375b72011-02-19 08:32:53 +0000141{
142 int rc = -1;
Peter Hinz56885f32011-03-02 22:03:47 +0000143#ifdef WIN32
Andy Green6ee372f2012-04-09 15:09:01 +0800144 /* TODO */
Peter Hinz56885f32011-03-02 22:03:47 +0000145#else
Andy Green32375b72011-02-19 08:32:53 +0000146 struct ifaddrs *ifr;
147 struct ifaddrs *ifc;
148 struct sockaddr_in *sin;
149
150 getifaddrs(&ifr);
151 for (ifc = ifr; ifc != NULL; ifc = ifc->ifa_next) {
152 if (strcmp(ifc->ifa_name, ifname))
153 continue;
154 if (ifc->ifa_addr == NULL)
155 continue;
156 sin = (struct sockaddr_in *)ifc->ifa_addr;
157 if (sin->sin_family != AF_INET)
158 continue;
159 memcpy(addr, sin, addrlen);
Andy Green6ee372f2012-04-09 15:09:01 +0800160 rc = 0;
Andy Green32375b72011-02-19 08:32:53 +0000161 }
162
163 freeifaddrs(ifr);
Peter Hinz56885f32011-03-02 22:03:47 +0000164#endif
Andy Green32375b72011-02-19 08:32:53 +0000165 return rc;
166}
167
Andy Green8f037e42010-12-19 22:13:26 +0000168void
Peter Hinz56885f32011-03-02 22:03:47 +0000169libwebsocket_close_and_free_session(struct libwebsocket_context *context,
Andy Green687b0182011-02-26 11:04:01 +0000170 struct libwebsocket *wsi, enum lws_close_status reason)
Andy Green251f6fa2010-11-03 11:13:06 +0000171{
Andy Greenb45993c2010-12-18 15:13:50 +0000172 int n;
Andy Green62c54d22011-02-14 09:14:25 +0000173 int old_state;
Andy Green5e1fa172011-02-10 09:07:05 +0000174 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
175 LWS_SEND_BUFFER_POST_PADDING];
Andy Greenc44159f2011-03-07 07:08:18 +0000176 int ret;
177 int m;
178 struct lws_tokens eff_buf;
Andy Greena41314f2011-05-23 10:00:03 +0100179 struct libwebsocket_extension *ext;
Andy Greenb45993c2010-12-18 15:13:50 +0000180
Andy Green4b6fbe12011-02-14 08:03:48 +0000181 if (!wsi)
Andy Greenb45993c2010-12-18 15:13:50 +0000182 return;
183
Andy Green62c54d22011-02-14 09:14:25 +0000184 old_state = wsi->state;
Andy Green251f6fa2010-11-03 11:13:06 +0000185
Andy Green62c54d22011-02-14 09:14:25 +0000186 if (old_state == WSI_STATE_DEAD_SOCKET)
Andy Green5e1fa172011-02-10 09:07:05 +0000187 return;
188
Andy Greenda527df2011-03-07 07:08:12 +0000189 wsi->close_reason = reason;
190
191 /*
Andy Green68b45042011-05-25 21:41:57 +0100192 * are his extensions okay with him closing? Eg he might be a mux
193 * parent and just his ch1 aspect is closing?
194 */
195
196
197 for (n = 0; n < wsi->count_active_extensions; n++) {
198 if (!wsi->active_extensions[n]->callback)
199 continue;
200
201 m = wsi->active_extensions[n]->callback(context,
202 wsi->active_extensions[n], wsi,
203 LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
204 wsi->active_extensions_user[n], NULL, 0);
205
206 /*
207 * if somebody vetoed actually closing him at this time....
208 * up to the extension to track the attempted close, let's
209 * just bail
210 */
211
212 if (m) {
Andy Green43db0452013-01-10 19:50:35 +0800213 lwsl_ext("extension vetoed close\n");
Andy Green68b45042011-05-25 21:41:57 +0100214 return;
215 }
216 }
217
218
219
220 /*
Andy Greenc44159f2011-03-07 07:08:18 +0000221 * flush any tx pending from extensions, since we may send close packet
222 * if there are problems with send, just nuke the connection
223 */
224
225 ret = 1;
226 while (ret == 1) {
227
228 /* default to nobody has more to spill */
229
230 ret = 0;
231 eff_buf.token = NULL;
232 eff_buf.token_len = 0;
233
234 /* show every extension the new incoming data */
235
236 for (n = 0; n < wsi->count_active_extensions; n++) {
237 m = wsi->active_extensions[n]->callback(
Andy Green46c2ea02011-03-22 09:04:01 +0000238 wsi->protocol->owning_server,
239 wsi->active_extensions[n], wsi,
Andy Greenc44159f2011-03-07 07:08:18 +0000240 LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
241 wsi->active_extensions_user[n], &eff_buf, 0);
242 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +0800243 lwsl_ext("Extension reports fatal error\n");
Andy Greenc44159f2011-03-07 07:08:18 +0000244 goto just_kill_connection;
245 }
246 if (m)
247 /*
248 * at least one extension told us he has more
249 * to spill, so we will go around again after
250 */
251 ret = 1;
252 }
253
254 /* assuming they left us something to send, send it */
255
256 if (eff_buf.token_len)
257 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
258 eff_buf.token_len))
259 goto just_kill_connection;
260 }
261
262 /*
Andy Greenda527df2011-03-07 07:08:12 +0000263 * signal we are closing, libsocket_write will
264 * add any necessary version-specific stuff. If the write fails,
265 * no worries we are closing anyway. If we didn't initiate this
266 * close, then our state has been changed to
267 * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
268 *
269 * Likewise if it's a second call to close this connection after we
270 * sent the close indication to the peer already, we are in state
271 * WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
272 */
273
274 if (old_state == WSI_STATE_ESTABLISHED &&
275 reason != LWS_CLOSE_STATUS_NOSTATUS) {
Andy Green66a16f32011-05-24 22:07:45 +0100276
Andy Green43db0452013-01-10 19:50:35 +0800277 lwsl_debug("sending close indication...\n");
Andy Green66a16f32011-05-24 22:07:45 +0100278
Andy Greenda527df2011-03-07 07:08:12 +0000279 n = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING],
280 0, LWS_WRITE_CLOSE);
281 if (!n) {
282 /*
283 * we have sent a nice protocol level indication we
284 * now wish to close, we should not send anything more
285 */
286
287 wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
288
289 /* and we should wait for a reply for a bit */
290
291 libwebsocket_set_timeout(wsi,
David Galeanoc9f1ff82013-01-09 18:01:23 +0800292 PENDING_TIMEOUT_CLOSE_ACK, AWAITING_TIMEOUT);
Andy Greenda527df2011-03-07 07:08:12 +0000293
Andy Green43db0452013-01-10 19:50:35 +0800294 lwsl_debug("sent close indication, awaiting ack\n");
Andy Greenda527df2011-03-07 07:08:12 +0000295
296 return;
297 }
298
299 /* else, the send failed and we should just hang up */
300 }
301
Andy Greenc44159f2011-03-07 07:08:18 +0000302just_kill_connection:
Andy Green66a16f32011-05-24 22:07:45 +0100303
Andy Green43db0452013-01-10 19:50:35 +0800304 lwsl_debug("libwebsocket_close_and_free_session: just_kill_connection\n");
Andy Green66a16f32011-05-24 22:07:45 +0100305
Andy Greenda527df2011-03-07 07:08:12 +0000306 /*
307 * we won't be servicing or receiving anything further from this guy
308 * remove this fd from wsi mapping hashtable
309 */
Andy Green4b6fbe12011-02-14 08:03:48 +0000310
Andy Greena41314f2011-05-23 10:00:03 +0100311 if (wsi->sock)
312 delete_from_fd(context, wsi->sock);
Andy Green4b6fbe12011-02-14 08:03:48 +0000313
314 /* delete it from the internal poll list if still present */
315
Peter Hinz56885f32011-03-02 22:03:47 +0000316 for (n = 0; n < context->fds_count; n++) {
317 if (context->fds[n].fd != wsi->sock)
Andy Green4b6fbe12011-02-14 08:03:48 +0000318 continue;
Peter Hinz56885f32011-03-02 22:03:47 +0000319 while (n < context->fds_count - 1) {
320 context->fds[n] = context->fds[n + 1];
Andy Green4b6fbe12011-02-14 08:03:48 +0000321 n++;
322 }
Peter Hinz56885f32011-03-02 22:03:47 +0000323 context->fds_count--;
Andy Green4b6fbe12011-02-14 08:03:48 +0000324 /* we only have to deal with one */
Peter Hinz56885f32011-03-02 22:03:47 +0000325 n = context->fds_count;
Andy Green4b6fbe12011-02-14 08:03:48 +0000326 }
327
328 /* remove also from external POLL support via protocol 0 */
Andy Greena41314f2011-05-23 10:00:03 +0100329 if (wsi->sock)
330 context->protocols[0].callback(context, wsi,
Andy Green4b6fbe12011-02-14 08:03:48 +0000331 LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
332
Andy Green251f6fa2010-11-03 11:13:06 +0000333 wsi->state = WSI_STATE_DEAD_SOCKET;
334
Andy Green4b6fbe12011-02-14 08:03:48 +0000335 /* tell the user it's all over for this guy */
336
Andy Greend4302732011-02-28 07:45:29 +0000337 if (wsi->protocol && wsi->protocol->callback &&
Andy Green6ee372f2012-04-09 15:09:01 +0800338 ((old_state == WSI_STATE_ESTABLISHED) ||
339 (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
340 (old_state == WSI_STATE_AWAITING_CLOSE_ACK))) {
Andy Green43db0452013-01-10 19:50:35 +0800341 lwsl_debug("calling back CLOSED\n");
Peter Hinz56885f32011-03-02 22:03:47 +0000342 wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
Andy Greene77ddd82010-11-13 10:03:47 +0000343 wsi->user_space, NULL, 0);
Andy Greencc012472011-11-07 19:53:23 +0800344 } else
Andy Green43db0452013-01-10 19:50:35 +0800345 lwsl_debug("not calling back closed, old_state=%d\n", old_state);
Andy Green251f6fa2010-11-03 11:13:06 +0000346
Andy Greenef660a92011-03-06 10:29:38 +0000347 /* deallocate any active extension contexts */
348
349 for (n = 0; n < wsi->count_active_extensions; n++) {
350 if (!wsi->active_extensions[n]->callback)
351 continue;
352
Andy Green46c2ea02011-03-22 09:04:01 +0000353 wsi->active_extensions[n]->callback(context,
354 wsi->active_extensions[n], wsi,
355 LWS_EXT_CALLBACK_DESTROY,
356 wsi->active_extensions_user[n], NULL, 0);
Andy Greenef660a92011-03-06 10:29:38 +0000357
358 free(wsi->active_extensions_user[n]);
359 }
360
Andy Greena41314f2011-05-23 10:00:03 +0100361 /*
362 * inform all extensions in case they tracked this guy out of band
363 * even though not active on him specifically
364 */
365
366 ext = context->extensions;
367 while (ext && ext->callback) {
368 ext->callback(context, ext, wsi,
369 LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
370 NULL, NULL, 0);
371 ext++;
372 }
373
Andy Greenef660a92011-03-06 10:29:38 +0000374 /* free up his parsing allocations */
Andy Green4b6fbe12011-02-14 08:03:48 +0000375
Andy Green251f6fa2010-11-03 11:13:06 +0000376 for (n = 0; n < WSI_TOKEN_COUNT; n++)
377 if (wsi->utf8_token[n].token)
378 free(wsi->utf8_token[n].token);
379
Andy Greena41314f2011-05-23 10:00:03 +0100380 if (wsi->c_address)
381 free(wsi->c_address);
382
Andy Green43db0452013-01-10 19:50:35 +0800383/* lwsl_info("closing fd=%d\n", wsi->sock); */
Andy Green251f6fa2010-11-03 11:13:06 +0000384
Andy Green3faa9c72010-11-08 17:03:03 +0000385#ifdef LWS_OPENSSL_SUPPORT
Andy Green90c7cbc2011-01-27 06:26:52 +0000386 if (wsi->ssl) {
Andy Green3faa9c72010-11-08 17:03:03 +0000387 n = SSL_get_fd(wsi->ssl);
388 SSL_shutdown(wsi->ssl);
Peter Hinz56885f32011-03-02 22:03:47 +0000389#ifdef WIN32
390 closesocket(n);
391#else
Andy Green3faa9c72010-11-08 17:03:03 +0000392 close(n);
Peter Hinz56885f32011-03-02 22:03:47 +0000393#endif
Andy Green3faa9c72010-11-08 17:03:03 +0000394 SSL_free(wsi->ssl);
395 } else {
396#endif
397 shutdown(wsi->sock, SHUT_RDWR);
Peter Hinz56885f32011-03-02 22:03:47 +0000398#ifdef WIN32
Andy Green66a16f32011-05-24 22:07:45 +0100399 if (wsi->sock)
400 closesocket(wsi->sock);
Peter Hinz56885f32011-03-02 22:03:47 +0000401#else
Andy Green66a16f32011-05-24 22:07:45 +0100402 if (wsi->sock)
403 close(wsi->sock);
Peter Hinz56885f32011-03-02 22:03:47 +0000404#endif
Andy Green3faa9c72010-11-08 17:03:03 +0000405#ifdef LWS_OPENSSL_SUPPORT
406 }
407#endif
David Brooks2c60d952012-04-20 12:19:01 +0800408 if (wsi->protocol && wsi->protocol->per_session_data_size && wsi->user_space) /* user code may own */
Andy Green4f3943a2010-11-12 10:44:16 +0000409 free(wsi->user_space);
410
Andy Green251f6fa2010-11-03 11:13:06 +0000411 free(wsi);
412}
413
Andy Green07034092011-02-13 08:37:12 +0000414/**
Andy Greenf7ee5492011-02-13 09:04:21 +0000415 * libwebsockets_hangup_on_client() - Server calls to terminate client
Andy Green6ee372f2012-04-09 15:09:01 +0800416 * connection
Peter Hinz56885f32011-03-02 22:03:47 +0000417 * @context: libwebsockets context
Andy Greenf7ee5492011-02-13 09:04:21 +0000418 * @fd: Connection socket descriptor
419 */
420
421void
Peter Hinz56885f32011-03-02 22:03:47 +0000422libwebsockets_hangup_on_client(struct libwebsocket_context *context, int fd)
Andy Greenf7ee5492011-02-13 09:04:21 +0000423{
Peter Hinz56885f32011-03-02 22:03:47 +0000424 struct libwebsocket *wsi = wsi_from_fd(context, fd);
Andy Greenf7ee5492011-02-13 09:04:21 +0000425
426 if (wsi == NULL)
427 return;
428
Peter Hinz56885f32011-03-02 22:03:47 +0000429 libwebsocket_close_and_free_session(context, wsi,
Andy Green6da560c2011-02-26 11:06:27 +0000430 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenf7ee5492011-02-13 09:04:21 +0000431}
432
433
434/**
Andy Green07034092011-02-13 08:37:12 +0000435 * libwebsockets_get_peer_addresses() - Get client address information
436 * @fd: Connection socket descriptor
437 * @name: Buffer to take client address name
438 * @name_len: Length of client address name buffer
439 * @rip: Buffer to take client address IP qotted quad
440 * @rip_len: Length of client address IP buffer
441 *
442 * This function fills in @name and @rip with the name and IP of
Andy Green6ee372f2012-04-09 15:09:01 +0800443 * the client connected with socket descriptor @fd. Names may be
444 * truncated if there is not enough room. If either cannot be
445 * determined, they will be returned as valid zero-length strings.
Andy Green07034092011-02-13 08:37:12 +0000446 */
447
448void
449libwebsockets_get_peer_addresses(int fd, char *name, int name_len,
450 char *rip, int rip_len)
451{
452 unsigned int len;
453 struct sockaddr_in sin;
454 struct hostent *host;
455 struct hostent *host1;
456 char ip[128];
Andy Greenf92def72011-03-09 15:02:20 +0000457 unsigned char *p;
Andy Green07034092011-02-13 08:37:12 +0000458 int n;
David Galeanocb193682013-01-09 15:29:00 +0800459#ifdef AF_LOCAL
460 struct sockaddr_un *un;
461#endif
Andy Green07034092011-02-13 08:37:12 +0000462
463 rip[0] = '\0';
464 name[0] = '\0';
465
466 len = sizeof sin;
467 if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
468 perror("getpeername");
469 return;
470 }
Andy Green6ee372f2012-04-09 15:09:01 +0800471
Andy Green07034092011-02-13 08:37:12 +0000472 host = gethostbyaddr((char *) &sin.sin_addr, sizeof sin.sin_addr,
473 AF_INET);
474 if (host == NULL) {
475 perror("gethostbyaddr");
476 return;
477 }
478
479 strncpy(name, host->h_name, name_len);
480 name[name_len - 1] = '\0';
481
482 host1 = gethostbyname(host->h_name);
483 if (host1 == NULL)
484 return;
Andy Greenf92def72011-03-09 15:02:20 +0000485 p = (unsigned char *)host1;
Andy Green07034092011-02-13 08:37:12 +0000486 n = 0;
487 while (p != NULL) {
Andy Greenf92def72011-03-09 15:02:20 +0000488 p = (unsigned char *)host1->h_addr_list[n++];
Andy Green07034092011-02-13 08:37:12 +0000489 if (p == NULL)
490 continue;
Peter Hinzbb45a902011-03-10 18:14:01 +0000491 if ((host1->h_addrtype != AF_INET)
492#ifdef AF_LOCAL
493 && (host1->h_addrtype != AF_LOCAL)
494#endif
495 )
Andy Green07034092011-02-13 08:37:12 +0000496 continue;
497
Andy Green7627af52011-03-09 15:13:52 +0000498 if (host1->h_addrtype == AF_INET)
499 sprintf(ip, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
Peter Hinzbb45a902011-03-10 18:14:01 +0000500#ifdef AF_LOCAL
Andy Green7627af52011-03-09 15:13:52 +0000501 else {
502 un = (struct sockaddr_un *)p;
Andy Green6ee372f2012-04-09 15:09:01 +0800503 strncpy(ip, un->sun_path, sizeof(ip) - 1);
Andy Green7627af52011-03-09 15:13:52 +0000504 ip[sizeof(ip) - 1] = '\0';
505 }
Peter Hinzbb45a902011-03-10 18:14:01 +0000506#endif
Andy Green07034092011-02-13 08:37:12 +0000507 p = NULL;
508 strncpy(rip, ip, rip_len);
509 rip[rip_len - 1] = '\0';
510 }
511}
Andy Green9f990342011-02-12 11:57:45 +0000512
Peter Hinz56885f32011-03-02 22:03:47 +0000513int libwebsockets_get_random(struct libwebsocket_context *context,
514 void *buf, int len)
515{
516 int n;
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800517 char *p = (char *)buf;
Peter Hinz56885f32011-03-02 22:03:47 +0000518
519#ifdef WIN32
520 for (n = 0; n < len; n++)
521 p[n] = (unsigned char)rand();
522#else
523 n = read(context->fd_random, p, len);
524#endif
525
526 return n;
527}
528
Andy Green2836c642011-03-07 20:47:41 +0000529unsigned char *
530libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md)
531{
532 return SHA1(d, n, md);
533}
534
Andy Greeneeaacb32011-03-01 20:44:24 +0000535void libwebsockets_00_spaceout(char *key, int spaces, int seed)
536{
537 char *p;
Andy Green6ee372f2012-04-09 15:09:01 +0800538
Andy Greeneeaacb32011-03-01 20:44:24 +0000539 key++;
540 while (spaces--) {
541 if (*key && (seed & 1))
542 key++;
543 seed >>= 1;
Andy Green6ee372f2012-04-09 15:09:01 +0800544
Andy Greeneeaacb32011-03-01 20:44:24 +0000545 p = key + strlen(key);
546 while (p >= key) {
547 p[1] = p[0];
548 p--;
549 }
550 *key++ = ' ';
551 }
552}
553
554void libwebsockets_00_spam(char *key, int count, int seed)
555{
556 char *p;
557
558 key++;
559 while (count--) {
Andy Green6ee372f2012-04-09 15:09:01 +0800560
Andy Greeneeaacb32011-03-01 20:44:24 +0000561 if (*key && (seed & 1))
562 key++;
563 seed >>= 1;
564
565 p = key + strlen(key);
566 while (p >= key) {
567 p[1] = p[0];
568 p--;
569 }
570 *key++ = 0x21 + ((seed & 0xffff) % 15);
571 /* 4 would use it up too fast.. not like it matters */
572 seed >>= 1;
573 }
574}
575
Andy Green95a7b5d2011-03-06 10:29:39 +0000576int lws_send_pipe_choked(struct libwebsocket *wsi)
577{
578 struct pollfd fds;
579
580 fds.fd = wsi->sock;
581 fds.events = POLLOUT;
582 fds.revents = 0;
583
584 if (poll(&fds, 1, 0) != 1)
585 return 1;
586
587 if ((fds.revents & POLLOUT) == 0)
588 return 1;
589
590 /* okay to send another packet without blocking */
591
592 return 0;
593}
594
Andy Greena41314f2011-05-23 10:00:03 +0100595int
Andy Green3b84c002011-03-06 13:14:42 +0000596lws_handle_POLLOUT_event(struct libwebsocket_context *context,
597 struct libwebsocket *wsi, struct pollfd *pollfd)
598{
599 struct lws_tokens eff_buf;
600 int n;
601 int ret;
602 int m;
Andy Greena41314f2011-05-23 10:00:03 +0100603 int handled = 0;
Andy Green3b84c002011-03-06 13:14:42 +0000604
Andy Greena41314f2011-05-23 10:00:03 +0100605 for (n = 0; n < wsi->count_active_extensions; n++) {
606 if (!wsi->active_extensions[n]->callback)
607 continue;
608
609 m = wsi->active_extensions[n]->callback(context,
610 wsi->active_extensions[n], wsi,
611 LWS_EXT_CALLBACK_IS_WRITEABLE,
612 wsi->active_extensions_user[n], NULL, 0);
613 if (m > handled)
614 handled = m;
615 }
616
617 if (handled == 1)
618 goto notify_action;
619
620 if (!wsi->extension_data_pending || handled == 2)
Andy Green3b84c002011-03-06 13:14:42 +0000621 goto user_service;
622
623 /*
624 * check in on the active extensions, see if they
625 * had pending stuff to spill... they need to get the
626 * first look-in otherwise sequence will be disordered
627 *
628 * NULL, zero-length eff_buf means just spill pending
629 */
630
631 ret = 1;
632 while (ret == 1) {
633
634 /* default to nobody has more to spill */
635
636 ret = 0;
637 eff_buf.token = NULL;
638 eff_buf.token_len = 0;
639
640 /* give every extension a chance to spill */
641
642 for (n = 0; n < wsi->count_active_extensions; n++) {
643 m = wsi->active_extensions[n]->callback(
Andy Green46c2ea02011-03-22 09:04:01 +0000644 wsi->protocol->owning_server,
645 wsi->active_extensions[n], wsi,
Andy Green3b84c002011-03-06 13:14:42 +0000646 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
647 wsi->active_extensions_user[n], &eff_buf, 0);
648 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +0800649 lwsl_err("ext reports fatal error\n");
Andy Green3b84c002011-03-06 13:14:42 +0000650 return -1;
651 }
652 if (m)
653 /*
654 * at least one extension told us he has more
655 * to spill, so we will go around again after
656 */
657 ret = 1;
658 }
659
660 /* assuming they gave us something to send, send it */
661
662 if (eff_buf.token_len) {
663 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
664 eff_buf.token_len))
665 return -1;
666 } else
667 continue;
668
669 /* no extension has more to spill */
670
671 if (!ret)
672 continue;
673
674 /*
675 * There's more to spill from an extension, but we just sent
676 * something... did that leave the pipe choked?
677 */
678
679 if (!lws_send_pipe_choked(wsi))
680 /* no we could add more */
681 continue;
682
Andy Green43db0452013-01-10 19:50:35 +0800683 lwsl_info("choked in POLLOUT service\n");
Andy Green3b84c002011-03-06 13:14:42 +0000684
685 /*
686 * Yes, he's choked. Leave the POLLOUT masked on so we will
687 * come back here when he is unchoked. Don't call the user
688 * callback to enforce ordering of spilling, he'll get called
689 * when we come back here and there's nothing more to spill.
690 */
691
692 return 0;
693 }
694
695 wsi->extension_data_pending = 0;
696
697user_service:
698 /* one shot */
699
Andy Greena41314f2011-05-23 10:00:03 +0100700 if (pollfd) {
701 pollfd->events &= ~POLLOUT;
Andy Green3b84c002011-03-06 13:14:42 +0000702
Andy Greena41314f2011-05-23 10:00:03 +0100703 /* external POLL support via protocol 0 */
704 context->protocols[0].callback(context, wsi,
705 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
706 (void *)(long)wsi->sock, NULL, POLLOUT);
707 }
708
709notify_action:
Andy Green3b84c002011-03-06 13:14:42 +0000710
Andy Green9e4c2b62011-03-07 20:47:39 +0000711 if (wsi->mode == LWS_CONNMODE_WS_CLIENT)
712 n = LWS_CALLBACK_CLIENT_WRITEABLE;
713 else
714 n = LWS_CALLBACK_SERVER_WRITEABLE;
715
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800716 wsi->protocol->callback(context, wsi, (enum libwebsocket_callback_reasons) n, wsi->user_space, NULL, 0);
Andy Green3b84c002011-03-06 13:14:42 +0000717
718 return 0;
719}
720
721
722
Andy Greena41314f2011-05-23 10:00:03 +0100723void
724libwebsocket_service_timeout_check(struct libwebsocket_context *context,
725 struct libwebsocket *wsi, unsigned int sec)
726{
727 int n;
728
729 /*
730 * if extensions want in on it (eg, we are a mux parent)
731 * give them a chance to service child timeouts
732 */
733
734 for (n = 0; n < wsi->count_active_extensions; n++)
735 wsi->active_extensions[n]->callback(
736 context, wsi->active_extensions[n],
737 wsi, LWS_EXT_CALLBACK_1HZ,
738 wsi->active_extensions_user[n], NULL, sec);
739
740 if (!wsi->pending_timeout)
741 return;
Andy Green6ee372f2012-04-09 15:09:01 +0800742
Andy Greena41314f2011-05-23 10:00:03 +0100743 /*
744 * if we went beyond the allowed time, kill the
745 * connection
746 */
747
748 if (sec > wsi->pending_timeout_limit) {
Andy Green43db0452013-01-10 19:50:35 +0800749 lwsl_info("TIMEDOUT WAITING\n");
Andy Greena41314f2011-05-23 10:00:03 +0100750 libwebsocket_close_and_free_session(context,
751 wsi, LWS_CLOSE_STATUS_NOSTATUS);
752 }
753}
754
755struct libwebsocket *
756libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
757{
758 struct libwebsocket *new_wsi;
759 int n;
760
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800761 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Greena41314f2011-05-23 10:00:03 +0100762 if (new_wsi == NULL) {
Andy Green43db0452013-01-10 19:50:35 +0800763 lwsl_err("Out of memory for new connection\n");
Andy Greena41314f2011-05-23 10:00:03 +0100764 return NULL;
765 }
766
Andy Green6ee372f2012-04-09 15:09:01 +0800767 memset(new_wsi, 0, sizeof(struct libwebsocket));
Andy Greena41314f2011-05-23 10:00:03 +0100768 new_wsi->count_active_extensions = 0;
769 new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
770
771 /* intialize the instance struct */
772
773 new_wsi->state = WSI_STATE_HTTP;
774 new_wsi->name_buffer_pos = 0;
775 new_wsi->mode = LWS_CONNMODE_WS_SERVING;
776
777 for (n = 0; n < WSI_TOKEN_COUNT; n++) {
778 new_wsi->utf8_token[n].token = NULL;
779 new_wsi->utf8_token[n].token_len = 0;
780 }
781
782 /*
783 * these can only be set once the protocol is known
784 * we set an unestablished connection's protocol pointer
785 * to the start of the supported list, so it can look
786 * for matching ones during the handshake
787 */
788 new_wsi->protocol = context->protocols;
789 new_wsi->user_space = NULL;
790
791 /*
792 * Default protocol is 76 / 00
793 * After 76, there's a header specified to inform which
794 * draft the client wants, when that's seen we modify
795 * the individual connection's spec revision accordingly
796 */
797 new_wsi->ietf_spec_revision = 0;
798
799 return new_wsi;
800}
801
802char *
803libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
804 struct libwebsocket *wsi, char *pkt)
805{
806 char hash[20];
807 char *p = pkt;
808 int n;
809 struct libwebsocket_extension *ext;
Andy Green09226502011-05-28 10:19:19 +0100810 struct libwebsocket_extension *ext1;
Andy Greena41314f2011-05-23 10:00:03 +0100811 int ext_count = 0;
Andy Green6ee372f2012-04-09 15:09:01 +0800812 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
813 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena41314f2011-05-23 10:00:03 +0100814 static const char magic_websocket_guid[] =
815 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
816
817 /*
818 * create the random key
819 */
820
821 n = libwebsockets_get_random(context, hash, 16);
822 if (n != 16) {
Andy Green43db0452013-01-10 19:50:35 +0800823 lwsl_err("Unable to read from random dev %s\n",
Andy Greena41314f2011-05-23 10:00:03 +0100824 SYSTEM_RANDOM_FILEPATH);
825 free(wsi->c_path);
826 free(wsi->c_host);
827 if (wsi->c_origin)
828 free(wsi->c_origin);
829 if (wsi->c_protocol)
830 free(wsi->c_protocol);
831 libwebsocket_close_and_free_session(context, wsi,
832 LWS_CLOSE_STATUS_NOSTATUS);
833 return NULL;
834 }
835
836 lws_b64_encode_string(hash, 16, wsi->key_b64,
837 sizeof wsi->key_b64);
838
839 /*
840 * 00 example client handshake
841 *
842 * GET /socket.io/websocket HTTP/1.1
843 * Upgrade: WebSocket
844 * Connection: Upgrade
845 * Host: 127.0.0.1:9999
846 * Origin: http://127.0.0.1
847 * Sec-WebSocket-Key1: 1 0 2#0W 9 89 7 92 ^
848 * Sec-WebSocket-Key2: 7 7Y 4328 B2v[8(z1
849 * Cookie: socketio=websocket
850 *
851 * (Á®Ä0¶†≥
852 *
853 * 04 example client handshake
854 *
855 * GET /chat HTTP/1.1
856 * Host: server.example.com
857 * Upgrade: websocket
858 * Connection: Upgrade
859 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
860 * Sec-WebSocket-Origin: http://example.com
861 * Sec-WebSocket-Protocol: chat, superchat
862 * Sec-WebSocket-Version: 4
863 */
864
865 p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a", wsi->c_path);
866
David Galeano4fbc40c2013-01-10 10:26:05 +0800867 p += sprintf(p, "Pragma: no-cache\x0d\x0a"
868 "Cache-Control: no-cache\x0d\x0a");
869
Andy Greena41314f2011-05-23 10:00:03 +0100870 if (wsi->ietf_spec_revision == 0) {
871 unsigned char spaces_1, spaces_2;
872 unsigned int max_1, max_2;
873 unsigned int num_1, num_2;
874 unsigned long product_1, product_2;
875 char key_1[40];
876 char key_2[40];
877 unsigned int seed;
878 unsigned int count;
879 char challenge[16];
880
Andy Green6ee372f2012-04-09 15:09:01 +0800881 libwebsockets_get_random(context, &spaces_1, sizeof(char));
882 libwebsockets_get_random(context, &spaces_2, sizeof(char));
Andy Greena41314f2011-05-23 10:00:03 +0100883
884 spaces_1 = (spaces_1 % 12) + 1;
885 spaces_2 = (spaces_2 % 12) + 1;
886
887 max_1 = 4294967295 / spaces_1;
888 max_2 = 4294967295 / spaces_2;
889
890 libwebsockets_get_random(context, &num_1, sizeof(int));
891 libwebsockets_get_random(context, &num_2, sizeof(int));
892
893 num_1 = (num_1 % max_1);
894 num_2 = (num_2 % max_2);
895
896 challenge[0] = num_1 >> 24;
897 challenge[1] = num_1 >> 16;
898 challenge[2] = num_1 >> 8;
899 challenge[3] = num_1;
900 challenge[4] = num_2 >> 24;
901 challenge[5] = num_2 >> 16;
902 challenge[6] = num_2 >> 8;
903 challenge[7] = num_2;
904
905 product_1 = num_1 * spaces_1;
906 product_2 = num_2 * spaces_2;
907
908 sprintf(key_1, "%lu", product_1);
909 sprintf(key_2, "%lu", product_2);
910
911 libwebsockets_get_random(context, &seed, sizeof(int));
912 libwebsockets_get_random(context, &count, sizeof(int));
913
914 libwebsockets_00_spam(key_1, (count % 12) + 1, seed);
915
916 libwebsockets_get_random(context, &seed, sizeof(int));
917 libwebsockets_get_random(context, &count, sizeof(int));
918
919 libwebsockets_00_spam(key_2, (count % 12) + 1, seed);
920
921 libwebsockets_get_random(context, &seed, sizeof(int));
922
923 libwebsockets_00_spaceout(key_1, spaces_1, seed);
924 libwebsockets_00_spaceout(key_2, spaces_2, seed >> 16);
925
926 p += sprintf(p, "Upgrade: WebSocket\x0d\x0a"
927 "Connection: Upgrade\x0d\x0aHost: %s\x0d\x0a",
928 wsi->c_host);
929 if (wsi->c_origin)
Andy Green6ee372f2012-04-09 15:09:01 +0800930 p += sprintf(p, "Origin: %s\x0d\x0a", wsi->c_origin);
Andy Greena41314f2011-05-23 10:00:03 +0100931
932 if (wsi->c_protocol)
933 p += sprintf(p, "Sec-WebSocket-Protocol: %s"
934 "\x0d\x0a", wsi->c_protocol);
935
Andy Green6ee372f2012-04-09 15:09:01 +0800936 p += sprintf(p, "Sec-WebSocket-Key1: %s\x0d\x0a", key_1);
937 p += sprintf(p, "Sec-WebSocket-Key2: %s\x0d\x0a", key_2);
Andy Greena41314f2011-05-23 10:00:03 +0100938
939 /* give userland a chance to append, eg, cookies */
940
941 context->protocols[0].callback(context, wsi,
942 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
943 NULL, &p, (pkt + sizeof(pkt)) - p - 12);
944
945 p += sprintf(p, "\x0d\x0a");
946
947 if (libwebsockets_get_random(context, p, 8) != 8)
948 return NULL;
949 memcpy(&challenge[8], p, 8);
950 p += 8;
951
952 /* precompute what we want to see from the server */
953
954 MD5((unsigned char *)challenge, 16,
955 (unsigned char *)wsi->initial_handshake_hash_base64);
956
957 goto issue_hdr;
958 }
959
960 p += sprintf(p, "Host: %s\x0d\x0a", wsi->c_host);
David Galeano4fbc40c2013-01-10 10:26:05 +0800961 p += sprintf(p, "Upgrade: websocket\x0d\x0a"
962 "Connection: Upgrade\x0d\x0a"
963 "Sec-WebSocket-Key: ");
Andy Greena41314f2011-05-23 10:00:03 +0100964 strcpy(p, wsi->key_b64);
965 p += strlen(wsi->key_b64);
966 p += sprintf(p, "\x0d\x0a");
David Galeanoaa0bc862013-01-09 15:31:46 +0800967 if (wsi->c_origin) {
968 if (wsi->ietf_spec_revision == 13) {
969 p += sprintf(p, "Origin: %s\x0d\x0a",
970 wsi->c_origin);
971 }
972 else {
David Galeanocb193682013-01-09 15:29:00 +0800973 p += sprintf(p, "Sec-WebSocket-Origin: %s\x0d\x0a",
Andy Greena41314f2011-05-23 10:00:03 +0100974 wsi->c_origin);
David Galeanoaa0bc862013-01-09 15:31:46 +0800975 }
976 }
Andy Greena41314f2011-05-23 10:00:03 +0100977 if (wsi->c_protocol)
978 p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
979 wsi->c_protocol);
980
981 /* tell the server what extensions we could support */
982
983 p += sprintf(p, "Sec-WebSocket-Extensions: ");
984
Andy Green6ee372f2012-04-09 15:09:01 +0800985 ext = context->extensions;
Andy Greena41314f2011-05-23 10:00:03 +0100986 while (ext && ext->callback) {
987
988 n = 0;
Andy Green09226502011-05-28 10:19:19 +0100989 ext1 = context->extensions;
Andy Green09226502011-05-28 10:19:19 +0100990
Andy Green6ee372f2012-04-09 15:09:01 +0800991 while (ext1 && ext1->callback) {
Andy Green09226502011-05-28 10:19:19 +0100992 n |= ext1->callback(context, ext1, wsi,
993 LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
994 NULL, (char *)ext->name, 0);
995
996 ext1++;
997 }
998
Andy Green6ee372f2012-04-09 15:09:01 +0800999 if (n) { /* an extension vetos us */
Andy Green43db0452013-01-10 19:50:35 +08001000 lwsl_ext("ext %s vetoed\n", (char *)ext->name);
Andy Green09226502011-05-28 10:19:19 +01001001 ext++;
1002 continue;
1003 }
1004
Andy Greena41314f2011-05-23 10:00:03 +01001005 n = context->protocols[0].callback(context, wsi,
1006 LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
1007 wsi->user_space, (char *)ext->name, 0);
1008
1009 /*
1010 * zero return from callback means
1011 * go ahead and allow the extension,
1012 * it's what we get if the callback is
1013 * unhandled
1014 */
1015
1016 if (n) {
1017 ext++;
1018 continue;
1019 }
1020
1021 /* apply it */
1022
1023 if (ext_count)
1024 *p++ = ',';
1025 p += sprintf(p, "%s", ext->name);
1026 ext_count++;
1027
1028 ext++;
1029 }
1030
1031 p += sprintf(p, "\x0d\x0a");
1032
1033 if (wsi->ietf_spec_revision)
1034 p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
1035 wsi->ietf_spec_revision);
1036
1037 /* give userland a chance to append, eg, cookies */
1038
1039 context->protocols[0].callback(context, wsi,
1040 LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
1041 NULL, &p, (pkt + sizeof(pkt)) - p - 12);
1042
1043 p += sprintf(p, "\x0d\x0a");
1044
1045 /* prepare the expected server accept response */
1046
1047 strcpy((char *)buf, wsi->key_b64);
1048 strcpy((char *)&buf[strlen((char *)buf)], magic_websocket_guid);
1049
1050 SHA1(buf, strlen((char *)buf), (unsigned char *)hash);
1051
1052 lws_b64_encode_string(hash, 20,
1053 wsi->initial_handshake_hash_base64,
1054 sizeof wsi->initial_handshake_hash_base64);
1055
1056issue_hdr:
1057
Andy Green6ee372f2012-04-09 15:09:01 +08001058#if 0
1059 puts(pkt);
1060#endif
Andy Green09226502011-05-28 10:19:19 +01001061
Andy Greena41314f2011-05-23 10:00:03 +01001062 /* done with these now */
1063
1064 free(wsi->c_path);
1065 free(wsi->c_host);
1066 if (wsi->c_origin)
1067 free(wsi->c_origin);
1068
1069 return p;
1070}
1071
1072int
1073lws_client_interpret_server_handshake(struct libwebsocket_context *context,
1074 struct libwebsocket *wsi)
1075{
Andy Green6ee372f2012-04-09 15:09:01 +08001076 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
1077 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena41314f2011-05-23 10:00:03 +01001078 char pkt[1024];
1079 char *p = &pkt[0];
1080 const char *pc;
1081 const char *c;
1082 int more = 1;
1083 int okay = 0;
1084 char ext_name[128];
1085 struct libwebsocket_extension *ext;
1086 void *v;
Andy Greenc15cb382011-06-26 10:27:28 +01001087 int len = 0;
Andy Greena41314f2011-05-23 10:00:03 +01001088 int n;
1089 static const char magic_websocket_04_masking_guid[] =
1090 "61AC5F19-FBBA-4540-B96F-6561F1AB40A8";
1091
1092 /*
1093 * 00 / 76 -->
1094 *
1095 * HTTP/1.1 101 WebSocket Protocol Handshake
1096 * Upgrade: WebSocket
1097 * Connection: Upgrade
1098 * Sec-WebSocket-Origin: http://127.0.0.1
1099 * Sec-WebSocket-Location: ws://127.0.0.1:9999/socket.io/websocket
1100 *
1101 * xxxxxxxxxxxxxxxx
1102 */
1103
1104 if (wsi->ietf_spec_revision == 0) {
1105 if (!wsi->utf8_token[WSI_TOKEN_HTTP].token_len ||
1106 !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
1107 !wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len ||
1108 !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len ||
1109 (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len &&
1110 wsi->c_protocol != NULL)) {
Andy Green43db0452013-01-10 19:50:35 +08001111 lwsl_parser("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001112 "missing required header(s)\n");
1113 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001114 lwsl_parser("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001115 goto bail3;
1116 }
1117
1118 strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token);
Andy Green6ee372f2012-04-09 15:09:01 +08001119 if (strncmp(wsi->utf8_token[WSI_TOKEN_HTTP].token, "101", 3)) {
Andy Green43db0452013-01-10 19:50:35 +08001120 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001121 "server sent bad HTTP response '%s'\n",
1122 wsi->utf8_token[WSI_TOKEN_HTTP].token);
1123 goto bail3;
1124 }
1125
Andy Green6ee372f2012-04-09 15:09:01 +08001126 if (wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len < 16) {
Andy Green43db0452013-01-10 19:50:35 +08001127 lwsl_parser("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001128 "challenge reply too short %d\n",
1129 wsi->utf8_token[
1130 WSI_TOKEN_CHALLENGE].token_len);
1131 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001132 lwsl_parser("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001133 goto bail3;
1134
1135 }
1136
1137 goto select_protocol;
1138 }
1139
1140 /*
1141 * well, what the server sent looked reasonable for syntax.
1142 * Now let's confirm it sent all the necessary headers
1143 */
1144#if 0
Andy Green43db0452013-01-10 19:50:35 +08001145 lwsl_parser("WSI_TOKEN_HTTP: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001146 wsi->utf8_token[WSI_TOKEN_HTTP].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001147 lwsl_parser("WSI_TOKEN_UPGRADE: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001148 wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001149 lwsl_parser("WSI_TOKEN_CONNECTION: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001150 wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001151 lwsl_parser("WSI_TOKEN_ACCEPT: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001152 wsi->utf8_token[WSI_TOKEN_ACCEPT].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001153 lwsl_parser("WSI_TOKEN_NONCE: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001154 wsi->utf8_token[WSI_TOKEN_NONCE].token_len);
Andy Green43db0452013-01-10 19:50:35 +08001155 lwsl_parser("WSI_TOKEN_PROTOCOL: %d\n",
Andy Green6ee372f2012-04-09 15:09:01 +08001156 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len);
Andy Greena41314f2011-05-23 10:00:03 +01001157#endif
Andy Green6ee372f2012-04-09 15:09:01 +08001158 if (!wsi->utf8_token[WSI_TOKEN_HTTP].token_len ||
1159 !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
1160 !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len ||
1161 !wsi->utf8_token[WSI_TOKEN_ACCEPT].token_len ||
1162 (!wsi->utf8_token[WSI_TOKEN_NONCE].token_len &&
Andy Greena41314f2011-05-23 10:00:03 +01001163 wsi->ietf_spec_revision == 4) ||
Andy Green6ee372f2012-04-09 15:09:01 +08001164 (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len &&
1165 wsi->c_protocol != NULL)) {
Andy Green43db0452013-01-10 19:50:35 +08001166 lwsl_parser("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001167 "missing required header(s)\n");
1168 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001169 lwsl_parser("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001170 goto bail3;
1171 }
1172
1173 /*
1174 * Everything seems to be there, now take a closer look at what
1175 * is in each header
1176 */
1177
1178 strtolower(wsi->utf8_token[WSI_TOKEN_HTTP].token);
Artem Egorkined515ddd2011-11-23 10:46:24 +02001179 if (strncmp(wsi->utf8_token[WSI_TOKEN_HTTP].token, "101", 3)) {
Andy Green43db0452013-01-10 19:50:35 +08001180 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001181 "server sent bad HTTP response '%s'\n",
1182 wsi->utf8_token[WSI_TOKEN_HTTP].token);
1183 goto bail3;
1184 }
1185
1186 strtolower(wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
1187 if (strcmp(wsi->utf8_token[WSI_TOKEN_UPGRADE].token,
1188 "websocket")) {
Andy Green43db0452013-01-10 19:50:35 +08001189 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001190 "sent bad Upgrade header '%s'\n",
1191 wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
1192 goto bail3;
1193 }
1194
1195 strtolower(wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
1196 if (strcmp(wsi->utf8_token[WSI_TOKEN_CONNECTION].token,
1197 "upgrade")) {
Andy Green43db0452013-01-10 19:50:35 +08001198 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001199 "sent bad Connection hdr '%s'\n",
1200 wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
1201 goto bail3;
1202 }
1203
1204select_protocol:
1205 pc = wsi->c_protocol;
1206 if (pc == NULL)
Andy Green43db0452013-01-10 19:50:35 +08001207 lwsl_parser("lws_client_interpret_server_handshake: "
Andy Green6ee372f2012-04-09 15:09:01 +08001208 "NULL c_protocol\n");
Andy Greena41314f2011-05-23 10:00:03 +01001209 else
Andy Green43db0452013-01-10 19:50:35 +08001210 lwsl_parser("lws_client_interpret_server_handshake: "
Andy Green6ee372f2012-04-09 15:09:01 +08001211 "cPprotocol='%s'\n", pc);
Andy Greena41314f2011-05-23 10:00:03 +01001212
1213 /*
1214 * confirm the protocol the server wants to talk was in the list
1215 * of protocols we offered
1216 */
1217
1218 if (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len) {
1219
Andy Green43db0452013-01-10 19:50:35 +08001220 lwsl_warn("lws_client_interpret_server_handshake "
Andy Green6ee372f2012-04-09 15:09:01 +08001221 "WSI_TOKEN_PROTOCOL is null\n");
Andy Greena41314f2011-05-23 10:00:03 +01001222 /*
1223 * no protocol name to work from,
1224 * default to first protocol
1225 */
1226 wsi->protocol = &context->protocols[0];
David Brooks2c60d952012-04-20 12:19:01 +08001227 wsi->c_callback = wsi->protocol->callback;
Andy Greena41314f2011-05-23 10:00:03 +01001228 free(wsi->c_protocol);
1229
David Galeano4c38f142013-01-09 19:49:50 +08001230 goto check_extensions;
Andy Greena41314f2011-05-23 10:00:03 +01001231 }
1232
1233 while (*pc && !okay) {
Andy Green6ee372f2012-04-09 15:09:01 +08001234 if ((!strncmp(pc, wsi->utf8_token[WSI_TOKEN_PROTOCOL].token,
1235 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len)) &&
1236 (pc[wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len] == ',' ||
1237 pc[wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len] == '\0')) {
Andy Greena41314f2011-05-23 10:00:03 +01001238 okay = 1;
1239 continue;
1240 }
1241 while (*pc && *pc != ',')
1242 pc++;
1243 while (*pc && *pc != ' ')
1244 pc++;
1245 }
1246
1247 /* done with him now */
1248
1249 if (wsi->c_protocol)
1250 free(wsi->c_protocol);
1251
Andy Greena41314f2011-05-23 10:00:03 +01001252 if (!okay) {
Andy Green43db0452013-01-10 19:50:35 +08001253 lwsl_err("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001254 "sent bad protocol '%s'\n",
1255 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
1256 goto bail2;
1257 }
1258
1259 /*
1260 * identify the selected protocol struct and set it
1261 */
1262 n = 0;
1263 wsi->protocol = NULL;
David Brooks2c60d952012-04-20 12:19:01 +08001264 while (context->protocols[n].callback && !wsi->protocol) { /* Stop after finding first one?? */
Andy Greena41314f2011-05-23 10:00:03 +01001265 if (strcmp(wsi->utf8_token[WSI_TOKEN_PROTOCOL].token,
David Brooks2c60d952012-04-20 12:19:01 +08001266 context->protocols[n].name) == 0) {
Andy Greena41314f2011-05-23 10:00:03 +01001267 wsi->protocol = &context->protocols[n];
David Brooks2c60d952012-04-20 12:19:01 +08001268 wsi->c_callback = wsi->protocol->callback;
1269 }
Andy Greena41314f2011-05-23 10:00:03 +01001270 n++;
1271 }
1272
1273 if (wsi->protocol == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08001274 lwsl_err("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001275 "requested protocol '%s', which we "
1276 "said we supported but we don't!\n",
1277 wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
1278 goto bail2;
1279 }
1280
1281
David Galeano4c38f142013-01-09 19:49:50 +08001282check_extensions:
1283
Andy Greena41314f2011-05-23 10:00:03 +01001284 /* instantiate the accepted extensions */
1285
1286 if (!wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token_len) {
Andy Green43db0452013-01-10 19:50:35 +08001287 lwsl_ext("no client extenstions allowed by server\n");
Andy Greena41314f2011-05-23 10:00:03 +01001288 goto check_accept;
1289 }
1290
1291 /*
1292 * break down the list of server accepted extensions
1293 * and go through matching them or identifying bogons
1294 */
1295
1296 c = wsi->utf8_token[WSI_TOKEN_EXTENSIONS].token;
1297 n = 0;
1298 while (more) {
1299
1300 if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
1301 ext_name[n] = *c++;
1302 if (n < sizeof(ext_name) - 1)
1303 n++;
1304 continue;
1305 }
1306 ext_name[n] = '\0';
1307 if (!*c)
1308 more = 0;
1309 else {
1310 c++;
1311 if (!n)
1312 continue;
1313 }
1314
1315 /* check we actually support it */
1316
Andy Green43db0452013-01-10 19:50:35 +08001317 lwsl_ext("checking client ext %s\n", ext_name);
Andy Greena41314f2011-05-23 10:00:03 +01001318
1319 n = 0;
1320 ext = wsi->protocol->owning_server->extensions;
1321 while (ext && ext->callback) {
1322
1323 if (strcmp(ext_name, ext->name)) {
1324 ext++;
1325 continue;
1326 }
1327
1328 n = 1;
1329
Andy Green43db0452013-01-10 19:50:35 +08001330 lwsl_ext("instantiating client ext %s\n", ext_name);
Andy Greena41314f2011-05-23 10:00:03 +01001331
1332 /* instantiate the extension on this conn */
1333
1334 wsi->active_extensions_user[
1335 wsi->count_active_extensions] =
1336 malloc(ext->per_session_data_size);
Andy Greenf6652412011-05-25 20:46:18 +01001337 memset(wsi->active_extensions_user[
1338 wsi->count_active_extensions], 0,
1339 ext->per_session_data_size);
Andy Greena41314f2011-05-23 10:00:03 +01001340 wsi->active_extensions[
1341 wsi->count_active_extensions] = ext;
1342
1343 /* allow him to construct his context */
1344
1345 ext->callback(wsi->protocol->owning_server,
1346 ext, wsi,
1347 LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
1348 wsi->active_extensions_user[
1349 wsi->count_active_extensions],
1350 NULL, 0);
1351
1352 wsi->count_active_extensions++;
1353
1354 ext++;
1355 }
1356
1357 if (n == 0) {
Andy Green43db0452013-01-10 19:50:35 +08001358 lwsl_warn("Server said we should use"
Andy Greena41314f2011-05-23 10:00:03 +01001359 "an unknown extension '%s'!\n", ext_name);
1360 goto bail2;
1361 }
1362
1363 n = 0;
1364 }
1365
1366
1367check_accept:
1368
1369 if (wsi->ietf_spec_revision == 0) {
1370
1371 if (memcmp(wsi->initial_handshake_hash_base64,
1372 wsi->utf8_token[WSI_TOKEN_CHALLENGE].token, 16)) {
Andy Green43db0452013-01-10 19:50:35 +08001373 lwsl_warn("libwebsocket_client_handshake "
Andy Greena41314f2011-05-23 10:00:03 +01001374 "failed 00 challenge compare\n");
1375 pkt[len] = '\0';
Andy Green43db0452013-01-10 19:50:35 +08001376 lwsl_warn("%s", pkt);
Andy Greena41314f2011-05-23 10:00:03 +01001377 goto bail2;
1378 }
1379
1380 goto accept_ok;
1381 }
1382
1383 /*
1384 * Confirm his accept token is the one we precomputed
1385 */
1386
1387 if (strcmp(wsi->utf8_token[WSI_TOKEN_ACCEPT].token,
1388 wsi->initial_handshake_hash_base64)) {
Andy Green43db0452013-01-10 19:50:35 +08001389 lwsl_warn("libwebsocket_client_handshake server "
Andy Greena41314f2011-05-23 10:00:03 +01001390 "sent bad ACCEPT '%s' vs computed '%s'\n",
1391 wsi->utf8_token[WSI_TOKEN_ACCEPT].token,
1392 wsi->initial_handshake_hash_base64);
1393 goto bail2;
1394 }
1395
1396 if (wsi->ietf_spec_revision == 4) {
1397 /*
1398 * Calculate the 04 masking key to use when
1399 * sending data to server
1400 */
1401
1402 strcpy((char *)buf, wsi->key_b64);
1403 p = (char *)buf + strlen(wsi->key_b64);
1404 strcpy(p, wsi->utf8_token[WSI_TOKEN_NONCE].token);
1405 p += wsi->utf8_token[WSI_TOKEN_NONCE].token_len;
1406 strcpy(p, magic_websocket_04_masking_guid);
1407 SHA1(buf, strlen((char *)buf), wsi->masking_key_04);
1408 }
Andy Green6ee372f2012-04-09 15:09:01 +08001409accept_ok:
Andy Greena41314f2011-05-23 10:00:03 +01001410
1411 /* allocate the per-connection user memory (if any) */
Andy Green6ee372f2012-04-09 15:09:01 +08001412 if (wsi->protocol->per_session_data_size &&
1413 !libwebsocket_ensure_user_space(wsi))
1414 goto bail2;
Andy Greena41314f2011-05-23 10:00:03 +01001415
1416 /* clear his proxy connection timeout */
1417
1418 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1419
1420 /* mark him as being alive */
1421
1422 wsi->state = WSI_STATE_ESTABLISHED;
1423 wsi->mode = LWS_CONNMODE_WS_CLIENT;
1424
Andy Green43db0452013-01-10 19:50:35 +08001425 lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
Andy Greena41314f2011-05-23 10:00:03 +01001426
1427 /* call him back to inform him he is up */
1428
1429 wsi->protocol->callback(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08001430 LWS_CALLBACK_CLIENT_ESTABLISHED,
1431 wsi->user_space, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01001432
1433 /*
1434 * inform all extensions, not just active ones since they
1435 * already know
1436 */
1437
1438 ext = context->extensions;
1439
1440 while (ext && ext->callback) {
1441 v = NULL;
1442 for (n = 0; n < wsi->count_active_extensions; n++)
1443 if (wsi->active_extensions[n] == ext)
1444 v = wsi->active_extensions_user[n];
1445
1446 ext->callback(context, ext, wsi,
1447 LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED, v, NULL, 0);
1448 ext++;
1449 }
1450
1451 return 0;
1452
1453bail3:
1454 if (wsi->c_protocol)
1455 free(wsi->c_protocol);
1456
1457bail2:
David Brooks80a44972012-04-20 12:18:47 +08001458 if (wsi->c_callback) wsi->c_callback(context, wsi,
1459 LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
1460 wsi->user_space,
1461 NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01001462 libwebsocket_close_and_free_session(context, wsi,
David Brooks80a44972012-04-20 12:18:47 +08001463 LWS_CLOSE_STATUS_NOSTATUS); // But this should be LWS_CLOSE_STATUS_PROTOCOL_ERR
1464
Andy Greena41314f2011-05-23 10:00:03 +01001465 return 1;
1466}
1467
1468
1469
Andy Green9f990342011-02-12 11:57:45 +00001470/**
1471 * libwebsocket_service_fd() - Service polled socket with something waiting
Peter Hinz56885f32011-03-02 22:03:47 +00001472 * @context: Websocket context
Andy Green9f990342011-02-12 11:57:45 +00001473 * @pollfd: The pollfd entry describing the socket fd and which events
Andy Green6ee372f2012-04-09 15:09:01 +08001474 * happened.
Andy Green9f990342011-02-12 11:57:45 +00001475 *
1476 * This function closes any active connections and then frees the
1477 * context. After calling this, any further use of the context is
1478 * undefined.
1479 */
1480
1481int
Peter Hinz56885f32011-03-02 22:03:47 +00001482libwebsocket_service_fd(struct libwebsocket_context *context,
Andy Green0d338332011-02-12 11:57:43 +00001483 struct pollfd *pollfd)
Andy Greenb45993c2010-12-18 15:13:50 +00001484{
Andy Green6ee372f2012-04-09 15:09:01 +08001485 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
1486 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greena71eafc2011-02-14 17:59:43 +00001487 struct libwebsocket *wsi;
Andy Green0d338332011-02-12 11:57:43 +00001488 struct libwebsocket *new_wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00001489 int n;
Andy Green0d338332011-02-12 11:57:43 +00001490 int m;
Tobias Maiere8c9b562012-04-05 11:57:12 +02001491 ssize_t len;
Andy Green0d338332011-02-12 11:57:43 +00001492 int accept_fd;
1493 unsigned int clilen;
1494 struct sockaddr_in cli_addr;
Andy Greena71eafc2011-02-14 17:59:43 +00001495 struct timeval tv;
Andy Greenbe93fef2011-02-14 20:25:43 +00001496 char pkt[1024];
1497 char *p = &pkt[0];
Andy Green2366b1c2011-03-06 13:15:31 +00001498 int more = 1;
Andy Green98a717c2011-03-06 13:14:15 +00001499 struct lws_tokens eff_buf;
Andy Green6c939552011-03-08 08:56:57 +00001500 int opt = 1;
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001501 char c;
Andy Greenc6517fa2011-03-06 13:15:29 +00001502
Andy Greenbe93fef2011-02-14 20:25:43 +00001503#ifdef LWS_OPENSSL_SUPPORT
1504 char ssl_err_buf[512];
1505#endif
Andy Greena71eafc2011-02-14 17:59:43 +00001506 /*
1507 * you can call us with pollfd = NULL to just allow the once-per-second
1508 * global timeout checks; if less than a second since the last check
1509 * it returns immediately then.
1510 */
1511
1512 gettimeofday(&tv, NULL);
1513
Peter Hinz56885f32011-03-02 22:03:47 +00001514 if (context->last_timeout_check_s != tv.tv_sec) {
1515 context->last_timeout_check_s = tv.tv_sec;
Andy Greena71eafc2011-02-14 17:59:43 +00001516
1517 /* global timeout check once per second */
1518
Peter Hinz56885f32011-03-02 22:03:47 +00001519 for (n = 0; n < context->fds_count; n++) {
1520 wsi = wsi_from_fd(context, context->fds[n].fd);
Andy Greena71eafc2011-02-14 17:59:43 +00001521
Andy Greena41314f2011-05-23 10:00:03 +01001522 libwebsocket_service_timeout_check(context, wsi,
1523 tv.tv_sec);
Andy Greena71eafc2011-02-14 17:59:43 +00001524 }
1525 }
1526
1527 /* just here for timeout management? */
1528
1529 if (pollfd == NULL)
1530 return 0;
1531
1532 /* no, here to service a socket descriptor */
1533
Peter Hinz56885f32011-03-02 22:03:47 +00001534 wsi = wsi_from_fd(context, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001535
Andy Green0d338332011-02-12 11:57:43 +00001536 if (wsi == NULL)
Andy Greenfa3f4052012-10-07 20:40:35 +08001537 return 0;
Andy Green8f037e42010-12-19 22:13:26 +00001538
Andy Green0d338332011-02-12 11:57:43 +00001539 switch (wsi->mode) {
1540 case LWS_CONNMODE_SERVER_LISTENER:
1541
1542 /* pollin means a client has connected to us then */
1543
David Galeanob88e0962013-01-10 09:54:10 +08001544 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001545 break;
1546
David Galeanof7009352011-09-26 12:09:54 +01001547 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001548 lwsl_warn("too busy to accept new client\n");
David Galeanof7009352011-09-26 12:09:54 +01001549 break;
1550 }
1551
Andy Green0d338332011-02-12 11:57:43 +00001552 /* listen socket got an unencrypted connection... */
1553
1554 clilen = sizeof(cli_addr);
1555 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1556 &clilen);
1557 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001558 lwsl_warn("ERROR on accept: %d\n", strerror(errno));
Andy Green3928f612012-07-20 12:58:38 +08001559 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001560 }
1561
Andy Green6c939552011-03-08 08:56:57 +00001562 /* Disable Nagle */
1563 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08001564 setsockopt(accept_fd, IPPROTO_TCP, TCP_NODELAY,
1565 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00001566
Andy Green07034092011-02-13 08:37:12 +00001567 /*
1568 * look at who we connected to and give user code a chance
1569 * to reject based on client IP. There's no protocol selected
1570 * yet so we issue this to protocols[0]
1571 */
1572
Peter Hinz56885f32011-03-02 22:03:47 +00001573 if ((context->protocols[0].callback)(context, wsi,
Andy Green07034092011-02-13 08:37:12 +00001574 LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
Andy Green6ee372f2012-04-09 15:09:01 +08001575 (void *)(long)accept_fd, NULL, 0)) {
Andy Green43db0452013-01-10 19:50:35 +08001576 lwsl_debug("Callback denied network connection\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001577#ifdef WIN32
1578 closesocket(accept_fd);
1579#else
Andy Green07034092011-02-13 08:37:12 +00001580 close(accept_fd);
Peter Hinz56885f32011-03-02 22:03:47 +00001581#endif
Andy Green07034092011-02-13 08:37:12 +00001582 break;
1583 }
1584
Andy Green0d338332011-02-12 11:57:43 +00001585 /* accepting connection to main listener */
1586
Andy Greena41314f2011-05-23 10:00:03 +01001587 new_wsi = libwebsocket_create_new_server_wsi(context);
David Galeanoed3c8402013-01-10 10:45:24 +08001588 if (new_wsi == NULL) {
1589#ifdef WIN32
1590 closesocket(accept_fd);
1591#else
1592 close(accept_fd);
1593#endif
Andy Green0d338332011-02-12 11:57:43 +00001594 break;
David Galeanoed3c8402013-01-10 10:45:24 +08001595 }
Andy Green0d338332011-02-12 11:57:43 +00001596
Andy Green0d338332011-02-12 11:57:43 +00001597 new_wsi->sock = accept_fd;
Andy Greena41314f2011-05-23 10:00:03 +01001598
Andy Green0d338332011-02-12 11:57:43 +00001599
1600#ifdef LWS_OPENSSL_SUPPORT
1601 new_wsi->ssl = NULL;
Andy Green0d338332011-02-12 11:57:43 +00001602
Peter Hinz56885f32011-03-02 22:03:47 +00001603 if (context->use_ssl) {
Andy Green0d338332011-02-12 11:57:43 +00001604
Peter Hinz56885f32011-03-02 22:03:47 +00001605 new_wsi->ssl = SSL_new(context->ssl_ctx);
Andy Green0d338332011-02-12 11:57:43 +00001606 if (new_wsi->ssl == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08001607 lwsl_err("SSL_new failed: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001608 ERR_error_string(SSL_get_error(
1609 new_wsi->ssl, 0), NULL));
Andy Green1f9bf522011-02-14 21:14:37 +00001610 libwebsockets_decode_ssl_error();
Andy Green0d338332011-02-12 11:57:43 +00001611 free(new_wsi);
David Galeanoed3c8402013-01-10 10:45:24 +08001612#ifdef WIN32
1613 closesocket(accept_fd);
1614#else
1615 close(accept_fd);
1616#endif
Andy Green0d338332011-02-12 11:57:43 +00001617 break;
1618 }
1619
1620 SSL_set_fd(new_wsi->ssl, accept_fd);
1621
1622 n = SSL_accept(new_wsi->ssl);
1623 if (n != 1) {
1624 /*
1625 * browsers seem to probe with various
1626 * ssl params which fail then retry
1627 * and succeed
1628 */
Andy Green43db0452013-01-10 19:50:35 +08001629 lwsl_debug("SSL_accept failed skt %u: %s\n",
Andy Green0d338332011-02-12 11:57:43 +00001630 pollfd->fd,
1631 ERR_error_string(SSL_get_error(
1632 new_wsi->ssl, n), NULL));
1633 SSL_free(
1634 new_wsi->ssl);
1635 free(new_wsi);
David Galeanoed3c8402013-01-10 10:45:24 +08001636#ifdef WIN32
1637 closesocket(accept_fd);
1638#else
1639 close(accept_fd);
1640#endif
Andy Green0d338332011-02-12 11:57:43 +00001641 break;
1642 }
Andy Green6ee372f2012-04-09 15:09:01 +08001643
Andy Green43db0452013-01-10 19:50:35 +08001644 lwsl_debug("accepted new SSL conn "
Andy Green0d338332011-02-12 11:57:43 +00001645 "port %u on fd=%d SSL ver %s\n",
1646 ntohs(cli_addr.sin_port), accept_fd,
1647 SSL_get_version(new_wsi->ssl));
1648
1649 } else
1650#endif
Andy Green43db0452013-01-10 19:50:35 +08001651 lwsl_debug("accepted new conn port %u on fd=%d\n",
Andy Green0d338332011-02-12 11:57:43 +00001652 ntohs(cli_addr.sin_port), accept_fd);
1653
Peter Hinz56885f32011-03-02 22:03:47 +00001654 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001655
Andy Green0d338332011-02-12 11:57:43 +00001656 /*
1657 * make sure NO events are seen yet on this new socket
1658 * (otherwise we inherit old fds[client].revents from
1659 * previous socket there and die mysteriously! )
1660 */
Peter Hinz56885f32011-03-02 22:03:47 +00001661 context->fds[context->fds_count].revents = 0;
Andy Green0d338332011-02-12 11:57:43 +00001662
Peter Hinz56885f32011-03-02 22:03:47 +00001663 context->fds[context->fds_count].events = POLLIN;
1664 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001665
Andy Green3221f922011-02-12 13:14:11 +00001666 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001667 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001668 LWS_CALLBACK_ADD_POLL_FD,
1669 (void *)(long)accept_fd, NULL, POLLIN);
1670
Andy Green0d338332011-02-12 11:57:43 +00001671 break;
1672
1673 case LWS_CONNMODE_BROADCAST_PROXY_LISTENER:
1674
1675 /* as we are listening, POLLIN means accept() is needed */
Andy Green6ee372f2012-04-09 15:09:01 +08001676
David Galeanob88e0962013-01-10 09:54:10 +08001677 if (!(pollfd->revents & POLLIN))
Andy Green0d338332011-02-12 11:57:43 +00001678 break;
1679
1680 /* listen socket got an unencrypted connection... */
1681
1682 clilen = sizeof(cli_addr);
1683 accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
1684 &clilen);
1685 if (accept_fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001686 lwsl_warn("ERROR on accept %d\n", accept_fd);
Andy Green3928f612012-07-20 12:58:38 +08001687 return -1;
Andy Green0d338332011-02-12 11:57:43 +00001688 }
1689
Peter Hinz56885f32011-03-02 22:03:47 +00001690 if (context->fds_count >= MAX_CLIENTS) {
Andy Green43db0452013-01-10 19:50:35 +08001691 lwsl_err("too busy to accept new broadcast "
Andy Green3221f922011-02-12 13:14:11 +00001692 "proxy client\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001693#ifdef WIN32
1694 closesocket(accept_fd);
1695#else
Andy Green0d338332011-02-12 11:57:43 +00001696 close(accept_fd);
Peter Hinz56885f32011-03-02 22:03:47 +00001697#endif
Andy Green0d338332011-02-12 11:57:43 +00001698 break;
1699 }
1700
1701 /* create a dummy wsi for the connection and add it */
1702
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001703 new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
1704 memset(new_wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00001705 new_wsi->sock = accept_fd;
1706 new_wsi->mode = LWS_CONNMODE_BROADCAST_PROXY;
1707 new_wsi->state = WSI_STATE_ESTABLISHED;
Andy Greend6e09112011-03-05 16:12:15 +00001708 new_wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00001709 /* note which protocol we are proxying */
1710 new_wsi->protocol_index_for_broadcast_proxy =
1711 wsi->protocol_index_for_broadcast_proxy;
Peter Hinz56885f32011-03-02 22:03:47 +00001712 insert_wsi(context, new_wsi);
Andy Green0d338332011-02-12 11:57:43 +00001713
1714 /* add connected socket to internal poll array */
1715
Peter Hinz56885f32011-03-02 22:03:47 +00001716 context->fds[context->fds_count].revents = 0;
1717 context->fds[context->fds_count].events = POLLIN;
1718 context->fds[context->fds_count++].fd = accept_fd;
Andy Green0d338332011-02-12 11:57:43 +00001719
Andy Green3221f922011-02-12 13:14:11 +00001720 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001721 context->protocols[0].callback(context, new_wsi,
Andy Green3221f922011-02-12 13:14:11 +00001722 LWS_CALLBACK_ADD_POLL_FD,
1723 (void *)(long)accept_fd, NULL, POLLIN);
1724
Andy Green0d338332011-02-12 11:57:43 +00001725 break;
1726
1727 case LWS_CONNMODE_BROADCAST_PROXY:
Andy Green8f037e42010-12-19 22:13:26 +00001728
Andy Greenb45993c2010-12-18 15:13:50 +00001729 /* handle session socket closed */
Andy Green8f037e42010-12-19 22:13:26 +00001730
Andy Green0d338332011-02-12 11:57:43 +00001731 if (pollfd->revents & (POLLERR | POLLHUP)) {
Andy Green8f037e42010-12-19 22:13:26 +00001732
Andy Green43db0452013-01-10 19:50:35 +08001733 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Timothy J Fontaineb86d64e2011-02-14 17:55:27 +00001734 (void *)wsi, pollfd->fd);
Andy Greenb45993c2010-12-18 15:13:50 +00001735
Peter Hinz56885f32011-03-02 22:03:47 +00001736 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001737 LWS_CLOSE_STATUS_NORMAL);
Andy Green4b6fbe12011-02-14 08:03:48 +00001738 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00001739 }
Andy Green8f037e42010-12-19 22:13:26 +00001740
Andy Green3b84c002011-03-06 13:14:42 +00001741 /*
1742 * either extension code with stuff to spill, or the user code,
1743 * requested a callback when it was OK to write
1744 */
Andy Green90c7cbc2011-01-27 06:26:52 +00001745
Andy Green3b84c002011-03-06 13:14:42 +00001746 if (pollfd->revents & POLLOUT)
Andy Green6ee372f2012-04-09 15:09:01 +08001747 if (lws_handle_POLLOUT_event(context, wsi,
1748 pollfd) < 0) {
1749 libwebsocket_close_and_free_session(
1750 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00001751 return 1;
1752 }
Andy Green90c7cbc2011-01-27 06:26:52 +00001753
Andy Greenb45993c2010-12-18 15:13:50 +00001754 /* any incoming data ready? */
1755
Andy Green0d338332011-02-12 11:57:43 +00001756 if (!(pollfd->revents & POLLIN))
1757 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001758
Andy Green0d338332011-02-12 11:57:43 +00001759 /* get the issued broadcast payload from the socket */
Andy Greenb45993c2010-12-18 15:13:50 +00001760
Andy Green0d338332011-02-12 11:57:43 +00001761 len = read(pollfd->fd, buf + LWS_SEND_BUFFER_PRE_PADDING,
1762 MAX_BROADCAST_PAYLOAD);
1763 if (len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001764 lwsl_err("Error reading broadcast payload\n");
Andy Green4b6fbe12011-02-14 08:03:48 +00001765 break;
Andy Green0d338332011-02-12 11:57:43 +00001766 }
Andy Greenb45993c2010-12-18 15:13:50 +00001767
Andy Green0d338332011-02-12 11:57:43 +00001768 /* broadcast it to all guys with this protocol index */
Andy Green8f037e42010-12-19 22:13:26 +00001769
Andy Green0d338332011-02-12 11:57:43 +00001770 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Green8f037e42010-12-19 22:13:26 +00001771
Peter Hinz56885f32011-03-02 22:03:47 +00001772 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00001773
Peter Hinz56885f32011-03-02 22:03:47 +00001774 new_wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00001775
Andy Green0d338332011-02-12 11:57:43 +00001776 /* only to clients we are serving to */
Andy Greenb45993c2010-12-18 15:13:50 +00001777
Andy Green0d338332011-02-12 11:57:43 +00001778 if (new_wsi->mode != LWS_CONNMODE_WS_SERVING)
Andy Greenb45993c2010-12-18 15:13:50 +00001779 continue;
1780
1781 /*
1782 * never broadcast to non-established
1783 * connection
1784 */
1785
Andy Green0d338332011-02-12 11:57:43 +00001786 if (new_wsi->state != WSI_STATE_ESTABLISHED)
Andy Green4739e5c2011-01-22 12:51:57 +00001787 continue;
1788
Andy Greenb45993c2010-12-18 15:13:50 +00001789 /*
1790 * only broadcast to connections using
1791 * the requested protocol
1792 */
1793
Andy Green0d338332011-02-12 11:57:43 +00001794 if (new_wsi->protocol->protocol_index !=
1795 wsi->protocol_index_for_broadcast_proxy)
Andy Greenb45993c2010-12-18 15:13:50 +00001796 continue;
1797
Andy Green8f037e42010-12-19 22:13:26 +00001798 /* broadcast it to this connection */
1799
Peter Hinz56885f32011-03-02 22:03:47 +00001800 new_wsi->protocol->callback(context, new_wsi,
Andy Green8f037e42010-12-19 22:13:26 +00001801 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00001802 new_wsi->user_space,
Andy Green0ca6a172010-12-19 20:50:01 +00001803 buf + LWS_SEND_BUFFER_PRE_PADDING, len);
Andy Greenb45993c2010-12-18 15:13:50 +00001804 }
Andy Green0d338332011-02-12 11:57:43 +00001805 }
1806 break;
Andy Greenb45993c2010-12-18 15:13:50 +00001807
Andy Greenbe93fef2011-02-14 20:25:43 +00001808 case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
1809
1810 /* handle proxy hung up on us */
1811
1812 if (pollfd->revents & (POLLERR | POLLHUP)) {
1813
Andy Green43db0452013-01-10 19:50:35 +08001814 lwsl_warn("Proxy connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00001815 (void *)wsi, pollfd->fd);
1816
Peter Hinz56885f32011-03-02 22:03:47 +00001817 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001818 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001819 return 1;
1820 }
1821
Andy Green72c34322011-04-16 10:46:21 +01001822 n = recv(wsi->sock, pkt, sizeof pkt, 0);
Andy Greenbe93fef2011-02-14 20:25:43 +00001823 if (n < 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001824 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001825 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001826 lwsl_err("ERROR reading from proxy socket\n");
Andy Greenbe93fef2011-02-14 20:25:43 +00001827 return 1;
1828 }
1829
1830 pkt[13] = '\0';
1831 if (strcmp(pkt, "HTTP/1.0 200 ") != 0) {
Peter Hinz56885f32011-03-02 22:03:47 +00001832 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001833 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green43db0452013-01-10 19:50:35 +08001834 lwsl_err("ERROR from proxy: %s\n", pkt);
Andy Greenbe93fef2011-02-14 20:25:43 +00001835 return 1;
1836 }
1837
1838 /* clear his proxy connection timeout */
1839
1840 libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1841
1842 /* fallthru */
1843
1844 case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
1845
1846 #ifdef LWS_OPENSSL_SUPPORT
Ken Atherton8360a472012-05-03 11:45:04 +08001847 if (wsi->use_ssl && !wsi->ssl) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001848
Peter Hinz56885f32011-03-02 22:03:47 +00001849 wsi->ssl = SSL_new(context->ssl_client_ctx);
1850 wsi->client_bio = BIO_new_socket(wsi->sock,
1851 BIO_NOCLOSE);
Andy Greenbe93fef2011-02-14 20:25:43 +00001852 SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
1853
Andy Green6901cb32011-02-21 08:06:47 +00001854 SSL_set_ex_data(wsi->ssl,
Andy Green2e24da02011-03-05 16:12:04 +00001855 openssl_websocket_private_data_index,
Peter Hinz56885f32011-03-02 22:03:47 +00001856 context);
Ken Atherton8360a472012-05-03 11:45:04 +08001857 }
Andy Green6901cb32011-02-21 08:06:47 +00001858
Ken Atherton8360a472012-05-03 11:45:04 +08001859 if (wsi->use_ssl) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001860 if (SSL_connect(wsi->ssl) <= 0) {
Ken Atherton8360a472012-05-03 11:45:04 +08001861
1862 /*
1863 * retry if new data comes until we
1864 * run into the connection timeout or win
1865 */
1866
Andy Green43db0452013-01-10 19:50:35 +08001867 lwsl_err("SSL connect error %s\n",
Andy Green687b0182011-02-26 11:04:01 +00001868 ERR_error_string(ERR_get_error(),
1869 ssl_err_buf));
Ken Atherton8360a472012-05-03 11:45:04 +08001870 return 0;
Andy Greenbe93fef2011-02-14 20:25:43 +00001871 }
1872
1873 n = SSL_get_verify_result(wsi->ssl);
Andy Green2e24da02011-03-05 16:12:04 +00001874 if ((n != X509_V_OK) && (
Andy Green687b0182011-02-26 11:04:01 +00001875 n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
1876 wsi->use_ssl != 2)) {
Andy Greenbe93fef2011-02-14 20:25:43 +00001877
Andy Green43db0452013-01-10 19:50:35 +08001878 lwsl_err("server's cert didn't "
Andy Green687b0182011-02-26 11:04:01 +00001879 "look good %d\n", n);
Peter Hinz56885f32011-03-02 22:03:47 +00001880 libwebsocket_close_and_free_session(context,
1881 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Green687b0182011-02-26 11:04:01 +00001882 return 1;
Andy Greenbe93fef2011-02-14 20:25:43 +00001883 }
Ken Atherton8360a472012-05-03 11:45:04 +08001884 } else
Andy Greenbe93fef2011-02-14 20:25:43 +00001885 wsi->ssl = NULL;
1886 #endif
1887
Andy Greena41314f2011-05-23 10:00:03 +01001888 p = libwebsockets_generate_client_handshake(context, wsi, p);
Andy Green6ee372f2012-04-09 15:09:01 +08001889 if (p == NULL)
Andy Greenbe93fef2011-02-14 20:25:43 +00001890 return 1;
Andy Greeneeaacb32011-03-01 20:44:24 +00001891
Andy Greenbe93fef2011-02-14 20:25:43 +00001892 /* send our request to the server */
1893
1894 #ifdef LWS_OPENSSL_SUPPORT
1895 if (wsi->use_ssl)
1896 n = SSL_write(wsi->ssl, pkt, p - pkt);
1897 else
1898 #endif
1899 n = send(wsi->sock, pkt, p - pkt, 0);
1900
1901 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001902 lwsl_debug("ERROR writing to client socket\n");
Peter Hinz56885f32011-03-02 22:03:47 +00001903 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00001904 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001905 return 1;
1906 }
1907
1908 wsi->parser_state = WSI_TOKEN_NAME_PART;
1909 wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
1910 libwebsocket_set_timeout(wsi,
David Galeanoc9f1ff82013-01-09 18:01:23 +08001911 PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, AWAITING_TIMEOUT);
Andy Greenbe93fef2011-02-14 20:25:43 +00001912
1913 break;
1914
1915 case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
1916
1917 /* handle server hung up on us */
1918
1919 if (pollfd->revents & (POLLERR | POLLHUP)) {
1920
Andy Green43db0452013-01-10 19:50:35 +08001921 lwsl_debug("Server connection %p (fd=%d) dead\n",
Andy Greenbe93fef2011-02-14 20:25:43 +00001922 (void *)wsi, pollfd->fd);
1923
1924 goto bail3;
1925 }
1926
1927
1928 /* interpret the server response */
1929
1930 /*
1931 * HTTP/1.1 101 Switching Protocols
1932 * Upgrade: websocket
1933 * Connection: Upgrade
1934 * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
1935 * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
1936 * Sec-WebSocket-Protocol: chat
1937 */
1938
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001939 /*
1940 * we have to take some care here to only take from the
1941 * socket bytewise. The browser may (and has been seen to
1942 * in the case that onopen() performs websocket traffic)
1943 * coalesce both handshake response and websocket traffic
1944 * in one packet, since at that point the connection is
1945 * definitively ready from browser pov.
1946 */
Andy Greenbe93fef2011-02-14 20:25:43 +00001947
Andy Green7b5af9a2012-04-09 15:23:47 +08001948 len = 1;
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001949 while (wsi->parser_state != WSI_PARSING_COMPLETE && len > 0) {
1950#ifdef LWS_OPENSSL_SUPPORT
1951 if (wsi->use_ssl)
1952 len = SSL_read(wsi->ssl, &c, 1);
1953 else
1954#endif
1955 len = recv(wsi->sock, &c, 1, 0);
1956
1957 libwebsocket_parse(wsi, c);
Andy Greenbe93fef2011-02-14 20:25:43 +00001958 }
1959
Andy Green27a0b912011-04-16 10:54:28 +01001960 /*
Andy Green6ee372f2012-04-09 15:09:01 +08001961 * hs may also be coming in multiple packets, there is a 5-sec
Andy Green27a0b912011-04-16 10:54:28 +01001962 * libwebsocket timeout still active here too, so if parsing did
1963 * not complete just wait for next packet coming in this state
1964 */
1965
1966 if (wsi->parser_state != WSI_PARSING_COMPLETE)
1967 break;
Andy Greenbe93fef2011-02-14 20:25:43 +00001968
Yonathan Yusim3ae39ff2012-04-09 06:42:39 +08001969 /*
1970 * otherwise deal with the handshake. If there's any
1971 * packet traffic already arrived we'll trigger poll() again
1972 * right away and deal with it that way
1973 */
1974
Andy Greena41314f2011-05-23 10:00:03 +01001975 return lws_client_interpret_server_handshake(context, wsi);
Andy Greenbe93fef2011-02-14 20:25:43 +00001976
1977bail3:
1978 if (wsi->c_protocol)
1979 free(wsi->c_protocol);
Peter Hinz56885f32011-03-02 22:03:47 +00001980 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08001981 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenbe93fef2011-02-14 20:25:43 +00001982 return 1;
Andy Greena41314f2011-05-23 10:00:03 +01001983
1984 case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
Andy Green43db0452013-01-10 19:50:35 +08001985 lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
Andy Greena41314f2011-05-23 10:00:03 +01001986 break;
1987
1988 case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
Andy Green43db0452013-01-10 19:50:35 +08001989 lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
Andy Greena41314f2011-05-23 10:00:03 +01001990 break;
1991
Andy Greenbe93fef2011-02-14 20:25:43 +00001992
Andy Green0d338332011-02-12 11:57:43 +00001993 case LWS_CONNMODE_WS_SERVING:
1994 case LWS_CONNMODE_WS_CLIENT:
1995
1996 /* handle session socket closed */
1997
1998 if (pollfd->revents & (POLLERR | POLLHUP)) {
1999
Andy Green43db0452013-01-10 19:50:35 +08002000 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Andy Green0d338332011-02-12 11:57:43 +00002001 (void *)wsi, pollfd->fd);
2002
Peter Hinz56885f32011-03-02 22:03:47 +00002003 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002004 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green4b6fbe12011-02-14 08:03:48 +00002005 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002006 }
2007
Andy Green0d338332011-02-12 11:57:43 +00002008 /* the guy requested a callback when it was OK to write */
2009
Andy Greenda527df2011-03-07 07:08:12 +00002010 if ((pollfd->revents & POLLOUT) &&
2011 wsi->state == WSI_STATE_ESTABLISHED)
2012 if (lws_handle_POLLOUT_event(context, wsi,
2013 pollfd) < 0) {
2014 libwebsocket_close_and_free_session(
2015 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green3b84c002011-03-06 13:14:42 +00002016 return 1;
2017 }
Andy Green0d338332011-02-12 11:57:43 +00002018
Andy Green0d338332011-02-12 11:57:43 +00002019
2020 /* any incoming data ready? */
2021
2022 if (!(pollfd->revents & POLLIN))
2023 break;
2024
Andy Greenb45993c2010-12-18 15:13:50 +00002025#ifdef LWS_OPENSSL_SUPPORT
David Galeano7ffbe1b2013-01-10 10:35:32 +08002026read_pending:
Andy Green0d338332011-02-12 11:57:43 +00002027 if (wsi->ssl)
Andy Green98a717c2011-03-06 13:14:15 +00002028 eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);
Andy Greenb45993c2010-12-18 15:13:50 +00002029 else
2030#endif
Andy Green98a717c2011-03-06 13:14:15 +00002031 eff_buf.token_len =
Andy Green72c34322011-04-16 10:46:21 +01002032 recv(pollfd->fd, buf, sizeof buf, 0);
Andy Greenb45993c2010-12-18 15:13:50 +00002033
Andy Green98a717c2011-03-06 13:14:15 +00002034 if (eff_buf.token_len < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002035 lwsl_debug("Socket read returned %d\n",
Andy Green98a717c2011-03-06 13:14:15 +00002036 eff_buf.token_len);
Alon Levydc93b7f2012-10-19 11:21:57 +02002037 if (errno != EINTR && errno != EAGAIN)
Andy Green6ee372f2012-04-09 15:09:01 +08002038 libwebsocket_close_and_free_session(context,
2039 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Nick Dowellc04c1932012-04-05 10:29:39 +08002040 return 1;
Andy Greenb45993c2010-12-18 15:13:50 +00002041 }
Andy Green98a717c2011-03-06 13:14:15 +00002042 if (!eff_buf.token_len) {
Peter Hinz56885f32011-03-02 22:03:47 +00002043 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002044 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenfa3f4052012-10-07 20:40:35 +08002045 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00002046 }
2047
Andy Green98a717c2011-03-06 13:14:15 +00002048 /*
2049 * give any active extensions a chance to munge the buffer
2050 * before parse. We pass in a pointer to an lws_tokens struct
2051 * prepared with the default buffer and content length that's in
2052 * there. Rather than rewrite the default buffer, extensions
2053 * that expect to grow the buffer can adapt .token to
2054 * point to their own per-connection buffer in the extension
2055 * user allocation. By default with no extensions or no
2056 * extension callback handling, just the normal input buffer is
2057 * used then so it is efficient.
2058 */
Andy Greenb45993c2010-12-18 15:13:50 +00002059
Andy Green98a717c2011-03-06 13:14:15 +00002060 eff_buf.token = (char *)buf;
Andy Greenb45993c2010-12-18 15:13:50 +00002061
Andy Green98a717c2011-03-06 13:14:15 +00002062 more = 1;
2063 while (more) {
Andy Green0d338332011-02-12 11:57:43 +00002064
Andy Green98a717c2011-03-06 13:14:15 +00002065 more = 0;
2066
2067 for (n = 0; n < wsi->count_active_extensions; n++) {
Andy Green46c2ea02011-03-22 09:04:01 +00002068 m = wsi->active_extensions[n]->callback(context,
2069 wsi->active_extensions[n], wsi,
Andy Green98a717c2011-03-06 13:14:15 +00002070 LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
Andy Green46c2ea02011-03-22 09:04:01 +00002071 wsi->active_extensions_user[n],
2072 &eff_buf, 0);
Andy Green98a717c2011-03-06 13:14:15 +00002073 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002074 lwsl_ext(
Andy Green6ee372f2012-04-09 15:09:01 +08002075 "Extension reports fatal error\n");
2076 libwebsocket_close_and_free_session(
2077 context, wsi,
2078 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green98a717c2011-03-06 13:14:15 +00002079 return 1;
2080 }
2081 if (m)
2082 more = 1;
2083 }
2084
2085 /* service incoming data */
2086
2087 if (eff_buf.token_len) {
2088 n = libwebsocket_read(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002089 (unsigned char *)eff_buf.token,
2090 eff_buf.token_len);
Andy Green98a717c2011-03-06 13:14:15 +00002091 if (n < 0)
2092 /* we closed wsi */
2093 return 1;
2094 }
2095
2096 eff_buf.token = NULL;
2097 eff_buf.token_len = 0;
2098 }
David Galeano7ffbe1b2013-01-10 10:35:32 +08002099
2100#ifdef LWS_OPENSSL_SUPPORT
2101 if (wsi->ssl && SSL_pending(wsi->ssl))
2102 goto read_pending;
2103#endif
Andy Green98a717c2011-03-06 13:14:15 +00002104 break;
Andy Greenb45993c2010-12-18 15:13:50 +00002105 }
2106
2107 return 0;
2108}
2109
Andy Green0d338332011-02-12 11:57:43 +00002110
Andy Green6964bb52011-01-23 16:50:33 +00002111/**
2112 * libwebsocket_context_destroy() - Destroy the websocket context
Peter Hinz56885f32011-03-02 22:03:47 +00002113 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002114 *
2115 * This function closes any active connections and then frees the
2116 * context. After calling this, any further use of the context is
2117 * undefined.
2118 */
2119void
Peter Hinz56885f32011-03-02 22:03:47 +00002120libwebsocket_context_destroy(struct libwebsocket_context *context)
Andy Green6964bb52011-01-23 16:50:33 +00002121{
Andy Green0d338332011-02-12 11:57:43 +00002122 int n;
2123 int m;
2124 struct libwebsocket *wsi;
Andy Greena41314f2011-05-23 10:00:03 +01002125 struct libwebsocket_extension *ext;
Andy Green6964bb52011-01-23 16:50:33 +00002126
Andy Green4b6fbe12011-02-14 08:03:48 +00002127 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002128 for (m = 0; m < context->fd_hashtable[n].length; m++) {
2129 wsi = context->fd_hashtable[n].wsi[m];
2130 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +00002131 LWS_CLOSE_STATUS_GOINGAWAY);
Andy Greenf3d3b402011-02-09 07:16:34 +00002132 }
Andy Green6964bb52011-01-23 16:50:33 +00002133
Andy Greena41314f2011-05-23 10:00:03 +01002134 /*
2135 * give all extensions a chance to clean up any per-context
2136 * allocations they might have made
2137 */
2138
2139 ext = context->extensions;
2140 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
2141 if (context->listen_port)
2142 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
Paulo Roberto Urio1f680ab2012-06-04 08:40:28 +08002143 while (ext && ext->callback) {
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002144 ext->callback(context, ext, NULL, (enum libwebsocket_extension_callback_reasons)m, NULL, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +01002145 ext++;
2146 }
2147
Peter Hinz56885f32011-03-02 22:03:47 +00002148#ifdef WIN32
2149#else
2150 close(context->fd_random);
Andy Green6964bb52011-01-23 16:50:33 +00002151#endif
2152
Peter Hinz56885f32011-03-02 22:03:47 +00002153#ifdef LWS_OPENSSL_SUPPORT
2154 if (context->ssl_ctx)
2155 SSL_CTX_free(context->ssl_ctx);
2156 if (context->ssl_client_ctx)
2157 SSL_CTX_free(context->ssl_client_ctx);
2158#endif
2159
2160 free(context);
2161
2162#ifdef WIN32
2163 WSACleanup();
2164#endif
Andy Green6964bb52011-01-23 16:50:33 +00002165}
2166
Alon Levy0291eb32012-10-19 11:21:56 +02002167LWS_EXTERN void *
2168libwebsocket_context_user(struct libwebsocket_context *context)
2169{
2170 return context->user_space;
2171}
2172
Andy Green6964bb52011-01-23 16:50:33 +00002173/**
2174 * libwebsocket_service() - Service any pending websocket activity
Peter Hinz56885f32011-03-02 22:03:47 +00002175 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +00002176 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
2177 * service otherwise block and service immediately, returning
2178 * after the timeout if nothing needed service.
2179 *
2180 * This function deals with any pending websocket traffic, for three
2181 * kinds of event. It handles these events on both server and client
2182 * types of connection the same.
2183 *
2184 * 1) Accept new connections to our context's server
2185 *
2186 * 2) Perform pending broadcast writes initiated from other forked
2187 * processes (effectively serializing asynchronous broadcasts)
2188 *
2189 * 3) Call the receive callback for incoming frame data received by
2190 * server or client connections.
2191 *
2192 * You need to call this service function periodically to all the above
2193 * functions to happen; if your application is single-threaded you can
2194 * just call it in your main event loop.
2195 *
2196 * Alternatively you can fork a new process that asynchronously handles
2197 * calling this service in a loop. In that case you are happy if this
2198 * call blocks your thread until it needs to take care of something and
2199 * would call it with a large nonzero timeout. Your loop then takes no
2200 * CPU while there is nothing happening.
2201 *
2202 * If you are calling it in a single-threaded app, you don't want it to
2203 * wait around blocking other things in your loop from happening, so you
2204 * would call it with a timeout_ms of 0, so it returns immediately if
2205 * nothing is pending, or as soon as it services whatever was pending.
2206 */
2207
Andy Greenb45993c2010-12-18 15:13:50 +00002208
Andy Greene92cd172011-01-19 13:11:55 +00002209int
Peter Hinz56885f32011-03-02 22:03:47 +00002210libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
Andy Greene92cd172011-01-19 13:11:55 +00002211{
2212 int n;
Andy Greene92cd172011-01-19 13:11:55 +00002213
2214 /* stay dead once we are dead */
2215
Peter Hinz56885f32011-03-02 22:03:47 +00002216 if (context == NULL)
Andy Greene92cd172011-01-19 13:11:55 +00002217 return 1;
2218
Andy Green0d338332011-02-12 11:57:43 +00002219 /* wait for something to need service */
Andy Green4739e5c2011-01-22 12:51:57 +00002220
Peter Hinz56885f32011-03-02 22:03:47 +00002221 n = poll(context->fds, context->fds_count, timeout_ms);
Andy Green3221f922011-02-12 13:14:11 +00002222 if (n == 0) /* poll timeout */
2223 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002224
Andy Green62c54d22011-02-14 09:14:25 +00002225 if (n < 0) {
Andy Green5e1fa172011-02-10 09:07:05 +00002226 /*
Andy Green43db0452013-01-10 19:50:35 +08002227 lwsl_err("Listen Socket dead\n");
Andy Green5e1fa172011-02-10 09:07:05 +00002228 */
Andy Green3928f612012-07-20 12:58:38 +08002229 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002230 }
Andy Greene92cd172011-01-19 13:11:55 +00002231
2232 /* handle accept on listening socket? */
2233
Peter Hinz56885f32011-03-02 22:03:47 +00002234 for (n = 0; n < context->fds_count; n++)
2235 if (context->fds[n].revents)
Andy Green3928f612012-07-20 12:58:38 +08002236 if (libwebsocket_service_fd(context,
2237 &context->fds[n]) < 0)
2238 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00002239 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00002240}
2241
Andy Greena41314f2011-05-23 10:00:03 +01002242int
2243lws_any_extension_handled(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002244 struct libwebsocket *wsi,
2245 enum libwebsocket_extension_callback_reasons r,
Andy Greena41314f2011-05-23 10:00:03 +01002246 void *v, size_t len)
2247{
2248 int n;
2249 int handled = 0;
2250
2251 /* maybe an extension will take care of it for us */
2252
2253 for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
2254 if (!wsi->active_extensions[n]->callback)
2255 continue;
2256
2257 handled |= wsi->active_extensions[n]->callback(context,
2258 wsi->active_extensions[n], wsi,
2259 r, wsi->active_extensions_user[n], v, len);
2260 }
2261
2262 return handled;
2263}
2264
2265
2266void *
2267lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08002268 struct libwebsocket_extension *ext)
Andy Greena41314f2011-05-23 10:00:03 +01002269{
2270 int n = 0;
2271
Andy Green68b45042011-05-25 21:41:57 +01002272 if (wsi == NULL)
2273 return NULL;
2274
Andy Greena41314f2011-05-23 10:00:03 +01002275 while (n < wsi->count_active_extensions) {
2276 if (wsi->active_extensions[n] != ext) {
2277 n++;
2278 continue;
2279 }
2280 return wsi->active_extensions_user[n];
2281 }
2282
2283 return NULL;
2284}
2285
Andy Green90c7cbc2011-01-27 06:26:52 +00002286/**
2287 * libwebsocket_callback_on_writable() - Request a callback when this socket
2288 * becomes able to be written to without
2289 * blocking
Andy Green32375b72011-02-19 08:32:53 +00002290 *
Peter Hinz56885f32011-03-02 22:03:47 +00002291 * @context: libwebsockets context
Andy Green90c7cbc2011-01-27 06:26:52 +00002292 * @wsi: Websocket connection instance to get callback for
2293 */
2294
2295int
Peter Hinz56885f32011-03-02 22:03:47 +00002296libwebsocket_callback_on_writable(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08002297 struct libwebsocket *wsi)
Andy Green90c7cbc2011-01-27 06:26:52 +00002298{
Andy Green90c7cbc2011-01-27 06:26:52 +00002299 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002300 int handled = 0;
2301
2302 /* maybe an extension will take care of it for us */
2303
2304 for (n = 0; n < wsi->count_active_extensions; n++) {
2305 if (!wsi->active_extensions[n]->callback)
2306 continue;
2307
2308 handled |= wsi->active_extensions[n]->callback(context,
2309 wsi->active_extensions[n], wsi,
2310 LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
2311 wsi->active_extensions_user[n], NULL, 0);
2312 }
2313
2314 if (handled)
2315 return 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002316
Peter Hinz56885f32011-03-02 22:03:47 +00002317 for (n = 0; n < context->fds_count; n++)
2318 if (context->fds[n].fd == wsi->sock) {
2319 context->fds[n].events |= POLLOUT;
Andy Greena41314f2011-05-23 10:00:03 +01002320 n = context->fds_count + 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00002321 }
2322
Andy Greena41314f2011-05-23 10:00:03 +01002323 if (n == context->fds_count)
Andy Green43db0452013-01-10 19:50:35 +08002324 lwsl_err("libwebsocket_callback_on_writable: "
Andy Green6ee372f2012-04-09 15:09:01 +08002325 "failed to find socket %d\n", wsi->sock);
Andy Greena41314f2011-05-23 10:00:03 +01002326
Andy Green3221f922011-02-12 13:14:11 +00002327 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002328 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002329 LWS_CALLBACK_SET_MODE_POLL_FD,
2330 (void *)(long)wsi->sock, NULL, POLLOUT);
2331
Andy Green90c7cbc2011-01-27 06:26:52 +00002332 return 1;
2333}
2334
2335/**
2336 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
2337 * all connections using the given protocol when it
2338 * becomes possible to write to each socket without
2339 * blocking in turn.
2340 *
2341 * @protocol: Protocol whose connections will get callbacks
2342 */
2343
2344int
2345libwebsocket_callback_on_writable_all_protocol(
2346 const struct libwebsocket_protocols *protocol)
2347{
Peter Hinz56885f32011-03-02 22:03:47 +00002348 struct libwebsocket_context *context = protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002349 int n;
Andy Green0d338332011-02-12 11:57:43 +00002350 int m;
2351 struct libwebsocket *wsi;
Andy Green90c7cbc2011-01-27 06:26:52 +00002352
Andy Green0d338332011-02-12 11:57:43 +00002353 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
2354
Peter Hinz56885f32011-03-02 22:03:47 +00002355 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Green0d338332011-02-12 11:57:43 +00002356
Peter Hinz56885f32011-03-02 22:03:47 +00002357 wsi = context->fd_hashtable[n].wsi[m];
Andy Green0d338332011-02-12 11:57:43 +00002358
2359 if (wsi->protocol == protocol)
Peter Hinz56885f32011-03-02 22:03:47 +00002360 libwebsocket_callback_on_writable(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002361 }
2362 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002363
2364 return 0;
2365}
2366
Andy Greenbe93fef2011-02-14 20:25:43 +00002367/**
2368 * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
2369 *
2370 * You will not need this unless you are doing something special
2371 *
2372 * @wsi: Websocket connection instance
2373 * @reason: timeout reason
2374 * @secs: how many seconds
2375 */
2376
2377void
2378libwebsocket_set_timeout(struct libwebsocket *wsi,
2379 enum pending_timeout reason, int secs)
2380{
2381 struct timeval tv;
2382
2383 gettimeofday(&tv, NULL);
2384
2385 wsi->pending_timeout_limit = tv.tv_sec + secs;
2386 wsi->pending_timeout = reason;
2387}
2388
Andy Greena6cbece2011-01-27 20:06:03 +00002389
2390/**
2391 * libwebsocket_get_socket_fd() - returns the socket file descriptor
2392 *
2393 * You will not need this unless you are doing something special
2394 *
2395 * @wsi: Websocket connection instance
2396 */
2397
2398int
2399libwebsocket_get_socket_fd(struct libwebsocket *wsi)
2400{
2401 return wsi->sock;
2402}
2403
Andy Green90c7cbc2011-01-27 06:26:52 +00002404/**
2405 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
2406 * receieved packets.
2407 *
2408 * If the output side of a server process becomes choked, this allows flow
2409 * control for the input side.
2410 *
2411 * @wsi: Websocket connection instance to get callback for
2412 * @enable: 0 = disable read servicing for this connection, 1 = enable
2413 */
2414
2415int
2416libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
2417{
Peter Hinz56885f32011-03-02 22:03:47 +00002418 struct libwebsocket_context *context = wsi->protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00002419 int n;
2420
Peter Hinz56885f32011-03-02 22:03:47 +00002421 for (n = 0; n < context->fds_count; n++)
2422 if (context->fds[n].fd == wsi->sock) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002423 if (enable)
Peter Hinz56885f32011-03-02 22:03:47 +00002424 context->fds[n].events |= POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002425 else
Peter Hinz56885f32011-03-02 22:03:47 +00002426 context->fds[n].events &= ~POLLIN;
Andy Green90c7cbc2011-01-27 06:26:52 +00002427
2428 return 0;
2429 }
2430
Andy Green3221f922011-02-12 13:14:11 +00002431 if (enable)
2432 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002433 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002434 LWS_CALLBACK_SET_MODE_POLL_FD,
2435 (void *)(long)wsi->sock, NULL, POLLIN);
2436 else
2437 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002438 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002439 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
2440 (void *)(long)wsi->sock, NULL, POLLIN);
2441
Andy Greena41314f2011-05-23 10:00:03 +01002442#if 0
Andy Green43db0452013-01-10 19:50:35 +08002443 lwsl_err("libwebsocket_rx_flow_control unable to find socket\n");
Andy Greena41314f2011-05-23 10:00:03 +01002444#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002445 return 1;
2446}
2447
Andy Green2ac5a6f2011-01-28 10:00:18 +00002448/**
2449 * libwebsocket_canonical_hostname() - returns this host's hostname
2450 *
2451 * This is typically used by client code to fill in the host parameter
2452 * when making a client connection. You can only call it after the context
2453 * has been created.
2454 *
Peter Hinz56885f32011-03-02 22:03:47 +00002455 * @context: Websocket context
Andy Green2ac5a6f2011-01-28 10:00:18 +00002456 */
2457
2458
2459extern const char *
Peter Hinz56885f32011-03-02 22:03:47 +00002460libwebsocket_canonical_hostname(struct libwebsocket_context *context)
Andy Green2ac5a6f2011-01-28 10:00:18 +00002461{
Peter Hinz56885f32011-03-02 22:03:47 +00002462 return (const char *)context->canonical_hostname;
Andy Green2ac5a6f2011-01-28 10:00:18 +00002463}
2464
2465
Andy Green90c7cbc2011-01-27 06:26:52 +00002466static void sigpipe_handler(int x)
2467{
2468}
2469
Andy Green6901cb32011-02-21 08:06:47 +00002470#ifdef LWS_OPENSSL_SUPPORT
2471static int
2472OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
2473{
2474
2475 SSL *ssl;
2476 int n;
Andy Green2e24da02011-03-05 16:12:04 +00002477 struct libwebsocket_context *context;
Andy Green6901cb32011-02-21 08:06:47 +00002478
2479 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
2480 SSL_get_ex_data_X509_STORE_CTX_idx());
2481
2482 /*
Andy Green2e24da02011-03-05 16:12:04 +00002483 * !!! nasty openssl requires the index to come as a library-scope
2484 * static
Andy Green6901cb32011-02-21 08:06:47 +00002485 */
Andy Green2e24da02011-03-05 16:12:04 +00002486 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
Andy Green6ee372f2012-04-09 15:09:01 +08002487
Peter Hinz56885f32011-03-02 22:03:47 +00002488 n = context->protocols[0].callback(NULL, NULL,
Andy Green6901cb32011-02-21 08:06:47 +00002489 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
2490 x509_ctx, ssl, preverify_ok);
2491
2492 /* convert return code from 0 = OK to 1 = OK */
2493
2494 if (!n)
2495 n = 1;
2496 else
2497 n = 0;
2498
2499 return n;
2500}
2501#endif
2502
Andy Greenb45993c2010-12-18 15:13:50 +00002503
Andy Greenab990e42010-10-31 12:42:52 +00002504/**
Andy Green4739e5c2011-01-22 12:51:57 +00002505 * libwebsocket_create_context() - Create the websocket handler
2506 * @port: Port to listen on... you can use 0 to suppress listening on
Andy Green6964bb52011-01-23 16:50:33 +00002507 * any port, that's what you want if you are not running a
2508 * websocket server at all but just using it as a client
Peter Hinz56885f32011-03-02 22:03:47 +00002509 * @interf: NULL to bind the listen socket to all interfaces, or the
Andy Green32375b72011-02-19 08:32:53 +00002510 * interface name, eg, "eth2"
Andy Green4f3943a2010-11-12 10:44:16 +00002511 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +00002512 * specific callback for each one. The list is ended with an
2513 * entry that has a NULL callback pointer.
Andy Green6964bb52011-01-23 16:50:33 +00002514 * It's not const because we write the owning_server member
Andy Greenc5114822011-03-06 10:29:35 +00002515 * @extensions: NULL or array of libwebsocket_extension structs listing the
Andy Green6ee372f2012-04-09 15:09:01 +08002516 * extensions this context supports
Andy Green3faa9c72010-11-08 17:03:03 +00002517 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +00002518 * to listen using SSL, set to the filepath to fetch the
2519 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +00002520 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +00002521 * else ignored
David Galeano2f82be82013-01-09 16:25:54 +08002522 * @ssl_ca_filepath: CA certificate filepath or NULL
Andy Green3faa9c72010-11-08 17:03:03 +00002523 * @gid: group id to change to after setting listen socket, or -1.
2524 * @uid: user id to change to after setting listen socket, or -1.
Andy Greenbfb051f2011-02-09 08:49:14 +00002525 * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
Andy Green15e31f32012-10-19 18:36:28 +08002526 * @user: optional user pointer that can be recovered via the context
2527 * pointer using libwebsocket_context_user
Andy Green05464c62010-11-12 10:44:18 +00002528 *
Andy Green8f037e42010-12-19 22:13:26 +00002529 * This function creates the listening socket and takes care
2530 * of all initialization in one step.
2531 *
Andy Greene92cd172011-01-19 13:11:55 +00002532 * After initialization, it returns a struct libwebsocket_context * that
2533 * represents this server. After calling, user code needs to take care
2534 * of calling libwebsocket_service() with the context pointer to get the
2535 * server's sockets serviced. This can be done in the same process context
2536 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +00002537 *
Andy Green8f037e42010-12-19 22:13:26 +00002538 * The protocol callback functions are called for a handful of events
2539 * including http requests coming in, websocket connections becoming
2540 * established, and data arriving; it's also called periodically to allow
2541 * async transmission.
2542 *
2543 * HTTP requests are sent always to the FIRST protocol in @protocol, since
2544 * at that time websocket protocol has not been negotiated. Other
2545 * protocols after the first one never see any HTTP callack activity.
2546 *
2547 * The server created is a simple http server by default; part of the
2548 * websocket standard is upgrading this http connection to a websocket one.
2549 *
2550 * This allows the same server to provide files like scripts and favicon /
2551 * images or whatever over http and dynamic data over websockets all in
2552 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +00002553 */
Andy Green4ea60062010-10-30 12:15:07 +01002554
Andy Greene92cd172011-01-19 13:11:55 +00002555struct libwebsocket_context *
Peter Hinz56885f32011-03-02 22:03:47 +00002556libwebsocket_create_context(int port, const char *interf,
Andy Greenb45993c2010-12-18 15:13:50 +00002557 struct libwebsocket_protocols *protocols,
Andy Greend6e09112011-03-05 16:12:15 +00002558 struct libwebsocket_extension *extensions,
Andy Green8f037e42010-12-19 22:13:26 +00002559 const char *ssl_cert_filepath,
2560 const char *ssl_private_key_filepath,
David Galeano2f82be82013-01-09 16:25:54 +08002561 const char *ssl_ca_filepath,
Alon Levy0291eb32012-10-19 11:21:56 +02002562 int gid, int uid, unsigned int options,
David Galeano2f82be82013-01-09 16:25:54 +08002563 void *user)
Andy Greenff95d7a2010-10-28 22:36:01 +01002564{
2565 int n;
Andy Greena41314f2011-05-23 10:00:03 +01002566 int m;
Andy Green4739e5c2011-01-22 12:51:57 +00002567 int sockfd = 0;
Andy Green251f6fa2010-11-03 11:13:06 +00002568 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +01002569 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +00002570 int opt = 1;
Peter Hinz56885f32011-03-02 22:03:47 +00002571 struct libwebsocket_context *context = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002572 unsigned int slen;
Andy Green9659f372011-01-27 22:01:43 +00002573 char *p;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002574 char hostname[1024] = "";
Andy Greena69f0512012-05-03 12:32:38 +08002575// struct hostent *he;
Andy Green0d338332011-02-12 11:57:43 +00002576 struct libwebsocket *wsi;
Andy Greena69f0512012-05-03 12:32:38 +08002577 struct sockaddr sa;
Andy Greenff95d7a2010-10-28 22:36:01 +01002578
Andy Green3faa9c72010-11-08 17:03:03 +00002579#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +00002580 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +00002581 char ssl_err_buf[512];
Andy Green3faa9c72010-11-08 17:03:03 +00002582#endif
2583
Andy Green43db0452013-01-10 19:50:35 +08002584 lwsl_info("Initial logging level %d\n", log_level);
2585
Peter Hinz56885f32011-03-02 22:03:47 +00002586#ifdef _WIN32
2587 {
2588 WORD wVersionRequested;
2589 WSADATA wsaData;
2590 int err;
Andy Green6ee372f2012-04-09 15:09:01 +08002591 HMODULE wsdll;
Peter Hinz56885f32011-03-02 22:03:47 +00002592
2593 /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
2594 wVersionRequested = MAKEWORD(2, 2);
2595
2596 err = WSAStartup(wVersionRequested, &wsaData);
2597 if (err != 0) {
2598 /* Tell the user that we could not find a usable */
2599 /* Winsock DLL. */
Andy Green43db0452013-01-10 19:50:35 +08002600 lwsl_err("WSAStartup failed with error: %d\n", err);
Peter Hinz56885f32011-03-02 22:03:47 +00002601 return NULL;
2602 }
David Galeano7b11fec2011-10-04 19:55:18 +08002603
Andy Green6ee372f2012-04-09 15:09:01 +08002604 /* default to a poll() made out of select() */
2605 poll = emulated_poll;
David Galeano7b11fec2011-10-04 19:55:18 +08002606
Andy Green6ee372f2012-04-09 15:09:01 +08002607 /* if windows socket lib available, use his WSAPoll */
David Galeanocb193682013-01-09 15:29:00 +08002608 wsdll = GetModuleHandle(_T("Ws2_32.dll"));
Andy Green6ee372f2012-04-09 15:09:01 +08002609 if (wsdll)
2610 poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
Peter Hinz56885f32011-03-02 22:03:47 +00002611 }
2612#endif
2613
2614
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002615 context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context));
Peter Hinz56885f32011-03-02 22:03:47 +00002616 if (!context) {
Andy Green43db0452013-01-10 19:50:35 +08002617 lwsl_err("No memory for websocket context\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002618 return NULL;
2619 }
Peter Hinz56885f32011-03-02 22:03:47 +00002620 context->protocols = protocols;
2621 context->listen_port = port;
2622 context->http_proxy_port = 0;
2623 context->http_proxy_address[0] = '\0';
2624 context->options = options;
2625 context->fds_count = 0;
Andy Greend6e09112011-03-05 16:12:15 +00002626 context->extensions = extensions;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08002627 context->last_timeout_check_s = 0;
Alon Levy0291eb32012-10-19 11:21:56 +02002628 context->user_space = user;
Andy Green9659f372011-01-27 22:01:43 +00002629
Peter Hinz56885f32011-03-02 22:03:47 +00002630#ifdef WIN32
2631 context->fd_random = 0;
2632#else
2633 context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
2634 if (context->fd_random < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002635 lwsl_err("Unable to open random device %s %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002636 SYSTEM_RANDOM_FILEPATH, context->fd_random);
Andy Green44eee682011-02-10 09:32:24 +00002637 return NULL;
2638 }
Peter Hinz56885f32011-03-02 22:03:47 +00002639#endif
Andy Green44eee682011-02-10 09:32:24 +00002640
Peter Hinz56885f32011-03-02 22:03:47 +00002641#ifdef LWS_OPENSSL_SUPPORT
2642 context->use_ssl = 0;
2643 context->ssl_ctx = NULL;
2644 context->ssl_client_ctx = NULL;
Andy Green2e24da02011-03-05 16:12:04 +00002645 openssl_websocket_private_data_index = 0;
Peter Hinz56885f32011-03-02 22:03:47 +00002646#endif
Andy Green2ac5a6f2011-01-28 10:00:18 +00002647
Andy Green788c4a82012-10-22 12:29:57 +01002648 if (options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME) {
Andy Greena69f0512012-05-03 12:32:38 +08002649
Andy Green788c4a82012-10-22 12:29:57 +01002650 strcpy(context->canonical_hostname, "unknown");
Andy Greena69f0512012-05-03 12:32:38 +08002651
Andy Green788c4a82012-10-22 12:29:57 +01002652 } else {
2653
2654 /* find canonical hostname */
2655
2656 hostname[(sizeof hostname) - 1] = '\0';
2657 memset(&sa, 0, sizeof(sa));
2658 sa.sa_family = AF_INET;
2659 sa.sa_data[(sizeof sa.sa_data) - 1] = '\0';
2660 gethostname(hostname, (sizeof hostname) - 1);
2661
2662 n = 0;
2663
David Galeanoed3c8402013-01-10 10:45:24 +08002664 if (strlen(hostname) < sizeof(sa.sa_data) - 1) {
Andy Green788c4a82012-10-22 12:29:57 +01002665 strcpy(sa.sa_data, hostname);
Andy Green43db0452013-01-10 19:50:35 +08002666 // lwsl_debug("my host name is %s\n", sa.sa_data);
Andy Green788c4a82012-10-22 12:29:57 +01002667 n = getnameinfo(&sa, sizeof(sa), hostname,
2668 (sizeof hostname) - 1, NULL, 0, 0);
2669 }
2670
2671 if (!n) {
2672 strncpy(context->canonical_hostname, hostname,
2673 sizeof context->canonical_hostname - 1);
2674 context->canonical_hostname[
2675 sizeof context->canonical_hostname - 1] = '\0';
2676 } else
2677 strncpy(context->canonical_hostname, hostname,
2678 sizeof context->canonical_hostname - 1);
2679
Andy Green43db0452013-01-10 19:50:35 +08002680 // lwsl_debug("context->canonical_hostname = %s\n",
Andy Green788c4a82012-10-22 12:29:57 +01002681 // context->canonical_hostname);
Andy Greena69f0512012-05-03 12:32:38 +08002682 }
2683
Andy Green9659f372011-01-27 22:01:43 +00002684 /* split the proxy ads:port if given */
2685
2686 p = getenv("http_proxy");
2687 if (p) {
Peter Hinz56885f32011-03-02 22:03:47 +00002688 strncpy(context->http_proxy_address, p,
Andy Green6ee372f2012-04-09 15:09:01 +08002689 sizeof context->http_proxy_address - 1);
Peter Hinz56885f32011-03-02 22:03:47 +00002690 context->http_proxy_address[
2691 sizeof context->http_proxy_address - 1] = '\0';
Andy Green9659f372011-01-27 22:01:43 +00002692
Peter Hinz56885f32011-03-02 22:03:47 +00002693 p = strchr(context->http_proxy_address, ':');
Andy Green9659f372011-01-27 22:01:43 +00002694 if (p == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002695 lwsl_err("http_proxy needs to be ads:port\n");
Andy Green9659f372011-01-27 22:01:43 +00002696 return NULL;
2697 }
2698 *p = '\0';
Peter Hinz56885f32011-03-02 22:03:47 +00002699 context->http_proxy_port = atoi(p + 1);
Andy Green9659f372011-01-27 22:01:43 +00002700
Andy Green43db0452013-01-10 19:50:35 +08002701 lwsl_debug("Using proxy %s:%u\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002702 context->http_proxy_address,
2703 context->http_proxy_port);
Andy Green9659f372011-01-27 22:01:43 +00002704 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002705
2706 if (port) {
2707
Andy Green3faa9c72010-11-08 17:03:03 +00002708#ifdef LWS_OPENSSL_SUPPORT
Peter Hinz56885f32011-03-02 22:03:47 +00002709 context->use_ssl = ssl_cert_filepath != NULL &&
Andy Green90c7cbc2011-01-27 06:26:52 +00002710 ssl_private_key_filepath != NULL;
Peter Hinz56885f32011-03-02 22:03:47 +00002711 if (context->use_ssl)
Andy Green43db0452013-01-10 19:50:35 +08002712 lwsl_info(" Compiled with SSL support, using it\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00002713 else
Andy Green43db0452013-01-10 19:50:35 +08002714 lwsl_info(" Compiled with SSL support, not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +00002715
Andy Green90c7cbc2011-01-27 06:26:52 +00002716#else
2717 if (ssl_cert_filepath != NULL &&
2718 ssl_private_key_filepath != NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002719 lwsl_info(" Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +00002720 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002721 }
Andy Green43db0452013-01-10 19:50:35 +08002722 lwsl_info(" Compiled without SSL support, "
Andy Green90c7cbc2011-01-27 06:26:52 +00002723 "serving unencrypted\n");
2724#endif
2725 }
2726
2727 /* ignore SIGPIPE */
Peter Hinz56885f32011-03-02 22:03:47 +00002728#ifdef WIN32
2729#else
Andy Green90c7cbc2011-01-27 06:26:52 +00002730 signal(SIGPIPE, sigpipe_handler);
Peter Hinz56885f32011-03-02 22:03:47 +00002731#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00002732
2733
2734#ifdef LWS_OPENSSL_SUPPORT
2735
2736 /* basic openssl init */
2737
2738 SSL_library_init();
2739
2740 OpenSSL_add_all_algorithms();
2741 SSL_load_error_strings();
2742
Andy Green2e24da02011-03-05 16:12:04 +00002743 openssl_websocket_private_data_index =
Andy Green6901cb32011-02-21 08:06:47 +00002744 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
2745
Andy Green90c7cbc2011-01-27 06:26:52 +00002746 /*
2747 * Firefox insists on SSLv23 not SSLv3
2748 * Konq disables SSLv2 by default now, SSLv23 works
2749 */
2750
2751 method = (SSL_METHOD *)SSLv23_server_method();
2752 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002753 lwsl_err("problem creating ssl method: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002754 ERR_error_string(ERR_get_error(), ssl_err_buf));
2755 return NULL;
2756 }
Peter Hinz56885f32011-03-02 22:03:47 +00002757 context->ssl_ctx = SSL_CTX_new(method); /* create context */
2758 if (!context->ssl_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002759 lwsl_err("problem creating ssl context: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00002760 ERR_error_string(ERR_get_error(), ssl_err_buf));
2761 return NULL;
2762 }
2763
David Galeanocc148e42013-01-10 10:18:59 +08002764#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002765 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002766#endif
David Galeano77a677c2013-01-10 10:14:12 +08002767 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002768 SSL_CTX_set_cipher_list(context->ssl_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002769
Andy Green90c7cbc2011-01-27 06:26:52 +00002770 /* client context */
Andy Green6ee372f2012-04-09 15:09:01 +08002771
2772 if (port == CONTEXT_PORT_NO_LISTEN) {
Peter Hinz56885f32011-03-02 22:03:47 +00002773 method = (SSL_METHOD *)SSLv23_client_method();
2774 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08002775 lwsl_err("problem creating ssl method: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002776 ERR_error_string(ERR_get_error(), ssl_err_buf));
2777 return NULL;
2778 }
2779 /* create context */
2780 context->ssl_client_ctx = SSL_CTX_new(method);
2781 if (!context->ssl_client_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08002782 lwsl_err("problem creating ssl context: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00002783 ERR_error_string(ERR_get_error(), ssl_err_buf));
2784 return NULL;
2785 }
Andy Green90c7cbc2011-01-27 06:26:52 +00002786
David Galeanocc148e42013-01-10 10:18:59 +08002787#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08002788 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08002789#endif
David Galeano77a677c2013-01-10 10:14:12 +08002790 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08002791 SSL_CTX_set_cipher_list(context->ssl_client_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08002792
Peter Hinz56885f32011-03-02 22:03:47 +00002793 /* openssl init for cert verification (for client sockets) */
David Galeano2f82be82013-01-09 16:25:54 +08002794 if (!ssl_ca_filepath) {
2795 if (!SSL_CTX_load_verify_locations(
2796 context->ssl_client_ctx, NULL,
2797 LWS_OPENSSL_CLIENT_CERTS))
Andy Green43db0452013-01-10 19:50:35 +08002798 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002799 "Unable to load SSL Client certs from %s "
2800 "(set by --with-client-cert-dir= in configure) -- "
2801 " client ssl isn't going to work",
2802 LWS_OPENSSL_CLIENT_CERTS);
2803 } else
2804 if (!SSL_CTX_load_verify_locations(
2805 context->ssl_client_ctx, ssl_ca_filepath,
2806 NULL))
Andy Green43db0452013-01-10 19:50:35 +08002807 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08002808 "Unable to load SSL Client certs "
2809 "file from %s -- client ssl isn't "
2810 "going to work", ssl_ca_filepath);
Peter Hinz56885f32011-03-02 22:03:47 +00002811
2812 /*
2813 * callback allowing user code to load extra verification certs
2814 * helping the client to verify server identity
2815 */
2816
2817 context->protocols[0].callback(context, NULL,
2818 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
2819 context->ssl_client_ctx, NULL, 0);
Andy Green90c7cbc2011-01-27 06:26:52 +00002820 }
Andy Green6ee372f2012-04-09 15:09:01 +08002821
Andy Greenc6bf2c22011-02-20 11:10:47 +00002822 /* as a server, are we requiring clients to identify themselves? */
2823
2824 if (options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
2825
2826 /* absolutely require the client cert */
Andy Green6ee372f2012-04-09 15:09:01 +08002827
Peter Hinz56885f32011-03-02 22:03:47 +00002828 SSL_CTX_set_verify(context->ssl_ctx,
Andy Green6901cb32011-02-21 08:06:47 +00002829 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2830 OpenSSL_verify_callback);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002831
2832 /*
2833 * give user code a chance to load certs into the server
2834 * allowing it to verify incoming client certs
2835 */
2836
Peter Hinz56885f32011-03-02 22:03:47 +00002837 context->protocols[0].callback(context, NULL,
Andy Greenc6bf2c22011-02-20 11:10:47 +00002838 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
Peter Hinz56885f32011-03-02 22:03:47 +00002839 context->ssl_ctx, NULL, 0);
Andy Greenc6bf2c22011-02-20 11:10:47 +00002840 }
2841
Peter Hinz56885f32011-03-02 22:03:47 +00002842 if (context->use_ssl) {
Andy Green90c7cbc2011-01-27 06:26:52 +00002843
2844 /* openssl init for server sockets */
2845
Andy Green3faa9c72010-11-08 17:03:03 +00002846 /* set the local certificate from CertFile */
David Galeano9b3d4b22013-01-10 10:11:21 +08002847 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
2848 ssl_cert_filepath);
Andy Green3faa9c72010-11-08 17:03:03 +00002849 if (n != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002850 lwsl_err("problem getting cert '%s': %s\n",
Andy Green3faa9c72010-11-08 17:03:03 +00002851 ssl_cert_filepath,
2852 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002853 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002854 }
2855 /* set the private key from KeyFile */
Peter Hinz56885f32011-03-02 22:03:47 +00002856 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
2857 ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
Andy Green43db0452013-01-10 19:50:35 +08002858 lwsl_err("ssl problem getting key '%s': %s\n",
Andy Green018d8eb2010-11-08 21:04:23 +00002859 ssl_private_key_filepath,
2860 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00002861 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002862 }
2863 /* verify private key */
Peter Hinz56885f32011-03-02 22:03:47 +00002864 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
Andy Green43db0452013-01-10 19:50:35 +08002865 lwsl_err("Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +00002866 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00002867 }
2868
2869 /* SSL is happy and has a cert it's content with */
2870 }
2871#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002872
Andy Greendf736162011-01-18 15:39:02 +00002873 /* selftest */
2874
2875 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +00002876 return NULL;
Andy Greendf736162011-01-18 15:39:02 +00002877
Andy Green0d338332011-02-12 11:57:43 +00002878 /* fd hashtable init */
2879
2880 for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
Peter Hinz56885f32011-03-02 22:03:47 +00002881 context->fd_hashtable[n].length = 0;
Andy Green0d338332011-02-12 11:57:43 +00002882
Andy Greenb45993c2010-12-18 15:13:50 +00002883 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +00002884
Andy Green4739e5c2011-01-22 12:51:57 +00002885 if (port) {
Andy Green8f037e42010-12-19 22:13:26 +00002886
Andy Green4739e5c2011-01-22 12:51:57 +00002887 sockfd = socket(AF_INET, SOCK_STREAM, 0);
2888 if (sockfd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002889 lwsl_err("ERROR opening socket");
Andy Green4739e5c2011-01-22 12:51:57 +00002890 return NULL;
2891 }
Andy Green775c0dd2010-10-29 14:15:22 +01002892
Andy Green4739e5c2011-01-22 12:51:57 +00002893 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08002894 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
2895 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00002896
2897 /* Disable Nagle */
2898 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08002899 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
2900 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00002901
Andy Green4739e5c2011-01-22 12:51:57 +00002902 bzero((char *) &serv_addr, sizeof(serv_addr));
2903 serv_addr.sin_family = AF_INET;
Peter Hinz56885f32011-03-02 22:03:47 +00002904 if (interf == NULL)
Andy Green32375b72011-02-19 08:32:53 +00002905 serv_addr.sin_addr.s_addr = INADDR_ANY;
2906 else
Peter Hinz56885f32011-03-02 22:03:47 +00002907 interface_to_sa(interf, &serv_addr,
Andy Green32375b72011-02-19 08:32:53 +00002908 sizeof(serv_addr));
Andy Green4739e5c2011-01-22 12:51:57 +00002909 serv_addr.sin_port = htons(port);
2910
2911 n = bind(sockfd, (struct sockaddr *) &serv_addr,
2912 sizeof(serv_addr));
2913 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002914 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Green8f037e42010-12-19 22:13:26 +00002915 port, n, errno);
Andy Green4739e5c2011-01-22 12:51:57 +00002916 return NULL;
2917 }
Andy Green0d338332011-02-12 11:57:43 +00002918
Aaron Zinman4550f1d2013-01-10 12:35:18 +08002919 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
2920 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00002921 wsi->sock = sockfd;
Andy Greend6e09112011-03-05 16:12:15 +00002922 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00002923 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
Peter Hinz56885f32011-03-02 22:03:47 +00002924 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00002925
David Galeano36973092013-01-10 09:58:24 +08002926 listen(sockfd, SOMAXCONN);
Andy Green43db0452013-01-10 19:50:35 +08002927 lwsl_info(" Listening on port %d\n", port);
Andy Green0d338332011-02-12 11:57:43 +00002928
2929 /* list in the internal poll array */
Andy Green6ee372f2012-04-09 15:09:01 +08002930
Peter Hinz56885f32011-03-02 22:03:47 +00002931 context->fds[context->fds_count].fd = sockfd;
2932 context->fds[context->fds_count++].events = POLLIN;
Andy Green3221f922011-02-12 13:14:11 +00002933
2934 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00002935 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00002936 LWS_CALLBACK_ADD_POLL_FD,
2937 (void *)(long)sockfd, NULL, POLLIN);
2938
Andy Green8f037e42010-12-19 22:13:26 +00002939 }
Andy Greenb45993c2010-12-18 15:13:50 +00002940
Andy Green6ee372f2012-04-09 15:09:01 +08002941 /*
2942 * drop any root privs for this process
2943 * to listen on port < 1023 we would have needed root, but now we are
2944 * listening, we don't want the power for anything else
2945 */
Peter Hinz56885f32011-03-02 22:03:47 +00002946#ifdef WIN32
2947#else
Andy Green3faa9c72010-11-08 17:03:03 +00002948 if (gid != -1)
2949 if (setgid(gid))
Andy Green43db0452013-01-10 19:50:35 +08002950 lwsl_warn("setgid: %s\n", strerror(errno));
Andy Green3faa9c72010-11-08 17:03:03 +00002951 if (uid != -1)
2952 if (setuid(uid))
Andy Green43db0452013-01-10 19:50:35 +08002953 lwsl_warn("setuid: %s\n", strerror(errno));
Peter Hinz56885f32011-03-02 22:03:47 +00002954#endif
Andy Greenb45993c2010-12-18 15:13:50 +00002955
2956 /* set up our internal broadcast trigger sockets per-protocol */
2957
Peter Hinz56885f32011-03-02 22:03:47 +00002958 for (context->count_protocols = 0;
2959 protocols[context->count_protocols].callback;
2960 context->count_protocols++) {
Andy Green2d1301e2011-05-24 10:14:41 +01002961
Andy Green43db0452013-01-10 19:50:35 +08002962 lwsl_parser(" Protocol: %s\n",
2963 protocols[context->count_protocols].name);
Andy Green2d1301e2011-05-24 10:14:41 +01002964
Peter Hinz56885f32011-03-02 22:03:47 +00002965 protocols[context->count_protocols].owning_server = context;
2966 protocols[context->count_protocols].protocol_index =
2967 context->count_protocols;
Andy Greenb45993c2010-12-18 15:13:50 +00002968
2969 fd = socket(AF_INET, SOCK_STREAM, 0);
2970 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002971 lwsl_err("ERROR opening socket");
Andy Greene92cd172011-01-19 13:11:55 +00002972 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002973 }
Andy Green8f037e42010-12-19 22:13:26 +00002974
Andy Greenb45993c2010-12-18 15:13:50 +00002975 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08002976 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt,
2977 sizeof(opt));
Andy Greenb45993c2010-12-18 15:13:50 +00002978
2979 bzero((char *) &serv_addr, sizeof(serv_addr));
2980 serv_addr.sin_family = AF_INET;
2981 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
2982 serv_addr.sin_port = 0; /* pick the port for us */
2983
2984 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
2985 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002986 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Greenb45993c2010-12-18 15:13:50 +00002987 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +00002988 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002989 }
2990
2991 slen = sizeof cli_addr;
2992 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
2993 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08002994 lwsl_err("getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +00002995 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00002996 }
Peter Hinz56885f32011-03-02 22:03:47 +00002997 protocols[context->count_protocols].broadcast_socket_port =
Andy Greenb45993c2010-12-18 15:13:50 +00002998 ntohs(cli_addr.sin_port);
2999 listen(fd, 5);
3000
Andy Green43db0452013-01-10 19:50:35 +08003001 lwsl_debug(" Protocol %s broadcast socket %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00003002 protocols[context->count_protocols].name,
Andy Greenb45993c2010-12-18 15:13:50 +00003003 ntohs(cli_addr.sin_port));
3004
Andy Green0d338332011-02-12 11:57:43 +00003005 /* dummy wsi per broadcast proxy socket */
3006
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003007 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
3008 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00003009 wsi->sock = fd;
3010 wsi->mode = LWS_CONNMODE_BROADCAST_PROXY_LISTENER;
Andy Greend6e09112011-03-05 16:12:15 +00003011 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00003012 /* note which protocol we are proxying */
Peter Hinz56885f32011-03-02 22:03:47 +00003013 wsi->protocol_index_for_broadcast_proxy =
3014 context->count_protocols;
3015 insert_wsi(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00003016
3017 /* list in internal poll array */
3018
Peter Hinz56885f32011-03-02 22:03:47 +00003019 context->fds[context->fds_count].fd = fd;
3020 context->fds[context->fds_count].events = POLLIN;
3021 context->fds[context->fds_count].revents = 0;
3022 context->fds_count++;
Andy Green3221f922011-02-12 13:14:11 +00003023
3024 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00003025 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00003026 LWS_CALLBACK_ADD_POLL_FD,
3027 (void *)(long)fd, NULL, POLLIN);
Andy Greenb45993c2010-12-18 15:13:50 +00003028 }
3029
Andy Greena41314f2011-05-23 10:00:03 +01003030 /*
3031 * give all extensions a chance to create any per-context
3032 * allocations they need
3033 */
3034
3035 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
3036 if (port)
3037 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
Andrew Chambersd5512172012-05-20 08:17:09 +08003038
3039 if (extensions) {
3040 while (extensions->callback) {
Andy Green43db0452013-01-10 19:50:35 +08003041 lwsl_ext(" Extension: %s\n", extensions->name);
Aaron Zinman4550f1d2013-01-10 12:35:18 +08003042 extensions->callback(context, extensions, NULL,
3043 (enum libwebsocket_extension_callback_reasons)m,
3044 NULL, NULL, 0);
Andrew Chambersd5512172012-05-20 08:17:09 +08003045 extensions++;
3046 }
Andy Greena41314f2011-05-23 10:00:03 +01003047 }
3048
Peter Hinz56885f32011-03-02 22:03:47 +00003049 return context;
Andy Greene92cd172011-01-19 13:11:55 +00003050}
Andy Greenb45993c2010-12-18 15:13:50 +00003051
Andy Green4739e5c2011-01-22 12:51:57 +00003052
Andy Greened11a022011-01-20 10:23:50 +00003053#ifndef LWS_NO_FORK
3054
Andy Greene92cd172011-01-19 13:11:55 +00003055/**
3056 * libwebsockets_fork_service_loop() - Optional helper function forks off
3057 * a process for the websocket server loop.
Andy Green6964bb52011-01-23 16:50:33 +00003058 * You don't have to use this but if not, you
3059 * have to make sure you are calling
3060 * libwebsocket_service periodically to service
3061 * the websocket traffic
Peter Hinz56885f32011-03-02 22:03:47 +00003062 * @context: server context returned by creation function
Andy Greene92cd172011-01-19 13:11:55 +00003063 */
Andy Greenb45993c2010-12-18 15:13:50 +00003064
Andy Greene92cd172011-01-19 13:11:55 +00003065int
Peter Hinz56885f32011-03-02 22:03:47 +00003066libwebsockets_fork_service_loop(struct libwebsocket_context *context)
Andy Greene92cd172011-01-19 13:11:55 +00003067{
Andy Greene92cd172011-01-19 13:11:55 +00003068 int fd;
3069 struct sockaddr_in cli_addr;
3070 int n;
Andy Green3221f922011-02-12 13:14:11 +00003071 int p;
Andy Greenb45993c2010-12-18 15:13:50 +00003072
Andy Greened11a022011-01-20 10:23:50 +00003073 n = fork();
3074 if (n < 0)
3075 return n;
3076
3077 if (!n) {
3078
3079 /* main process context */
3080
Andy Green3221f922011-02-12 13:14:11 +00003081 /*
3082 * set up the proxy sockets to allow broadcast from
3083 * service process context
3084 */
3085
Peter Hinz56885f32011-03-02 22:03:47 +00003086 for (p = 0; p < context->count_protocols; p++) {
Andy Greened11a022011-01-20 10:23:50 +00003087 fd = socket(AF_INET, SOCK_STREAM, 0);
3088 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003089 lwsl_err("Unable to create socket\n");
Andy Greened11a022011-01-20 10:23:50 +00003090 return -1;
3091 }
3092 cli_addr.sin_family = AF_INET;
3093 cli_addr.sin_port = htons(
Peter Hinz56885f32011-03-02 22:03:47 +00003094 context->protocols[p].broadcast_socket_port);
Andy Greened11a022011-01-20 10:23:50 +00003095 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3096 n = connect(fd, (struct sockaddr *)&cli_addr,
3097 sizeof cli_addr);
3098 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08003099 lwsl_err("Unable to connect to "
Andy Greened11a022011-01-20 10:23:50 +00003100 "broadcast socket %d, %s\n",
Andy Green3221f922011-02-12 13:14:11 +00003101 n, strerror(errno));
Andy Greened11a022011-01-20 10:23:50 +00003102 return -1;
3103 }
3104
Peter Hinz56885f32011-03-02 22:03:47 +00003105 context->protocols[p].broadcast_socket_user_fd = fd;
Andy Greened11a022011-01-20 10:23:50 +00003106 }
3107
Andy Greene92cd172011-01-19 13:11:55 +00003108 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00003109 }
3110
Artem Baguinski91531662011-12-14 22:14:03 +01003111#ifdef HAVE_SYS_PRCTL_H
Andy Greenb45993c2010-12-18 15:13:50 +00003112 /* we want a SIGHUP when our parent goes down */
3113 prctl(PR_SET_PDEATHSIG, SIGHUP);
Artem Baguinski91531662011-12-14 22:14:03 +01003114#endif
Andy Greenb45993c2010-12-18 15:13:50 +00003115
3116 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +00003117
Artem Baguinski91531662011-12-14 22:14:03 +01003118 while (1) {
Peter Hinz56885f32011-03-02 22:03:47 +00003119 if (libwebsocket_service(context, 1000))
Andy Green3928f612012-07-20 12:58:38 +08003120 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003121//#ifndef HAVE_SYS_PRCTL_H
Artem Baguinski91531662011-12-14 22:14:03 +01003122/*
3123 * on systems without prctl() (i.e. anything but linux) we can notice that our
3124 * parent is dead if getppid() returns 1. FIXME apparently this is not true for
3125 * solaris, could remember ppid right after fork and wait for it to change.
3126 */
3127
3128 if (getppid() == 1)
3129 break;
Andy Green5e8967a2012-10-17 20:10:44 +08003130//#endif
Artem Baguinski91531662011-12-14 22:14:03 +01003131 }
3132
Andy Green8f037e42010-12-19 22:13:26 +00003133
Andy Green3928f612012-07-20 12:58:38 +08003134 return 1;
Andy Greenff95d7a2010-10-28 22:36:01 +01003135}
3136
Andy Greened11a022011-01-20 10:23:50 +00003137#endif
3138
Andy Greenb45993c2010-12-18 15:13:50 +00003139/**
3140 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +00003141 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +00003142 * @wsi: pointer to struct websocket you want to know the protocol of
3143 *
Andy Green8f037e42010-12-19 22:13:26 +00003144 *
3145 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +00003146 * the callback.
3147 */
Andy Greenab990e42010-10-31 12:42:52 +00003148
Andy Greenb45993c2010-12-18 15:13:50 +00003149const struct libwebsocket_protocols *
3150libwebsockets_get_protocol(struct libwebsocket *wsi)
3151{
3152 return wsi->protocol;
3153}
3154
3155/**
Andy Greene92cd172011-01-19 13:11:55 +00003156 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +00003157 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +00003158 * @protocol: pointer to the protocol you will broadcast to all members of
3159 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +00003160 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
3161 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
3162 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +00003163 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +00003164 *
3165 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +00003166 * the given protocol. It does not send the data directly; instead it calls
3167 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
3168 * wants to actually send the data for that connection, the callback itself
3169 * should call libwebsocket_write().
3170 *
3171 * libwebsockets_broadcast() can be called from another fork context without
3172 * having to take any care about data visibility between the processes, it'll
3173 * "just work".
3174 */
3175
3176
3177int
Andy Green8f037e42010-12-19 22:13:26 +00003178libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +00003179 unsigned char *buf, size_t len)
3180{
Peter Hinz56885f32011-03-02 22:03:47 +00003181 struct libwebsocket_context *context = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +00003182 int n;
Andy Green0d338332011-02-12 11:57:43 +00003183 int m;
Andy Green6ee372f2012-04-09 15:09:01 +08003184 struct libwebsocket *wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00003185
3186 if (!protocol->broadcast_socket_user_fd) {
3187 /*
Andy Greene92cd172011-01-19 13:11:55 +00003188 * We are either running unforked / flat, or we are being
3189 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +00003190 * eg, from a callback. In that case don't use sockets for
3191 * broadcast IPC (since we can't open a socket connection to
3192 * a socket listening on our own thread) but directly do the
3193 * send action.
3194 *
3195 * Locking is not needed because we are by definition being
3196 * called in the poll thread context and are serialized.
3197 */
3198
Andy Green0d338332011-02-12 11:57:43 +00003199 for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003200
Peter Hinz56885f32011-03-02 22:03:47 +00003201 for (m = 0; m < context->fd_hashtable[n].length; m++) {
Andy Greenb45993c2010-12-18 15:13:50 +00003202
Peter Hinz56885f32011-03-02 22:03:47 +00003203 wsi = context->fd_hashtable[n].wsi[m];
Andy Greenb45993c2010-12-18 15:13:50 +00003204
Andy Green0d338332011-02-12 11:57:43 +00003205 if (wsi->mode != LWS_CONNMODE_WS_SERVING)
3206 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00003207
Andy Green0d338332011-02-12 11:57:43 +00003208 /*
3209 * never broadcast to
3210 * non-established connections
3211 */
3212 if (wsi->state != WSI_STATE_ESTABLISHED)
3213 continue;
3214
3215 /* only broadcast to guys using
3216 * requested protocol
3217 */
3218 if (wsi->protocol != protocol)
3219 continue;
3220
Peter Hinz56885f32011-03-02 22:03:47 +00003221 wsi->protocol->callback(context, wsi,
Andy Green8f037e42010-12-19 22:13:26 +00003222 LWS_CALLBACK_BROADCAST,
Andy Green0d338332011-02-12 11:57:43 +00003223 wsi->user_space,
Andy Greenb45993c2010-12-18 15:13:50 +00003224 buf, len);
Andy Green0d338332011-02-12 11:57:43 +00003225 }
Andy Greenb45993c2010-12-18 15:13:50 +00003226 }
3227
3228 return 0;
3229 }
3230
Andy Green0ca6a172010-12-19 20:50:01 +00003231 /*
3232 * We're being called from a different process context than the server
3233 * loop. Instead of broadcasting directly, we send our
3234 * payload on a socket to do the IPC; the server process will serialize
3235 * the broadcast action in its main poll() loop.
3236 *
3237 * There's one broadcast socket listening for each protocol supported
3238 * set up when the websocket server initializes
3239 */
3240
Andy Green6964bb52011-01-23 16:50:33 +00003241 n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
Andy Greenb45993c2010-12-18 15:13:50 +00003242
3243 return n;
3244}
Andy Green82c3d542011-03-07 21:16:31 +00003245
3246int
3247libwebsocket_is_final_fragment(struct libwebsocket *wsi)
3248{
3249 return wsi->final;
3250}
Alex Bligh49146db2011-11-07 17:19:25 +08003251
David Galeanoe2cf9922013-01-09 18:06:55 +08003252unsigned char
3253libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
3254{
3255 return wsi->rsv;
3256}
3257
Alex Bligh49146db2011-11-07 17:19:25 +08003258void *
3259libwebsocket_ensure_user_space(struct libwebsocket *wsi)
3260{
3261 /* allocate the per-connection user memory (if any) */
3262
3263 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
3264 wsi->user_space = malloc(
3265 wsi->protocol->per_session_data_size);
3266 if (wsi->user_space == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08003267 lwsl_err("Out of memory for conn user space\n");
Alex Bligh49146db2011-11-07 17:19:25 +08003268 return NULL;
3269 }
Andy Green6ee372f2012-04-09 15:09:01 +08003270 memset(wsi->user_space, 0,
3271 wsi->protocol->per_session_data_size);
Alex Bligh49146db2011-11-07 17:19:25 +08003272 }
3273 return wsi->user_space;
3274}
Andy Green43db0452013-01-10 19:50:35 +08003275
3276void _lws_log(int filter, const char *format, ...)
3277{
3278 va_list ap;
3279 int n;
3280
3281 if (!(log_level & filter))
3282 return;
3283
3284 for (n = 0; n < LLL_COUNT; n++)
3285 if (filter == (1 << n)) {
3286 fprintf(stderr, "%s: ", log_level_names[n]);
3287 break;
3288 }
3289
3290 va_start(ap, format);
3291 vfprintf(stderr, format, ap);
3292 va_end(ap);
3293}
3294
3295/**
3296 * lws_set_log_level() - Set the logging bitfield
3297 * @level: OR together the LLL_ debug contexts you want output from
3298 *
3299 *
3300 * defaults to err and warn contexts enabled
3301 */
3302
3303void lws_set_log_level(int level)
3304{
3305 log_level = level;
3306}
3307