blob: 6113f9b050de43b1088b1ff2e735cfb5431db2cc [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 Greenc11db202013-01-19 11:12:16 +080023#include <syslog.h>
Andy Greenff95d7a2010-10-28 22:36:01 +010024
Peter Hinz56885f32011-03-02 22:03:47 +000025#ifdef WIN32
David Galeanocb193682013-01-09 15:29:00 +080026#include <tchar.h>
27#include <io.h>
Peter Hinz56885f32011-03-02 22:03:47 +000028#else
Davidc4ef7b12013-01-12 20:39:47 +080029#ifdef LWS_BUILTIN_GETIFADDRS
30#include <getifaddrs.h>
31#else
Peter Hinz56885f32011-03-02 22:03:47 +000032#include <ifaddrs.h>
Davidc4ef7b12013-01-12 20:39:47 +080033#endif
Andy Green7627af52011-03-09 15:13:52 +000034#include <sys/un.h>
Andy Greena69f0512012-05-03 12:32:38 +080035#include <sys/socket.h>
36#include <netdb.h>
Peter Hinz56885f32011-03-02 22:03:47 +000037#endif
Andy Green2e24da02011-03-05 16:12:04 +000038
39#ifdef LWS_OPENSSL_SUPPORT
40int openssl_websocket_private_data_index;
41#endif
42
Andy Greenaa6fc442012-04-12 13:26:49 +080043#ifdef __MINGW32__
44#include "../win32port/win32helpers/websock-w32.c"
45#else
46#ifdef __MINGW64__
47#include "../win32port/win32helpers/websock-w32.c"
48#endif
49#endif
50
Andy Green7c19c342013-01-19 12:18:07 +080051static int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
Andy Greende8f27a2013-01-12 09:17:42 +080052static void lwsl_emit_stderr(const char *line);
53static void (*lwsl_emit)(const char *line) = lwsl_emit_stderr;
Andy Green43db0452013-01-10 19:50:35 +080054static const char *log_level_names[] = {
55 "ERR",
56 "WARN",
Andy Green7c19c342013-01-19 12:18:07 +080057 "NOTICE",
Andy Green43db0452013-01-10 19:50:35 +080058 "INFO",
59 "DEBUG",
60 "PARSER",
61 "HEADER",
62 "EXTENSION",
63 "CLIENT",
64};
65
Andy Green0d338332011-02-12 11:57:43 +000066int
Andy Greendfb23042013-01-17 12:26:48 +080067insert_wsi_socket_into_fds(struct libwebsocket_context *context, struct libwebsocket *wsi)
Andy Green0d338332011-02-12 11:57:43 +000068{
Andy Greendfb23042013-01-17 12:26:48 +080069 if (context->fds_count >= context->max_fds) {
70 lwsl_err("Reached limit of fds tracking (%d)\n", context->max_fds);
Andy Green0d338332011-02-12 11:57:43 +000071 return 1;
72 }
73
Andy Greendfb23042013-01-17 12:26:48 +080074 if (wsi->sock > context->max_fds) {
75 lwsl_err("Socket fd %d is beyond what we can index (%d)\n", wsi->sock, context->max_fds);
76 return 1;
77 }
78
79 assert(wsi);
80 assert(wsi->sock);
81
82 lwsl_info("insert_wsi_socket_into_fds: wsi=%p, sock=%d, fds pos=%d\n", wsi, wsi->sock, context->fds_count);
83
84 context->lws_lookup[wsi->sock] = wsi;
85 wsi->position_in_fds_table = context->fds_count;
86 context->fds[context->fds_count].fd = wsi->sock;
87 context->fds[context->fds_count].events = POLLIN;
88 context->fds[context->fds_count++].revents = 0;
89
90 /* external POLL support via protocol 0 */
91 context->protocols[0].callback(context, wsi,
92 LWS_CALLBACK_ADD_POLL_FD,
93 (void *)(long)wsi->sock, NULL, POLLIN);
Andy Green0d338332011-02-12 11:57:43 +000094
95 return 0;
96}
97
Andy Greendfb23042013-01-17 12:26:48 +080098static int
99remove_wsi_socket_from_fds(struct libwebsocket_context *context, struct libwebsocket *wsi)
Andy Green0d338332011-02-12 11:57:43 +0000100{
Andy Greendfb23042013-01-17 12:26:48 +0800101 int m;
Andy Green0d338332011-02-12 11:57:43 +0000102
Andy Greendfb23042013-01-17 12:26:48 +0800103 if (!--context->fds_count)
104 goto do_ext;
Andy Green0d338332011-02-12 11:57:43 +0000105
Andy Greendfb23042013-01-17 12:26:48 +0800106 if (wsi->sock > context->max_fds) {
107 lwsl_err("Socket fd %d is beyond what we can index (%d)\n", wsi->sock, context->max_fds);
108 return 1;
109 }
Andy Green0d338332011-02-12 11:57:43 +0000110
Andy Greendfb23042013-01-17 12:26:48 +0800111 lwsl_info("remove_wsi_socket_from_fds: wsi=%p, sock=%d, fds pos=%d\n", wsi, wsi->sock, wsi->position_in_fds_table);
112
113 m = wsi->position_in_fds_table; /* replace the contents for this */
114
115 /* have the last guy take up the vacant slot */
116 context->fds[m] = context->fds[context->fds_count]; /* vacant fds slot filled with end one */
117 /* end guy's fds_lookup entry remains unchanged (still same fd pointing to same wsi) */
118 /* end guy's "position in fds table" changed */
119 context->lws_lookup[context->fds[context->fds_count].fd]->position_in_fds_table = m;
120 /* deletion guy's lws_lookup entry needs nuking */
121 context->lws_lookup[wsi->sock] = NULL; /* no WSI for the socket of the wsi being removed*/
122 wsi->position_in_fds_table = -1; /* removed wsi has no position any more */
123
124do_ext:
125 /* remove also from external POLL support via protocol 0 */
126 if (wsi->sock)
127 context->protocols[0].callback(context, wsi,
128 LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
129
130 return 0;
Andy Green0d338332011-02-12 11:57:43 +0000131}
132
Andy Green32375b72011-02-19 08:32:53 +0000133
Andy Green8f037e42010-12-19 22:13:26 +0000134void
Peter Hinz56885f32011-03-02 22:03:47 +0000135libwebsocket_close_and_free_session(struct libwebsocket_context *context,
Andy Green687b0182011-02-26 11:04:01 +0000136 struct libwebsocket *wsi, enum lws_close_status reason)
Andy Green251f6fa2010-11-03 11:13:06 +0000137{
Andy Greenb45993c2010-12-18 15:13:50 +0000138 int n;
Andy Green62c54d22011-02-14 09:14:25 +0000139 int old_state;
Andy Green5e1fa172011-02-10 09:07:05 +0000140 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
141 LWS_SEND_BUFFER_POST_PADDING];
Andy Greenc44159f2011-03-07 07:08:18 +0000142 int ret;
143 int m;
144 struct lws_tokens eff_buf;
Andy Greena41314f2011-05-23 10:00:03 +0100145 struct libwebsocket_extension *ext;
Andy Greenb45993c2010-12-18 15:13:50 +0000146
Andy Green4b6fbe12011-02-14 08:03:48 +0000147 if (!wsi)
Andy Greenb45993c2010-12-18 15:13:50 +0000148 return;
149
Andy Green62c54d22011-02-14 09:14:25 +0000150 old_state = wsi->state;
Andy Green251f6fa2010-11-03 11:13:06 +0000151
Andy Green62c54d22011-02-14 09:14:25 +0000152 if (old_state == WSI_STATE_DEAD_SOCKET)
Andy Green5e1fa172011-02-10 09:07:05 +0000153 return;
154
Andy Greenda527df2011-03-07 07:08:12 +0000155 wsi->close_reason = reason;
156
157 /*
Andy Green68b45042011-05-25 21:41:57 +0100158 * are his extensions okay with him closing? Eg he might be a mux
159 * parent and just his ch1 aspect is closing?
160 */
161
162
163 for (n = 0; n < wsi->count_active_extensions; n++) {
164 if (!wsi->active_extensions[n]->callback)
165 continue;
166
167 m = wsi->active_extensions[n]->callback(context,
168 wsi->active_extensions[n], wsi,
169 LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
170 wsi->active_extensions_user[n], NULL, 0);
171
172 /*
173 * if somebody vetoed actually closing him at this time....
174 * up to the extension to track the attempted close, let's
175 * just bail
176 */
177
178 if (m) {
Andy Green43db0452013-01-10 19:50:35 +0800179 lwsl_ext("extension vetoed close\n");
Andy Green68b45042011-05-25 21:41:57 +0100180 return;
181 }
182 }
183
184
185
186 /*
Andy Greenc44159f2011-03-07 07:08:18 +0000187 * flush any tx pending from extensions, since we may send close packet
188 * if there are problems with send, just nuke the connection
189 */
190
191 ret = 1;
192 while (ret == 1) {
193
194 /* default to nobody has more to spill */
195
196 ret = 0;
197 eff_buf.token = NULL;
198 eff_buf.token_len = 0;
199
200 /* show every extension the new incoming data */
201
202 for (n = 0; n < wsi->count_active_extensions; n++) {
203 m = wsi->active_extensions[n]->callback(
Andy Green46c2ea02011-03-22 09:04:01 +0000204 wsi->protocol->owning_server,
205 wsi->active_extensions[n], wsi,
Andy Greenc44159f2011-03-07 07:08:18 +0000206 LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
207 wsi->active_extensions_user[n], &eff_buf, 0);
208 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +0800209 lwsl_ext("Extension reports fatal error\n");
Andy Greenc44159f2011-03-07 07:08:18 +0000210 goto just_kill_connection;
211 }
212 if (m)
213 /*
214 * at least one extension told us he has more
215 * to spill, so we will go around again after
216 */
217 ret = 1;
218 }
219
220 /* assuming they left us something to send, send it */
221
222 if (eff_buf.token_len)
223 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
Andy Green0303db42013-01-17 14:46:43 +0800224 eff_buf.token_len)) {
225 lwsl_debug("close: sending final extension spill had problems\n");
Andy Greenc44159f2011-03-07 07:08:18 +0000226 goto just_kill_connection;
Andy Green0303db42013-01-17 14:46:43 +0800227 }
Andy Greenc44159f2011-03-07 07:08:18 +0000228 }
229
230 /*
Andy Greenda527df2011-03-07 07:08:12 +0000231 * signal we are closing, libsocket_write will
232 * add any necessary version-specific stuff. If the write fails,
233 * no worries we are closing anyway. If we didn't initiate this
234 * close, then our state has been changed to
235 * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
236 *
237 * Likewise if it's a second call to close this connection after we
238 * sent the close indication to the peer already, we are in state
239 * WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
240 */
241
242 if (old_state == WSI_STATE_ESTABLISHED &&
243 reason != LWS_CLOSE_STATUS_NOSTATUS) {
Andy Green66a16f32011-05-24 22:07:45 +0100244
Andy Green43db0452013-01-10 19:50:35 +0800245 lwsl_debug("sending close indication...\n");
Andy Green66a16f32011-05-24 22:07:45 +0100246
Andy Greenda527df2011-03-07 07:08:12 +0000247 n = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING],
248 0, LWS_WRITE_CLOSE);
249 if (!n) {
250 /*
251 * we have sent a nice protocol level indication we
252 * now wish to close, we should not send anything more
253 */
254
255 wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
256
Andy Green0303db42013-01-17 14:46:43 +0800257 /* and we should wait for a reply for a bit out of politeness */
Andy Greenda527df2011-03-07 07:08:12 +0000258
259 libwebsocket_set_timeout(wsi,
Andy Green0303db42013-01-17 14:46:43 +0800260 PENDING_TIMEOUT_CLOSE_ACK, 1);
Andy Greenda527df2011-03-07 07:08:12 +0000261
Andy Green43db0452013-01-10 19:50:35 +0800262 lwsl_debug("sent close indication, awaiting ack\n");
Andy Greenda527df2011-03-07 07:08:12 +0000263
264 return;
265 }
266
Andy Green0303db42013-01-17 14:46:43 +0800267 lwsl_info("close: sending the close packet failed, hanging up\n");
268
Andy Greenda527df2011-03-07 07:08:12 +0000269 /* else, the send failed and we should just hang up */
270 }
271
Andy Greenc44159f2011-03-07 07:08:18 +0000272just_kill_connection:
Andy Green66a16f32011-05-24 22:07:45 +0100273
Andy Green43db0452013-01-10 19:50:35 +0800274 lwsl_debug("libwebsocket_close_and_free_session: just_kill_connection\n");
Andy Green66a16f32011-05-24 22:07:45 +0100275
Andy Greenda527df2011-03-07 07:08:12 +0000276 /*
277 * we won't be servicing or receiving anything further from this guy
Andy Greendfb23042013-01-17 12:26:48 +0800278 * delete socket from the internal poll list if still present
Andy Greenda527df2011-03-07 07:08:12 +0000279 */
Andy Green4b6fbe12011-02-14 08:03:48 +0000280
Andy Greendfb23042013-01-17 12:26:48 +0800281 remove_wsi_socket_from_fds(context, wsi);
Andy Green4b6fbe12011-02-14 08:03:48 +0000282
Andy Green251f6fa2010-11-03 11:13:06 +0000283 wsi->state = WSI_STATE_DEAD_SOCKET;
284
Andy Green4b6fbe12011-02-14 08:03:48 +0000285 /* tell the user it's all over for this guy */
286
Andy Greend4302732011-02-28 07:45:29 +0000287 if (wsi->protocol && wsi->protocol->callback &&
Andy Green6ee372f2012-04-09 15:09:01 +0800288 ((old_state == WSI_STATE_ESTABLISHED) ||
289 (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
290 (old_state == WSI_STATE_AWAITING_CLOSE_ACK))) {
Andy Green43db0452013-01-10 19:50:35 +0800291 lwsl_debug("calling back CLOSED\n");
Peter Hinz56885f32011-03-02 22:03:47 +0000292 wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
Andy Greene77ddd82010-11-13 10:03:47 +0000293 wsi->user_space, NULL, 0);
Andy Greencc012472011-11-07 19:53:23 +0800294 } else
Andy Green43db0452013-01-10 19:50:35 +0800295 lwsl_debug("not calling back closed, old_state=%d\n", old_state);
Andy Green251f6fa2010-11-03 11:13:06 +0000296
Andy Greenef660a92011-03-06 10:29:38 +0000297 /* deallocate any active extension contexts */
298
299 for (n = 0; n < wsi->count_active_extensions; n++) {
300 if (!wsi->active_extensions[n]->callback)
301 continue;
302
Andy Green46c2ea02011-03-22 09:04:01 +0000303 wsi->active_extensions[n]->callback(context,
304 wsi->active_extensions[n], wsi,
305 LWS_EXT_CALLBACK_DESTROY,
306 wsi->active_extensions_user[n], NULL, 0);
Andy Greenef660a92011-03-06 10:29:38 +0000307
308 free(wsi->active_extensions_user[n]);
309 }
310
Andy Greena41314f2011-05-23 10:00:03 +0100311 /*
312 * inform all extensions in case they tracked this guy out of band
313 * even though not active on him specifically
314 */
315
316 ext = context->extensions;
317 while (ext && ext->callback) {
318 ext->callback(context, ext, wsi,
319 LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
320 NULL, NULL, 0);
321 ext++;
322 }
323
Andy Greenef660a92011-03-06 10:29:38 +0000324 /* free up his parsing allocations */
Andy Green4b6fbe12011-02-14 08:03:48 +0000325
Andy Green251f6fa2010-11-03 11:13:06 +0000326 for (n = 0; n < WSI_TOKEN_COUNT; n++)
327 if (wsi->utf8_token[n].token)
328 free(wsi->utf8_token[n].token);
Andy Greena1ce6be2013-01-18 11:43:21 +0800329#ifndef LWS_NO_CLIENT
Andy Greena41314f2011-05-23 10:00:03 +0100330 if (wsi->c_address)
331 free(wsi->c_address);
Andy Greena1ce6be2013-01-18 11:43:21 +0800332#endif
Andy Green706961d2013-01-17 16:50:35 +0800333 if (wsi->rxflow_buffer)
334 free(wsi->rxflow_buffer);
335
Andy Green43db0452013-01-10 19:50:35 +0800336/* lwsl_info("closing fd=%d\n", wsi->sock); */
Andy Green251f6fa2010-11-03 11:13:06 +0000337
Andy Green3faa9c72010-11-08 17:03:03 +0000338#ifdef LWS_OPENSSL_SUPPORT
Andy Green90c7cbc2011-01-27 06:26:52 +0000339 if (wsi->ssl) {
Andy Green3faa9c72010-11-08 17:03:03 +0000340 n = SSL_get_fd(wsi->ssl);
341 SSL_shutdown(wsi->ssl);
Andy Green3fc2c652013-01-14 15:35:02 +0800342 compatible_close(n);
Andy Green3faa9c72010-11-08 17:03:03 +0000343 SSL_free(wsi->ssl);
344 } else {
345#endif
Andy Green0303db42013-01-17 14:46:43 +0800346 if (wsi->sock) {
347 n = shutdown(wsi->sock, SHUT_RDWR);
348 if (n)
349 lwsl_debug("closing: shutdown returned %d\n", errno);
Andy Green3fc2c652013-01-14 15:35:02 +0800350
Andy Green0303db42013-01-17 14:46:43 +0800351 n = compatible_close(wsi->sock);
352 if (n)
353 lwsl_debug("closing: close returned %d\n", errno);
354 }
Andy Green3faa9c72010-11-08 17:03:03 +0000355#ifdef LWS_OPENSSL_SUPPORT
356 }
357#endif
David Brooks2c60d952012-04-20 12:19:01 +0800358 if (wsi->protocol && wsi->protocol->per_session_data_size && wsi->user_space) /* user code may own */
Andy Green4f3943a2010-11-12 10:44:16 +0000359 free(wsi->user_space);
360
Andy Green251f6fa2010-11-03 11:13:06 +0000361 free(wsi);
362}
363
Andy Green07034092011-02-13 08:37:12 +0000364/**
Andy Greenf7ee5492011-02-13 09:04:21 +0000365 * libwebsockets_hangup_on_client() - Server calls to terminate client
Andy Green6ee372f2012-04-09 15:09:01 +0800366 * connection
Peter Hinz56885f32011-03-02 22:03:47 +0000367 * @context: libwebsockets context
Andy Greenf7ee5492011-02-13 09:04:21 +0000368 * @fd: Connection socket descriptor
369 */
370
371void
Peter Hinz56885f32011-03-02 22:03:47 +0000372libwebsockets_hangup_on_client(struct libwebsocket_context *context, int fd)
Andy Greenf7ee5492011-02-13 09:04:21 +0000373{
Andy Greendfb23042013-01-17 12:26:48 +0800374 struct libwebsocket *wsi = context->lws_lookup[fd];
Andy Greenf7ee5492011-02-13 09:04:21 +0000375
Andy Greendfb23042013-01-17 12:26:48 +0800376 if (wsi) {
377 libwebsocket_close_and_free_session(context,
378 wsi, LWS_CLOSE_STATUS_NOSTATUS);
379 } else
380 close(fd);
Andy Greenf7ee5492011-02-13 09:04:21 +0000381}
382
383
384/**
Andy Green07034092011-02-13 08:37:12 +0000385 * libwebsockets_get_peer_addresses() - Get client address information
386 * @fd: Connection socket descriptor
387 * @name: Buffer to take client address name
388 * @name_len: Length of client address name buffer
389 * @rip: Buffer to take client address IP qotted quad
390 * @rip_len: Length of client address IP buffer
391 *
392 * This function fills in @name and @rip with the name and IP of
Andy Green6ee372f2012-04-09 15:09:01 +0800393 * the client connected with socket descriptor @fd. Names may be
394 * truncated if there is not enough room. If either cannot be
395 * determined, they will be returned as valid zero-length strings.
Andy Green07034092011-02-13 08:37:12 +0000396 */
397
398void
399libwebsockets_get_peer_addresses(int fd, char *name, int name_len,
400 char *rip, int rip_len)
401{
402 unsigned int len;
403 struct sockaddr_in sin;
404 struct hostent *host;
405 struct hostent *host1;
406 char ip[128];
Andy Greenf92def72011-03-09 15:02:20 +0000407 unsigned char *p;
Andy Green07034092011-02-13 08:37:12 +0000408 int n;
David Galeanocb193682013-01-09 15:29:00 +0800409#ifdef AF_LOCAL
410 struct sockaddr_un *un;
411#endif
Andy Green07034092011-02-13 08:37:12 +0000412
413 rip[0] = '\0';
414 name[0] = '\0';
415
416 len = sizeof sin;
417 if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
418 perror("getpeername");
419 return;
420 }
Andy Green6ee372f2012-04-09 15:09:01 +0800421
Andy Green07034092011-02-13 08:37:12 +0000422 host = gethostbyaddr((char *) &sin.sin_addr, sizeof sin.sin_addr,
423 AF_INET);
424 if (host == NULL) {
425 perror("gethostbyaddr");
426 return;
427 }
428
429 strncpy(name, host->h_name, name_len);
430 name[name_len - 1] = '\0';
431
432 host1 = gethostbyname(host->h_name);
433 if (host1 == NULL)
434 return;
Andy Greenf92def72011-03-09 15:02:20 +0000435 p = (unsigned char *)host1;
Andy Green07034092011-02-13 08:37:12 +0000436 n = 0;
437 while (p != NULL) {
Andy Greenf92def72011-03-09 15:02:20 +0000438 p = (unsigned char *)host1->h_addr_list[n++];
Andy Green07034092011-02-13 08:37:12 +0000439 if (p == NULL)
440 continue;
Peter Hinzbb45a902011-03-10 18:14:01 +0000441 if ((host1->h_addrtype != AF_INET)
442#ifdef AF_LOCAL
443 && (host1->h_addrtype != AF_LOCAL)
444#endif
445 )
Andy Green07034092011-02-13 08:37:12 +0000446 continue;
447
Andy Green7627af52011-03-09 15:13:52 +0000448 if (host1->h_addrtype == AF_INET)
449 sprintf(ip, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
Peter Hinzbb45a902011-03-10 18:14:01 +0000450#ifdef AF_LOCAL
Andy Green7627af52011-03-09 15:13:52 +0000451 else {
452 un = (struct sockaddr_un *)p;
Andy Green6ee372f2012-04-09 15:09:01 +0800453 strncpy(ip, un->sun_path, sizeof(ip) - 1);
Andy Green7627af52011-03-09 15:13:52 +0000454 ip[sizeof(ip) - 1] = '\0';
455 }
Peter Hinzbb45a902011-03-10 18:14:01 +0000456#endif
Andy Green07034092011-02-13 08:37:12 +0000457 p = NULL;
458 strncpy(rip, ip, rip_len);
459 rip[rip_len - 1] = '\0';
460 }
461}
Andy Green9f990342011-02-12 11:57:45 +0000462
Peter Hinz56885f32011-03-02 22:03:47 +0000463int libwebsockets_get_random(struct libwebsocket_context *context,
464 void *buf, int len)
465{
466 int n;
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800467 char *p = (char *)buf;
Peter Hinz56885f32011-03-02 22:03:47 +0000468
469#ifdef WIN32
470 for (n = 0; n < len; n++)
471 p[n] = (unsigned char)rand();
472#else
473 n = read(context->fd_random, p, len);
474#endif
475
476 return n;
477}
478
Andy Green2836c642011-03-07 20:47:41 +0000479unsigned char *
480libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md)
481{
482 return SHA1(d, n, md);
483}
484
Andy Green95a7b5d2011-03-06 10:29:39 +0000485int lws_send_pipe_choked(struct libwebsocket *wsi)
486{
487 struct pollfd fds;
488
489 fds.fd = wsi->sock;
490 fds.events = POLLOUT;
491 fds.revents = 0;
492
493 if (poll(&fds, 1, 0) != 1)
494 return 1;
495
496 if ((fds.revents & POLLOUT) == 0)
497 return 1;
498
499 /* okay to send another packet without blocking */
500
501 return 0;
502}
503
Andy Greena41314f2011-05-23 10:00:03 +0100504int
Andy Green3b84c002011-03-06 13:14:42 +0000505lws_handle_POLLOUT_event(struct libwebsocket_context *context,
506 struct libwebsocket *wsi, struct pollfd *pollfd)
507{
508 struct lws_tokens eff_buf;
509 int n;
510 int ret;
511 int m;
Andy Greena41314f2011-05-23 10:00:03 +0100512 int handled = 0;
Andy Green3b84c002011-03-06 13:14:42 +0000513
Andy Greena41314f2011-05-23 10:00:03 +0100514 for (n = 0; n < wsi->count_active_extensions; n++) {
515 if (!wsi->active_extensions[n]->callback)
516 continue;
517
518 m = wsi->active_extensions[n]->callback(context,
519 wsi->active_extensions[n], wsi,
520 LWS_EXT_CALLBACK_IS_WRITEABLE,
521 wsi->active_extensions_user[n], NULL, 0);
522 if (m > handled)
523 handled = m;
524 }
525
526 if (handled == 1)
527 goto notify_action;
528
529 if (!wsi->extension_data_pending || handled == 2)
Andy Green3b84c002011-03-06 13:14:42 +0000530 goto user_service;
531
532 /*
533 * check in on the active extensions, see if they
534 * had pending stuff to spill... they need to get the
535 * first look-in otherwise sequence will be disordered
536 *
537 * NULL, zero-length eff_buf means just spill pending
538 */
539
540 ret = 1;
541 while (ret == 1) {
542
543 /* default to nobody has more to spill */
544
545 ret = 0;
546 eff_buf.token = NULL;
547 eff_buf.token_len = 0;
548
549 /* give every extension a chance to spill */
550
551 for (n = 0; n < wsi->count_active_extensions; n++) {
552 m = wsi->active_extensions[n]->callback(
Andy Green46c2ea02011-03-22 09:04:01 +0000553 wsi->protocol->owning_server,
554 wsi->active_extensions[n], wsi,
Andy Green3b84c002011-03-06 13:14:42 +0000555 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
556 wsi->active_extensions_user[n], &eff_buf, 0);
557 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +0800558 lwsl_err("ext reports fatal error\n");
Andy Green3b84c002011-03-06 13:14:42 +0000559 return -1;
560 }
561 if (m)
562 /*
563 * at least one extension told us he has more
564 * to spill, so we will go around again after
565 */
566 ret = 1;
567 }
568
569 /* assuming they gave us something to send, send it */
570
571 if (eff_buf.token_len) {
572 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
573 eff_buf.token_len))
574 return -1;
575 } else
576 continue;
577
578 /* no extension has more to spill */
579
580 if (!ret)
581 continue;
582
583 /*
584 * There's more to spill from an extension, but we just sent
585 * something... did that leave the pipe choked?
586 */
587
588 if (!lws_send_pipe_choked(wsi))
589 /* no we could add more */
590 continue;
591
Andy Green43db0452013-01-10 19:50:35 +0800592 lwsl_info("choked in POLLOUT service\n");
Andy Green3b84c002011-03-06 13:14:42 +0000593
594 /*
595 * Yes, he's choked. Leave the POLLOUT masked on so we will
596 * come back here when he is unchoked. Don't call the user
597 * callback to enforce ordering of spilling, he'll get called
598 * when we come back here and there's nothing more to spill.
599 */
600
601 return 0;
602 }
603
604 wsi->extension_data_pending = 0;
605
606user_service:
607 /* one shot */
608
Andy Greena41314f2011-05-23 10:00:03 +0100609 if (pollfd) {
610 pollfd->events &= ~POLLOUT;
Andy Green3b84c002011-03-06 13:14:42 +0000611
Andy Greena41314f2011-05-23 10:00:03 +0100612 /* external POLL support via protocol 0 */
613 context->protocols[0].callback(context, wsi,
614 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
615 (void *)(long)wsi->sock, NULL, POLLOUT);
616 }
617
618notify_action:
Andy Green3b84c002011-03-06 13:14:42 +0000619
Andy Green9e4c2b62011-03-07 20:47:39 +0000620 if (wsi->mode == LWS_CONNMODE_WS_CLIENT)
621 n = LWS_CALLBACK_CLIENT_WRITEABLE;
622 else
623 n = LWS_CALLBACK_SERVER_WRITEABLE;
624
Andy Green706961d2013-01-17 16:50:35 +0800625 user_callback_handle_rxflow(wsi->protocol->callback, context,
626 wsi, (enum libwebsocket_callback_reasons) n, wsi->user_space, NULL, 0);
Andy Green3b84c002011-03-06 13:14:42 +0000627
628 return 0;
629}
630
631
632
Andy Greena41314f2011-05-23 10:00:03 +0100633void
634libwebsocket_service_timeout_check(struct libwebsocket_context *context,
635 struct libwebsocket *wsi, unsigned int sec)
636{
637 int n;
638
639 /*
640 * if extensions want in on it (eg, we are a mux parent)
641 * give them a chance to service child timeouts
642 */
643
644 for (n = 0; n < wsi->count_active_extensions; n++)
645 wsi->active_extensions[n]->callback(
646 context, wsi->active_extensions[n],
647 wsi, LWS_EXT_CALLBACK_1HZ,
648 wsi->active_extensions_user[n], NULL, sec);
649
650 if (!wsi->pending_timeout)
651 return;
Andy Green6ee372f2012-04-09 15:09:01 +0800652
Andy Greena41314f2011-05-23 10:00:03 +0100653 /*
654 * if we went beyond the allowed time, kill the
655 * connection
656 */
657
658 if (sec > wsi->pending_timeout_limit) {
Andy Green43db0452013-01-10 19:50:35 +0800659 lwsl_info("TIMEDOUT WAITING\n");
Andy Greena41314f2011-05-23 10:00:03 +0100660 libwebsocket_close_and_free_session(context,
661 wsi, LWS_CLOSE_STATUS_NOSTATUS);
662 }
663}
664
Andy Green9f990342011-02-12 11:57:45 +0000665/**
666 * libwebsocket_service_fd() - Service polled socket with something waiting
Peter Hinz56885f32011-03-02 22:03:47 +0000667 * @context: Websocket context
Andy Green9f990342011-02-12 11:57:45 +0000668 * @pollfd: The pollfd entry describing the socket fd and which events
Andy Green6ee372f2012-04-09 15:09:01 +0800669 * happened.
Andy Green9f990342011-02-12 11:57:45 +0000670 *
671 * This function closes any active connections and then frees the
672 * context. After calling this, any further use of the context is
673 * undefined.
674 */
675
676int
Peter Hinz56885f32011-03-02 22:03:47 +0000677libwebsocket_service_fd(struct libwebsocket_context *context,
Andy Green0d338332011-02-12 11:57:43 +0000678 struct pollfd *pollfd)
Andy Greenb45993c2010-12-18 15:13:50 +0000679{
Andy Greena1ce6be2013-01-18 11:43:21 +0800680 struct libwebsocket *wsi;
Andy Green6ee372f2012-04-09 15:09:01 +0800681 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1 +
682 MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
Andy Greenb45993c2010-12-18 15:13:50 +0000683 int n;
Andy Green0d338332011-02-12 11:57:43 +0000684 int m;
Andy Greena71eafc2011-02-14 17:59:43 +0000685 struct timeval tv;
Andy Green2366b1c2011-03-06 13:15:31 +0000686 int more = 1;
Andy Green98a717c2011-03-06 13:14:15 +0000687 struct lws_tokens eff_buf;
Andy Green03674a62013-01-16 11:47:40 +0800688#ifndef LWS_NO_CLIENT
Andy Green76f61e72013-01-16 11:53:05 +0800689 extern int lws_client_socket_service(struct libwebsocket_context *context, struct libwebsocket *wsi, struct pollfd *pollfd);
Andy Green03674a62013-01-16 11:47:40 +0800690#endif
Andy Greena1ce6be2013-01-18 11:43:21 +0800691#ifndef LWS_NO_SERVER
692 extern int lws_server_socket_service(struct libwebsocket_context *context, struct libwebsocket *wsi, struct pollfd *pollfd);
693#endif
Andy Greena71eafc2011-02-14 17:59:43 +0000694 /*
695 * you can call us with pollfd = NULL to just allow the once-per-second
696 * global timeout checks; if less than a second since the last check
697 * it returns immediately then.
698 */
699
700 gettimeofday(&tv, NULL);
701
Peter Hinz56885f32011-03-02 22:03:47 +0000702 if (context->last_timeout_check_s != tv.tv_sec) {
703 context->last_timeout_check_s = tv.tv_sec;
Andy Greena71eafc2011-02-14 17:59:43 +0000704
705 /* global timeout check once per second */
706
Peter Hinz56885f32011-03-02 22:03:47 +0000707 for (n = 0; n < context->fds_count; n++) {
Andy Greendfb23042013-01-17 12:26:48 +0800708 struct libwebsocket *new_wsi = context->lws_lookup[context->fds[n].fd];
709 if (!new_wsi)
710 continue;
711 libwebsocket_service_timeout_check(context,
712 new_wsi, tv.tv_sec);
Andy Greena71eafc2011-02-14 17:59:43 +0000713 }
714 }
715
716 /* just here for timeout management? */
717
718 if (pollfd == NULL)
719 return 0;
720
721 /* no, here to service a socket descriptor */
722
Andy Green65b0e912013-01-16 07:59:47 +0800723 /*
724 * deal with listen service piggybacking
725 * every listen_service_modulo services of other fds, we
726 * sneak one in to service the listen socket if there's anything waiting
727 *
728 * To handle connection storms, as found in ab, if we previously saw a
729 * pending connection here, it causes us to check again next time.
730 */
731
732 if (context->listen_service_fd && pollfd->fd != context->listen_service_fd) {
733 context->listen_service_count++;
734 if (context->listen_service_extraseen ||
735 context->listen_service_count == context->listen_service_modulo) {
736 context->listen_service_count = 0;
737 m = 1;
738 if (context->listen_service_extraseen > 5)
739 m = 2;
740 while (m--) {
741 /* even with extpoll, we prepared this internal fds for listen */
742 n = poll(&context->fds[0], 1, 0);
743 if (n > 0) { /* there's a connection waiting for us */
744 libwebsocket_service_fd(context, &context->fds[0]);
745 context->listen_service_extraseen++;
746 } else {
747 if (context->listen_service_extraseen)
748 context->listen_service_extraseen--;
749 break;
750 }
751 }
752 }
753
754 }
755
756 /* okay, what we came here to do... */
757
Andy Greendfb23042013-01-17 12:26:48 +0800758 wsi = context->lws_lookup[pollfd->fd];
Andy Greend280b6e2013-01-15 13:40:23 +0800759 if (wsi == NULL) {
Andy Greendfb23042013-01-17 12:26:48 +0800760 if (pollfd->fd > 11)
761 lwsl_err("unexpected NULL wsi fd=%d fds_count=%d\n", pollfd->fd, context->fds_count);
Andy Greenfa3f4052012-10-07 20:40:35 +0800762 return 0;
Andy Greend280b6e2013-01-15 13:40:23 +0800763 }
Andy Green8f037e42010-12-19 22:13:26 +0000764
Andy Green0d338332011-02-12 11:57:43 +0000765 switch (wsi->mode) {
Andy Greend280b6e2013-01-15 13:40:23 +0800766
Andy Greena1ce6be2013-01-18 11:43:21 +0800767#ifndef LWS_NO_SERVER
Andy Greend280b6e2013-01-15 13:40:23 +0800768 case LWS_CONNMODE_HTTP_SERVING:
Andy Green0d338332011-02-12 11:57:43 +0000769 case LWS_CONNMODE_SERVER_LISTENER:
Andy Green0d338332011-02-12 11:57:43 +0000770 case LWS_CONNMODE_BROADCAST_PROXY_LISTENER:
Andy Green0d338332011-02-12 11:57:43 +0000771 case LWS_CONNMODE_BROADCAST_PROXY:
Andy Greena1ce6be2013-01-18 11:43:21 +0800772 return lws_server_socket_service(context, wsi, pollfd);
773#endif
Andy Greenbe93fef2011-02-14 20:25:43 +0000774
Andy Green0d338332011-02-12 11:57:43 +0000775 case LWS_CONNMODE_WS_SERVING:
776 case LWS_CONNMODE_WS_CLIENT:
777
778 /* handle session socket closed */
779
780 if (pollfd->revents & (POLLERR | POLLHUP)) {
781
Andy Green43db0452013-01-10 19:50:35 +0800782 lwsl_debug("Session Socket %p (fd=%d) dead\n",
Andy Green0d338332011-02-12 11:57:43 +0000783 (void *)wsi, pollfd->fd);
784
Peter Hinz56885f32011-03-02 22:03:47 +0000785 libwebsocket_close_and_free_session(context, wsi,
Andy Green687b0182011-02-26 11:04:01 +0000786 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green040d2ef2013-01-16 13:40:43 +0800787 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +0000788 }
789
Andy Green0d338332011-02-12 11:57:43 +0000790 /* the guy requested a callback when it was OK to write */
791
Andy Greenda527df2011-03-07 07:08:12 +0000792 if ((pollfd->revents & POLLOUT) &&
793 wsi->state == WSI_STATE_ESTABLISHED)
794 if (lws_handle_POLLOUT_event(context, wsi,
795 pollfd) < 0) {
796 libwebsocket_close_and_free_session(
797 context, wsi, LWS_CLOSE_STATUS_NORMAL);
Andy Green040d2ef2013-01-16 13:40:43 +0800798 return 0;
Andy Green3b84c002011-03-06 13:14:42 +0000799 }
Andy Green0d338332011-02-12 11:57:43 +0000800
Andy Green0d338332011-02-12 11:57:43 +0000801
802 /* any incoming data ready? */
803
804 if (!(pollfd->revents & POLLIN))
805 break;
806
Andy Greenb45993c2010-12-18 15:13:50 +0000807#ifdef LWS_OPENSSL_SUPPORT
David Galeano7ffbe1b2013-01-10 10:35:32 +0800808read_pending:
Andy Green0d338332011-02-12 11:57:43 +0000809 if (wsi->ssl)
Andy Green98a717c2011-03-06 13:14:15 +0000810 eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);
Andy Greenb45993c2010-12-18 15:13:50 +0000811 else
812#endif
Andy Green98a717c2011-03-06 13:14:15 +0000813 eff_buf.token_len =
Andy Green72c34322011-04-16 10:46:21 +0100814 recv(pollfd->fd, buf, sizeof buf, 0);
Andy Greenb45993c2010-12-18 15:13:50 +0000815
Andy Green98a717c2011-03-06 13:14:15 +0000816 if (eff_buf.token_len < 0) {
Andy Green43db0452013-01-10 19:50:35 +0800817 lwsl_debug("Socket read returned %d\n",
Andy Green98a717c2011-03-06 13:14:15 +0000818 eff_buf.token_len);
Alon Levydc93b7f2012-10-19 11:21:57 +0200819 if (errno != EINTR && errno != EAGAIN)
Andy Green6ee372f2012-04-09 15:09:01 +0800820 libwebsocket_close_and_free_session(context,
821 wsi, LWS_CLOSE_STATUS_NOSTATUS);
Andy Green040d2ef2013-01-16 13:40:43 +0800822 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +0000823 }
Andy Green98a717c2011-03-06 13:14:15 +0000824 if (!eff_buf.token_len) {
Peter Hinz56885f32011-03-02 22:03:47 +0000825 libwebsocket_close_and_free_session(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +0800826 LWS_CLOSE_STATUS_NOSTATUS);
Andy Greenfa3f4052012-10-07 20:40:35 +0800827 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +0000828 }
829
Andy Green98a717c2011-03-06 13:14:15 +0000830 /*
831 * give any active extensions a chance to munge the buffer
832 * before parse. We pass in a pointer to an lws_tokens struct
833 * prepared with the default buffer and content length that's in
834 * there. Rather than rewrite the default buffer, extensions
835 * that expect to grow the buffer can adapt .token to
836 * point to their own per-connection buffer in the extension
837 * user allocation. By default with no extensions or no
838 * extension callback handling, just the normal input buffer is
839 * used then so it is efficient.
840 */
Andy Greenb45993c2010-12-18 15:13:50 +0000841
Andy Green98a717c2011-03-06 13:14:15 +0000842 eff_buf.token = (char *)buf;
Andy Greenb45993c2010-12-18 15:13:50 +0000843
Andy Green98a717c2011-03-06 13:14:15 +0000844 more = 1;
845 while (more) {
Andy Green0d338332011-02-12 11:57:43 +0000846
Andy Green98a717c2011-03-06 13:14:15 +0000847 more = 0;
848
849 for (n = 0; n < wsi->count_active_extensions; n++) {
Andy Green46c2ea02011-03-22 09:04:01 +0000850 m = wsi->active_extensions[n]->callback(context,
851 wsi->active_extensions[n], wsi,
Andy Green98a717c2011-03-06 13:14:15 +0000852 LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
Andy Green46c2ea02011-03-22 09:04:01 +0000853 wsi->active_extensions_user[n],
854 &eff_buf, 0);
Andy Green98a717c2011-03-06 13:14:15 +0000855 if (m < 0) {
Andy Green43db0452013-01-10 19:50:35 +0800856 lwsl_ext(
Andy Green6ee372f2012-04-09 15:09:01 +0800857 "Extension reports fatal error\n");
858 libwebsocket_close_and_free_session(
859 context, wsi,
860 LWS_CLOSE_STATUS_NOSTATUS);
Andy Green040d2ef2013-01-16 13:40:43 +0800861 return 0;
Andy Green98a717c2011-03-06 13:14:15 +0000862 }
863 if (m)
864 more = 1;
865 }
866
867 /* service incoming data */
868
869 if (eff_buf.token_len) {
870 n = libwebsocket_read(context, wsi,
Andy Green6ee372f2012-04-09 15:09:01 +0800871 (unsigned char *)eff_buf.token,
872 eff_buf.token_len);
Andy Green98a717c2011-03-06 13:14:15 +0000873 if (n < 0)
874 /* we closed wsi */
Andy Green040d2ef2013-01-16 13:40:43 +0800875 return 0;
Andy Green98a717c2011-03-06 13:14:15 +0000876 }
877
878 eff_buf.token = NULL;
879 eff_buf.token_len = 0;
880 }
David Galeano7ffbe1b2013-01-10 10:35:32 +0800881
882#ifdef LWS_OPENSSL_SUPPORT
883 if (wsi->ssl && SSL_pending(wsi->ssl))
884 goto read_pending;
885#endif
Andy Green98a717c2011-03-06 13:14:15 +0000886 break;
Andy Green76f61e72013-01-16 11:53:05 +0800887
888 default:
Andy Green03674a62013-01-16 11:47:40 +0800889#ifdef LWS_NO_CLIENT
890 break;
891#else
Andy Green76f61e72013-01-16 11:53:05 +0800892 return lws_client_socket_service(context, wsi, pollfd);
Andy Green03674a62013-01-16 11:47:40 +0800893#endif
Andy Greenb45993c2010-12-18 15:13:50 +0000894 }
895
896 return 0;
897}
898
Andy Green0d338332011-02-12 11:57:43 +0000899
Andy Green6964bb52011-01-23 16:50:33 +0000900/**
901 * libwebsocket_context_destroy() - Destroy the websocket context
Peter Hinz56885f32011-03-02 22:03:47 +0000902 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +0000903 *
904 * This function closes any active connections and then frees the
905 * context. After calling this, any further use of the context is
906 * undefined.
907 */
908void
Peter Hinz56885f32011-03-02 22:03:47 +0000909libwebsocket_context_destroy(struct libwebsocket_context *context)
Andy Green6964bb52011-01-23 16:50:33 +0000910{
Andy Green0d338332011-02-12 11:57:43 +0000911 int n;
912 int m;
Andy Greena41314f2011-05-23 10:00:03 +0100913 struct libwebsocket_extension *ext;
Andy Green6964bb52011-01-23 16:50:33 +0000914
Andy Greendfb23042013-01-17 12:26:48 +0800915 for (n = 0; n < context->fds_count; n++) {
916 struct libwebsocket *wsi = context->lws_lookup[context->fds[n].fd];
917 libwebsocket_close_and_free_session(context,
918 wsi, LWS_CLOSE_STATUS_GOINGAWAY);
919 }
Andy Green6964bb52011-01-23 16:50:33 +0000920
Andy Greena41314f2011-05-23 10:00:03 +0100921 /*
922 * give all extensions a chance to clean up any per-context
923 * allocations they might have made
924 */
925
926 ext = context->extensions;
927 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT;
928 if (context->listen_port)
929 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
Paulo Roberto Urio1f680ab2012-06-04 08:40:28 +0800930 while (ext && ext->callback) {
Aaron Zinman4550f1d2013-01-10 12:35:18 +0800931 ext->callback(context, ext, NULL, (enum libwebsocket_extension_callback_reasons)m, NULL, NULL, 0);
Andy Greena41314f2011-05-23 10:00:03 +0100932 ext++;
933 }
934
Peter Hinz56885f32011-03-02 22:03:47 +0000935#ifdef WIN32
936#else
937 close(context->fd_random);
Andy Green6964bb52011-01-23 16:50:33 +0000938#endif
939
Peter Hinz56885f32011-03-02 22:03:47 +0000940#ifdef LWS_OPENSSL_SUPPORT
941 if (context->ssl_ctx)
942 SSL_CTX_free(context->ssl_ctx);
943 if (context->ssl_client_ctx)
944 SSL_CTX_free(context->ssl_client_ctx);
945#endif
946
947 free(context);
948
949#ifdef WIN32
950 WSACleanup();
951#endif
Andy Green6964bb52011-01-23 16:50:33 +0000952}
953
Alon Levy0291eb32012-10-19 11:21:56 +0200954LWS_EXTERN void *
955libwebsocket_context_user(struct libwebsocket_context *context)
956{
957 return context->user_space;
958}
959
Andy Green6964bb52011-01-23 16:50:33 +0000960/**
961 * libwebsocket_service() - Service any pending websocket activity
Peter Hinz56885f32011-03-02 22:03:47 +0000962 * @context: Websocket context
Andy Green6964bb52011-01-23 16:50:33 +0000963 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
964 * service otherwise block and service immediately, returning
965 * after the timeout if nothing needed service.
966 *
967 * This function deals with any pending websocket traffic, for three
968 * kinds of event. It handles these events on both server and client
969 * types of connection the same.
970 *
971 * 1) Accept new connections to our context's server
972 *
973 * 2) Perform pending broadcast writes initiated from other forked
974 * processes (effectively serializing asynchronous broadcasts)
975 *
976 * 3) Call the receive callback for incoming frame data received by
977 * server or client connections.
978 *
979 * You need to call this service function periodically to all the above
980 * functions to happen; if your application is single-threaded you can
981 * just call it in your main event loop.
982 *
983 * Alternatively you can fork a new process that asynchronously handles
984 * calling this service in a loop. In that case you are happy if this
985 * call blocks your thread until it needs to take care of something and
986 * would call it with a large nonzero timeout. Your loop then takes no
987 * CPU while there is nothing happening.
988 *
989 * If you are calling it in a single-threaded app, you don't want it to
990 * wait around blocking other things in your loop from happening, so you
991 * would call it with a timeout_ms of 0, so it returns immediately if
992 * nothing is pending, or as soon as it services whatever was pending.
993 */
994
Andy Greenb45993c2010-12-18 15:13:50 +0000995
Andy Greene92cd172011-01-19 13:11:55 +0000996int
Peter Hinz56885f32011-03-02 22:03:47 +0000997libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
Andy Greene92cd172011-01-19 13:11:55 +0000998{
999 int n;
Andy Greene92cd172011-01-19 13:11:55 +00001000
1001 /* stay dead once we are dead */
1002
Peter Hinz56885f32011-03-02 22:03:47 +00001003 if (context == NULL)
Andy Greene92cd172011-01-19 13:11:55 +00001004 return 1;
1005
Andy Green0d338332011-02-12 11:57:43 +00001006 /* wait for something to need service */
Andy Green4739e5c2011-01-22 12:51:57 +00001007
Peter Hinz56885f32011-03-02 22:03:47 +00001008 n = poll(context->fds, context->fds_count, timeout_ms);
Andy Green3221f922011-02-12 13:14:11 +00001009 if (n == 0) /* poll timeout */
1010 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00001011
Andy Greendfb23042013-01-17 12:26:48 +08001012 if (n < 0)
Andy Green3928f612012-07-20 12:58:38 +08001013 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00001014
Andy Greendfb23042013-01-17 12:26:48 +08001015 /* any socket with events to service? */
Andy Greene92cd172011-01-19 13:11:55 +00001016
Peter Hinz56885f32011-03-02 22:03:47 +00001017 for (n = 0; n < context->fds_count; n++)
1018 if (context->fds[n].revents)
Andy Green3928f612012-07-20 12:58:38 +08001019 if (libwebsocket_service_fd(context,
1020 &context->fds[n]) < 0)
1021 return -1;
Andy Greene92cd172011-01-19 13:11:55 +00001022 return 0;
Andy Greene92cd172011-01-19 13:11:55 +00001023}
1024
Andy Greena41314f2011-05-23 10:00:03 +01001025int
1026lws_any_extension_handled(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08001027 struct libwebsocket *wsi,
1028 enum libwebsocket_extension_callback_reasons r,
Andy Greena41314f2011-05-23 10:00:03 +01001029 void *v, size_t len)
1030{
1031 int n;
1032 int handled = 0;
1033
1034 /* maybe an extension will take care of it for us */
1035
1036 for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
1037 if (!wsi->active_extensions[n]->callback)
1038 continue;
1039
1040 handled |= wsi->active_extensions[n]->callback(context,
1041 wsi->active_extensions[n], wsi,
1042 r, wsi->active_extensions_user[n], v, len);
1043 }
1044
1045 return handled;
1046}
1047
1048
1049void *
1050lws_get_extension_user_matching_ext(struct libwebsocket *wsi,
Andy Green6ee372f2012-04-09 15:09:01 +08001051 struct libwebsocket_extension *ext)
Andy Greena41314f2011-05-23 10:00:03 +01001052{
1053 int n = 0;
1054
Andy Green68b45042011-05-25 21:41:57 +01001055 if (wsi == NULL)
1056 return NULL;
1057
Andy Greena41314f2011-05-23 10:00:03 +01001058 while (n < wsi->count_active_extensions) {
1059 if (wsi->active_extensions[n] != ext) {
1060 n++;
1061 continue;
1062 }
1063 return wsi->active_extensions_user[n];
1064 }
1065
1066 return NULL;
1067}
1068
Andy Green90c7cbc2011-01-27 06:26:52 +00001069/**
1070 * libwebsocket_callback_on_writable() - Request a callback when this socket
1071 * becomes able to be written to without
1072 * blocking
Andy Green32375b72011-02-19 08:32:53 +00001073 *
Peter Hinz56885f32011-03-02 22:03:47 +00001074 * @context: libwebsockets context
Andy Green90c7cbc2011-01-27 06:26:52 +00001075 * @wsi: Websocket connection instance to get callback for
1076 */
1077
1078int
Peter Hinz56885f32011-03-02 22:03:47 +00001079libwebsocket_callback_on_writable(struct libwebsocket_context *context,
Andy Green6ee372f2012-04-09 15:09:01 +08001080 struct libwebsocket *wsi)
Andy Green90c7cbc2011-01-27 06:26:52 +00001081{
Andy Green90c7cbc2011-01-27 06:26:52 +00001082 int n;
Andy Greena41314f2011-05-23 10:00:03 +01001083 int handled = 0;
1084
1085 /* maybe an extension will take care of it for us */
1086
1087 for (n = 0; n < wsi->count_active_extensions; n++) {
1088 if (!wsi->active_extensions[n]->callback)
1089 continue;
1090
1091 handled |= wsi->active_extensions[n]->callback(context,
1092 wsi->active_extensions[n], wsi,
1093 LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
1094 wsi->active_extensions_user[n], NULL, 0);
1095 }
1096
1097 if (handled)
1098 return 1;
Andy Green90c7cbc2011-01-27 06:26:52 +00001099
Andy Greendfb23042013-01-17 12:26:48 +08001100 if (wsi->position_in_fds_table < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001101 lwsl_err("libwebsocket_callback_on_writable: "
Andy Green6ee372f2012-04-09 15:09:01 +08001102 "failed to find socket %d\n", wsi->sock);
Andy Greendfb23042013-01-17 12:26:48 +08001103 return -1;
1104 }
1105
1106 context->fds[wsi->position_in_fds_table].events |= POLLOUT;
Andy Greena41314f2011-05-23 10:00:03 +01001107
Andy Green3221f922011-02-12 13:14:11 +00001108 /* external POLL support via protocol 0 */
Peter Hinz56885f32011-03-02 22:03:47 +00001109 context->protocols[0].callback(context, wsi,
Andy Green3221f922011-02-12 13:14:11 +00001110 LWS_CALLBACK_SET_MODE_POLL_FD,
1111 (void *)(long)wsi->sock, NULL, POLLOUT);
1112
Andy Green90c7cbc2011-01-27 06:26:52 +00001113 return 1;
1114}
1115
1116/**
1117 * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
1118 * all connections using the given protocol when it
1119 * becomes possible to write to each socket without
1120 * blocking in turn.
1121 *
1122 * @protocol: Protocol whose connections will get callbacks
1123 */
1124
1125int
1126libwebsocket_callback_on_writable_all_protocol(
1127 const struct libwebsocket_protocols *protocol)
1128{
Peter Hinz56885f32011-03-02 22:03:47 +00001129 struct libwebsocket_context *context = protocol->owning_server;
Andy Green90c7cbc2011-01-27 06:26:52 +00001130 int n;
Andy Green0d338332011-02-12 11:57:43 +00001131 struct libwebsocket *wsi;
Andy Green90c7cbc2011-01-27 06:26:52 +00001132
Andy Greendfb23042013-01-17 12:26:48 +08001133 for (n = 0; n < context->fds_count; n++) {
1134 wsi = context->lws_lookup[context->fds[n].fd];
1135 if (!wsi)
1136 continue;
1137 if (wsi->protocol == protocol)
1138 libwebsocket_callback_on_writable(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00001139 }
Andy Green90c7cbc2011-01-27 06:26:52 +00001140
1141 return 0;
1142}
1143
Andy Greenbe93fef2011-02-14 20:25:43 +00001144/**
1145 * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
1146 *
1147 * You will not need this unless you are doing something special
1148 *
1149 * @wsi: Websocket connection instance
1150 * @reason: timeout reason
1151 * @secs: how many seconds
1152 */
1153
1154void
1155libwebsocket_set_timeout(struct libwebsocket *wsi,
1156 enum pending_timeout reason, int secs)
1157{
1158 struct timeval tv;
1159
1160 gettimeofday(&tv, NULL);
1161
1162 wsi->pending_timeout_limit = tv.tv_sec + secs;
1163 wsi->pending_timeout = reason;
1164}
1165
Andy Greena6cbece2011-01-27 20:06:03 +00001166
1167/**
1168 * libwebsocket_get_socket_fd() - returns the socket file descriptor
1169 *
1170 * You will not need this unless you are doing something special
1171 *
1172 * @wsi: Websocket connection instance
1173 */
1174
1175int
1176libwebsocket_get_socket_fd(struct libwebsocket *wsi)
1177{
1178 return wsi->sock;
1179}
1180
Andy Greena1ce6be2013-01-18 11:43:21 +08001181#ifdef LWS_NO_SERVER
1182int
1183_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
1184{
1185 return 0;
1186}
1187#else
Andy Green706961d2013-01-17 16:50:35 +08001188int
1189_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
1190{
1191 struct libwebsocket_context *context = wsi->protocol->owning_server;
1192 int n;
1193
1194 if (!(wsi->rxflow_change_to & 2))
1195 return 0;
1196
1197 wsi->rxflow_change_to &= ~2;
1198
1199 lwsl_info("rxflow: wsi %p change_to %d\n", wsi, wsi->rxflow_change_to);
1200
1201 /* if we're letting it come again, did we interrupt anything? */
1202 if ((wsi->rxflow_change_to & 1) && wsi->rxflow_buffer) {
1203 n = libwebsocket_interpret_incoming_packet(wsi, NULL, 0);
1204 if (n < 0) {
1205 libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
1206 return -1;
1207 }
1208 if (n)
1209 /* oh he stuck again, do nothing */
1210 return 0;
1211 }
1212
1213 if (wsi->rxflow_change_to & 1)
1214 context->fds[wsi->position_in_fds_table].events |= POLLIN;
1215 else
1216 context->fds[wsi->position_in_fds_table].events &= ~POLLIN;
1217
1218 if (wsi->rxflow_change_to & 1)
1219 /* external POLL support via protocol 0 */
1220 context->protocols[0].callback(context, wsi,
1221 LWS_CALLBACK_SET_MODE_POLL_FD,
1222 (void *)(long)wsi->sock, NULL, POLLIN);
1223 else
1224 /* external POLL support via protocol 0 */
1225 context->protocols[0].callback(context, wsi,
1226 LWS_CALLBACK_CLEAR_MODE_POLL_FD,
1227 (void *)(long)wsi->sock, NULL, POLLIN);
1228
1229 return 1;
1230}
Andy Greena1ce6be2013-01-18 11:43:21 +08001231#endif
Andy Green706961d2013-01-17 16:50:35 +08001232
Andy Green90c7cbc2011-01-27 06:26:52 +00001233/**
1234 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
1235 * receieved packets.
1236 *
1237 * If the output side of a server process becomes choked, this allows flow
1238 * control for the input side.
1239 *
1240 * @wsi: Websocket connection instance to get callback for
1241 * @enable: 0 = disable read servicing for this connection, 1 = enable
1242 */
1243
1244int
1245libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
1246{
Andy Green706961d2013-01-17 16:50:35 +08001247 wsi->rxflow_change_to = 2 | !!enable;
Andy Green90c7cbc2011-01-27 06:26:52 +00001248
Andy Green706961d2013-01-17 16:50:35 +08001249 return 0;
Andy Green90c7cbc2011-01-27 06:26:52 +00001250}
1251
Andy Green706961d2013-01-17 16:50:35 +08001252
Andy Green2ac5a6f2011-01-28 10:00:18 +00001253/**
1254 * libwebsocket_canonical_hostname() - returns this host's hostname
1255 *
1256 * This is typically used by client code to fill in the host parameter
1257 * when making a client connection. You can only call it after the context
1258 * has been created.
1259 *
Peter Hinz56885f32011-03-02 22:03:47 +00001260 * @context: Websocket context
Andy Green2ac5a6f2011-01-28 10:00:18 +00001261 */
1262
1263
1264extern const char *
Peter Hinz56885f32011-03-02 22:03:47 +00001265libwebsocket_canonical_hostname(struct libwebsocket_context *context)
Andy Green2ac5a6f2011-01-28 10:00:18 +00001266{
Peter Hinz56885f32011-03-02 22:03:47 +00001267 return (const char *)context->canonical_hostname;
Andy Green2ac5a6f2011-01-28 10:00:18 +00001268}
1269
1270
Andy Green90c7cbc2011-01-27 06:26:52 +00001271static void sigpipe_handler(int x)
1272{
1273}
1274
Andy Green6901cb32011-02-21 08:06:47 +00001275#ifdef LWS_OPENSSL_SUPPORT
1276static int
1277OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
1278{
1279
1280 SSL *ssl;
1281 int n;
Andy Green2e24da02011-03-05 16:12:04 +00001282 struct libwebsocket_context *context;
Andy Green6901cb32011-02-21 08:06:47 +00001283
1284 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
1285 SSL_get_ex_data_X509_STORE_CTX_idx());
1286
1287 /*
Andy Green2e24da02011-03-05 16:12:04 +00001288 * !!! nasty openssl requires the index to come as a library-scope
1289 * static
Andy Green6901cb32011-02-21 08:06:47 +00001290 */
Andy Green2e24da02011-03-05 16:12:04 +00001291 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
Andy Green6ee372f2012-04-09 15:09:01 +08001292
Peter Hinz56885f32011-03-02 22:03:47 +00001293 n = context->protocols[0].callback(NULL, NULL,
Andy Green6901cb32011-02-21 08:06:47 +00001294 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
1295 x509_ctx, ssl, preverify_ok);
1296
1297 /* convert return code from 0 = OK to 1 = OK */
1298
1299 if (!n)
1300 n = 1;
1301 else
1302 n = 0;
1303
1304 return n;
1305}
1306#endif
1307
Andy Green706961d2013-01-17 16:50:35 +08001308int user_callback_handle_rxflow(callback_function callback_function,
1309 struct libwebsocket_context * context,
1310 struct libwebsocket *wsi,
1311 enum libwebsocket_callback_reasons reason, void *user,
1312 void *in, size_t len)
1313{
1314 int n;
1315
1316 n = callback_function(context, wsi, reason, user, in, len);
1317 if (n < 0)
1318 return n;
1319
1320 _libwebsocket_rx_flow_control(wsi);
1321
1322 return 0;
1323}
1324
Andy Greenb45993c2010-12-18 15:13:50 +00001325
Andy Greenab990e42010-10-31 12:42:52 +00001326/**
Andy Green4739e5c2011-01-22 12:51:57 +00001327 * libwebsocket_create_context() - Create the websocket handler
1328 * @port: Port to listen on... you can use 0 to suppress listening on
Andy Green6964bb52011-01-23 16:50:33 +00001329 * any port, that's what you want if you are not running a
1330 * websocket server at all but just using it as a client
Peter Hinz56885f32011-03-02 22:03:47 +00001331 * @interf: NULL to bind the listen socket to all interfaces, or the
Andy Green32375b72011-02-19 08:32:53 +00001332 * interface name, eg, "eth2"
Andy Green4f3943a2010-11-12 10:44:16 +00001333 * @protocols: Array of structures listing supported protocols and a protocol-
Andy Green8f037e42010-12-19 22:13:26 +00001334 * specific callback for each one. The list is ended with an
1335 * entry that has a NULL callback pointer.
Andy Green6964bb52011-01-23 16:50:33 +00001336 * It's not const because we write the owning_server member
Andy Greenc5114822011-03-06 10:29:35 +00001337 * @extensions: NULL or array of libwebsocket_extension structs listing the
Andy Green6ee372f2012-04-09 15:09:01 +08001338 * extensions this context supports
Andy Green3faa9c72010-11-08 17:03:03 +00001339 * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
Andy Green8f037e42010-12-19 22:13:26 +00001340 * to listen using SSL, set to the filepath to fetch the
1341 * server cert from, otherwise NULL for unencrypted
Andy Green3faa9c72010-11-08 17:03:03 +00001342 * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
Andy Green8f037e42010-12-19 22:13:26 +00001343 * else ignored
David Galeano2f82be82013-01-09 16:25:54 +08001344 * @ssl_ca_filepath: CA certificate filepath or NULL
Andy Green3faa9c72010-11-08 17:03:03 +00001345 * @gid: group id to change to after setting listen socket, or -1.
1346 * @uid: user id to change to after setting listen socket, or -1.
Andy Greenbfb051f2011-02-09 08:49:14 +00001347 * @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
Andy Green15e31f32012-10-19 18:36:28 +08001348 * @user: optional user pointer that can be recovered via the context
1349 * pointer using libwebsocket_context_user
Andy Green05464c62010-11-12 10:44:18 +00001350 *
Andy Green8f037e42010-12-19 22:13:26 +00001351 * This function creates the listening socket and takes care
1352 * of all initialization in one step.
1353 *
Andy Greene92cd172011-01-19 13:11:55 +00001354 * After initialization, it returns a struct libwebsocket_context * that
1355 * represents this server. After calling, user code needs to take care
1356 * of calling libwebsocket_service() with the context pointer to get the
1357 * server's sockets serviced. This can be done in the same process context
1358 * or a forked process, or another thread,
Andy Green05464c62010-11-12 10:44:18 +00001359 *
Andy Green8f037e42010-12-19 22:13:26 +00001360 * The protocol callback functions are called for a handful of events
1361 * including http requests coming in, websocket connections becoming
1362 * established, and data arriving; it's also called periodically to allow
1363 * async transmission.
1364 *
1365 * HTTP requests are sent always to the FIRST protocol in @protocol, since
1366 * at that time websocket protocol has not been negotiated. Other
1367 * protocols after the first one never see any HTTP callack activity.
1368 *
1369 * The server created is a simple http server by default; part of the
1370 * websocket standard is upgrading this http connection to a websocket one.
1371 *
1372 * This allows the same server to provide files like scripts and favicon /
1373 * images or whatever over http and dynamic data over websockets all in
1374 * one place; they're all handled in the user callback.
Andy Greenab990e42010-10-31 12:42:52 +00001375 */
Andy Green4ea60062010-10-30 12:15:07 +01001376
Andy Greene92cd172011-01-19 13:11:55 +00001377struct libwebsocket_context *
Peter Hinz56885f32011-03-02 22:03:47 +00001378libwebsocket_create_context(int port, const char *interf,
Andy Greenb45993c2010-12-18 15:13:50 +00001379 struct libwebsocket_protocols *protocols,
Andy Greend6e09112011-03-05 16:12:15 +00001380 struct libwebsocket_extension *extensions,
Andy Green8f037e42010-12-19 22:13:26 +00001381 const char *ssl_cert_filepath,
1382 const char *ssl_private_key_filepath,
David Galeano2f82be82013-01-09 16:25:54 +08001383 const char *ssl_ca_filepath,
Alon Levy0291eb32012-10-19 11:21:56 +02001384 int gid, int uid, unsigned int options,
David Galeano2f82be82013-01-09 16:25:54 +08001385 void *user)
Andy Greenff95d7a2010-10-28 22:36:01 +01001386{
1387 int n;
Andy Greena41314f2011-05-23 10:00:03 +01001388 int m;
Andy Green251f6fa2010-11-03 11:13:06 +00001389 int fd;
Andy Greenff95d7a2010-10-28 22:36:01 +01001390 struct sockaddr_in serv_addr, cli_addr;
Andy Green251f6fa2010-11-03 11:13:06 +00001391 int opt = 1;
Peter Hinz56885f32011-03-02 22:03:47 +00001392 struct libwebsocket_context *context = NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00001393 unsigned int slen;
Andy Green9659f372011-01-27 22:01:43 +00001394 char *p;
Andy Green0d338332011-02-12 11:57:43 +00001395 struct libwebsocket *wsi;
Andy Greenff95d7a2010-10-28 22:36:01 +01001396
Andy Green3faa9c72010-11-08 17:03:03 +00001397#ifdef LWS_OPENSSL_SUPPORT
Andy Greenf2f54d52010-11-15 22:08:00 +00001398 SSL_METHOD *method;
Andy Green3faa9c72010-11-08 17:03:03 +00001399 char ssl_err_buf[512];
Andy Green3faa9c72010-11-08 17:03:03 +00001400#endif
1401
Andy Greenb3a614a2013-01-19 13:08:17 +08001402 lwsl_notice("Initial logging level %d\n", log_level);
Andy Greenc0d6b632013-01-12 23:42:17 +08001403 lwsl_info(" LWS_MAX_HEADER_NAME_LENGTH: %u\n", LWS_MAX_HEADER_NAME_LENGTH);
1404 lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
1405 lwsl_info(" LWS_INITIAL_HDR_ALLOC: %u\n", LWS_INITIAL_HDR_ALLOC);
1406 lwsl_info(" LWS_ADDITIONAL_HDR_ALLOC: %u\n", LWS_ADDITIONAL_HDR_ALLOC);
1407 lwsl_info(" MAX_USER_RX_BUFFER: %u\n", MAX_USER_RX_BUFFER);
1408 lwsl_info(" MAX_BROADCAST_PAYLOAD: %u\n", MAX_BROADCAST_PAYLOAD);
1409 lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
1410 lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE);
1411 lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED);
1412 lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT);
1413 lwsl_info(" CIPHERS_LIST_STRING: '%s'\n", CIPHERS_LIST_STRING);
1414 lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
1415 lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER);
Andy Green43db0452013-01-10 19:50:35 +08001416
Peter Hinz56885f32011-03-02 22:03:47 +00001417#ifdef _WIN32
1418 {
1419 WORD wVersionRequested;
1420 WSADATA wsaData;
1421 int err;
Andy Green6ee372f2012-04-09 15:09:01 +08001422 HMODULE wsdll;
Peter Hinz56885f32011-03-02 22:03:47 +00001423
1424 /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
1425 wVersionRequested = MAKEWORD(2, 2);
1426
1427 err = WSAStartup(wVersionRequested, &wsaData);
1428 if (err != 0) {
1429 /* Tell the user that we could not find a usable */
1430 /* Winsock DLL. */
Andy Green43db0452013-01-10 19:50:35 +08001431 lwsl_err("WSAStartup failed with error: %d\n", err);
Peter Hinz56885f32011-03-02 22:03:47 +00001432 return NULL;
1433 }
David Galeano7b11fec2011-10-04 19:55:18 +08001434
Andy Green6ee372f2012-04-09 15:09:01 +08001435 /* default to a poll() made out of select() */
1436 poll = emulated_poll;
David Galeano7b11fec2011-10-04 19:55:18 +08001437
Andy Green6ee372f2012-04-09 15:09:01 +08001438 /* if windows socket lib available, use his WSAPoll */
David Galeanocb193682013-01-09 15:29:00 +08001439 wsdll = GetModuleHandle(_T("Ws2_32.dll"));
Andy Green6ee372f2012-04-09 15:09:01 +08001440 if (wsdll)
1441 poll = (PFNWSAPOLL)GetProcAddress(wsdll, "WSAPoll");
Peter Hinz56885f32011-03-02 22:03:47 +00001442 }
1443#endif
1444
1445
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001446 context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context));
Peter Hinz56885f32011-03-02 22:03:47 +00001447 if (!context) {
Andy Green43db0452013-01-10 19:50:35 +08001448 lwsl_err("No memory for websocket context\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00001449 return NULL;
1450 }
Peter Hinz56885f32011-03-02 22:03:47 +00001451 context->protocols = protocols;
1452 context->listen_port = port;
1453 context->http_proxy_port = 0;
1454 context->http_proxy_address[0] = '\0';
1455 context->options = options;
Andy Greendfb23042013-01-17 12:26:48 +08001456 /* to reduce this allocation, */
1457 context->max_fds = getdtablesize();
Andy Greenb3a614a2013-01-19 13:08:17 +08001458 lwsl_notice(" max fd tracked: %u\n", context->max_fds);
Andy Greendfb23042013-01-17 12:26:48 +08001459
1460 context->fds = (struct pollfd *)malloc(sizeof(struct pollfd) * context->max_fds);
1461 if (context->fds == NULL) {
1462 lwsl_err("Unable to allocate fds array for %d connections\n", context->max_fds);
1463 free(context);
1464 return NULL;
1465 }
1466 context->lws_lookup = (struct libwebsocket **)malloc(sizeof(struct libwebsocke *) * context->max_fds);
1467 if (context->lws_lookup == NULL) {
1468 lwsl_err("Unable to allocate lws_lookup array for %d connections\n", context->max_fds);
1469 free(context->fds);
1470 free(context);
1471 return NULL;
1472 }
Peter Hinz56885f32011-03-02 22:03:47 +00001473 context->fds_count = 0;
Andy Greend6e09112011-03-05 16:12:15 +00001474 context->extensions = extensions;
Paulo Roberto Urio1e326632012-06-04 10:52:19 +08001475 context->last_timeout_check_s = 0;
Andy Greendfb23042013-01-17 12:26:48 +08001476 context->user_space = user;
Andy Green9659f372011-01-27 22:01:43 +00001477
Peter Hinz56885f32011-03-02 22:03:47 +00001478#ifdef WIN32
1479 context->fd_random = 0;
1480#else
1481 context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
1482 if (context->fd_random < 0) {
Andy Greendfb23042013-01-17 12:26:48 +08001483 free(context);
Andy Green43db0452013-01-10 19:50:35 +08001484 lwsl_err("Unable to open random device %s %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00001485 SYSTEM_RANDOM_FILEPATH, context->fd_random);
Andy Green44eee682011-02-10 09:32:24 +00001486 return NULL;
1487 }
Peter Hinz56885f32011-03-02 22:03:47 +00001488#endif
Andy Green44eee682011-02-10 09:32:24 +00001489
Peter Hinz56885f32011-03-02 22:03:47 +00001490#ifdef LWS_OPENSSL_SUPPORT
1491 context->use_ssl = 0;
1492 context->ssl_ctx = NULL;
1493 context->ssl_client_ctx = NULL;
Andy Green2e24da02011-03-05 16:12:04 +00001494 openssl_websocket_private_data_index = 0;
Peter Hinz56885f32011-03-02 22:03:47 +00001495#endif
Andy Green2ac5a6f2011-01-28 10:00:18 +00001496
Andy Greena1ce6be2013-01-18 11:43:21 +08001497 strcpy(context->canonical_hostname, "unknown");
Andy Greena69f0512012-05-03 12:32:38 +08001498
Andy Greena1ce6be2013-01-18 11:43:21 +08001499#ifndef LWS_NO_SERVER
1500 if (!(options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)) {
1501 struct sockaddr sa;
1502 char hostname[1024] = "";
Andy Green788c4a82012-10-22 12:29:57 +01001503
1504 /* find canonical hostname */
1505
1506 hostname[(sizeof hostname) - 1] = '\0';
1507 memset(&sa, 0, sizeof(sa));
1508 sa.sa_family = AF_INET;
1509 sa.sa_data[(sizeof sa.sa_data) - 1] = '\0';
1510 gethostname(hostname, (sizeof hostname) - 1);
1511
1512 n = 0;
1513
David Galeanoed3c8402013-01-10 10:45:24 +08001514 if (strlen(hostname) < sizeof(sa.sa_data) - 1) {
Andy Green788c4a82012-10-22 12:29:57 +01001515 strcpy(sa.sa_data, hostname);
Andy Green43db0452013-01-10 19:50:35 +08001516 // lwsl_debug("my host name is %s\n", sa.sa_data);
Andy Green788c4a82012-10-22 12:29:57 +01001517 n = getnameinfo(&sa, sizeof(sa), hostname,
1518 (sizeof hostname) - 1, NULL, 0, 0);
1519 }
1520
1521 if (!n) {
1522 strncpy(context->canonical_hostname, hostname,
1523 sizeof context->canonical_hostname - 1);
1524 context->canonical_hostname[
1525 sizeof context->canonical_hostname - 1] = '\0';
1526 } else
1527 strncpy(context->canonical_hostname, hostname,
1528 sizeof context->canonical_hostname - 1);
1529
Andy Greenb3a614a2013-01-19 13:08:17 +08001530 lwsl_notice(" canonical_hostname = %s\n", context->canonical_hostname);
Andy Greena69f0512012-05-03 12:32:38 +08001531 }
Andy Greena1ce6be2013-01-18 11:43:21 +08001532#endif
Andy Greena69f0512012-05-03 12:32:38 +08001533
Andy Green9659f372011-01-27 22:01:43 +00001534 /* split the proxy ads:port if given */
1535
1536 p = getenv("http_proxy");
1537 if (p) {
Peter Hinz56885f32011-03-02 22:03:47 +00001538 strncpy(context->http_proxy_address, p,
Andy Green6ee372f2012-04-09 15:09:01 +08001539 sizeof context->http_proxy_address - 1);
Peter Hinz56885f32011-03-02 22:03:47 +00001540 context->http_proxy_address[
1541 sizeof context->http_proxy_address - 1] = '\0';
Andy Green9659f372011-01-27 22:01:43 +00001542
Peter Hinz56885f32011-03-02 22:03:47 +00001543 p = strchr(context->http_proxy_address, ':');
Andy Green9659f372011-01-27 22:01:43 +00001544 if (p == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08001545 lwsl_err("http_proxy needs to be ads:port\n");
Andy Green9659f372011-01-27 22:01:43 +00001546 return NULL;
1547 }
1548 *p = '\0';
Peter Hinz56885f32011-03-02 22:03:47 +00001549 context->http_proxy_port = atoi(p + 1);
Andy Green9659f372011-01-27 22:01:43 +00001550
Andy Greenb3a614a2013-01-19 13:08:17 +08001551 lwsl_notice(" Proxy %s:%u\n",
Peter Hinz56885f32011-03-02 22:03:47 +00001552 context->http_proxy_address,
1553 context->http_proxy_port);
Andy Green9659f372011-01-27 22:01:43 +00001554 }
Andy Green90c7cbc2011-01-27 06:26:52 +00001555
Andy Greena1ce6be2013-01-18 11:43:21 +08001556#ifndef LWS_NO_SERVER
Andy Green90c7cbc2011-01-27 06:26:52 +00001557 if (port) {
1558
Andy Green3faa9c72010-11-08 17:03:03 +00001559#ifdef LWS_OPENSSL_SUPPORT
Peter Hinz56885f32011-03-02 22:03:47 +00001560 context->use_ssl = ssl_cert_filepath != NULL &&
Andy Green90c7cbc2011-01-27 06:26:52 +00001561 ssl_private_key_filepath != NULL;
Peter Hinz56885f32011-03-02 22:03:47 +00001562 if (context->use_ssl)
Andy Greenb3a614a2013-01-19 13:08:17 +08001563 lwsl_notice(" Compiled with SSL support, using it\n");
Andy Green90c7cbc2011-01-27 06:26:52 +00001564 else
Andy Greenb3a614a2013-01-19 13:08:17 +08001565 lwsl_notice(" Compiled with SSL support, not using it\n");
Andy Green3faa9c72010-11-08 17:03:03 +00001566
Andy Green90c7cbc2011-01-27 06:26:52 +00001567#else
1568 if (ssl_cert_filepath != NULL &&
1569 ssl_private_key_filepath != NULL) {
Andy Greenb3a614a2013-01-19 13:08:17 +08001570 lwsl_notice(" Not compiled for OpenSSl support!\n");
Andy Greene92cd172011-01-19 13:11:55 +00001571 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00001572 }
Andy Greenb3a614a2013-01-19 13:08:17 +08001573 lwsl_notice(" Compiled without SSL support, "
Andy Green90c7cbc2011-01-27 06:26:52 +00001574 "serving unencrypted\n");
1575#endif
1576 }
Andy Greena1ce6be2013-01-18 11:43:21 +08001577#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00001578
1579 /* ignore SIGPIPE */
Peter Hinz56885f32011-03-02 22:03:47 +00001580#ifdef WIN32
1581#else
Andy Green90c7cbc2011-01-27 06:26:52 +00001582 signal(SIGPIPE, sigpipe_handler);
Peter Hinz56885f32011-03-02 22:03:47 +00001583#endif
Andy Green90c7cbc2011-01-27 06:26:52 +00001584
1585
1586#ifdef LWS_OPENSSL_SUPPORT
1587
1588 /* basic openssl init */
1589
1590 SSL_library_init();
1591
1592 OpenSSL_add_all_algorithms();
1593 SSL_load_error_strings();
1594
Andy Green2e24da02011-03-05 16:12:04 +00001595 openssl_websocket_private_data_index =
Andy Green6901cb32011-02-21 08:06:47 +00001596 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
1597
Andy Green90c7cbc2011-01-27 06:26:52 +00001598 /*
1599 * Firefox insists on SSLv23 not SSLv3
1600 * Konq disables SSLv2 by default now, SSLv23 works
1601 */
1602
1603 method = (SSL_METHOD *)SSLv23_server_method();
1604 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08001605 lwsl_err("problem creating ssl method: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00001606 ERR_error_string(ERR_get_error(), ssl_err_buf));
1607 return NULL;
1608 }
Peter Hinz56885f32011-03-02 22:03:47 +00001609 context->ssl_ctx = SSL_CTX_new(method); /* create context */
1610 if (!context->ssl_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08001611 lwsl_err("problem creating ssl context: %s\n",
Andy Green90c7cbc2011-01-27 06:26:52 +00001612 ERR_error_string(ERR_get_error(), ssl_err_buf));
1613 return NULL;
1614 }
1615
David Galeanocc148e42013-01-10 10:18:59 +08001616#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08001617 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08001618#endif
David Galeano77a677c2013-01-10 10:14:12 +08001619 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08001620 SSL_CTX_set_cipher_list(context->ssl_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08001621
Andy Greena1ce6be2013-01-18 11:43:21 +08001622#ifndef LWS_NO_CLIENT
1623
Andy Green90c7cbc2011-01-27 06:26:52 +00001624 /* client context */
Andy Green6ee372f2012-04-09 15:09:01 +08001625
1626 if (port == CONTEXT_PORT_NO_LISTEN) {
Peter Hinz56885f32011-03-02 22:03:47 +00001627 method = (SSL_METHOD *)SSLv23_client_method();
1628 if (!method) {
Andy Green43db0452013-01-10 19:50:35 +08001629 lwsl_err("problem creating ssl method: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00001630 ERR_error_string(ERR_get_error(), ssl_err_buf));
1631 return NULL;
1632 }
1633 /* create context */
1634 context->ssl_client_ctx = SSL_CTX_new(method);
1635 if (!context->ssl_client_ctx) {
Andy Green43db0452013-01-10 19:50:35 +08001636 lwsl_err("problem creating ssl context: %s\n",
Peter Hinz56885f32011-03-02 22:03:47 +00001637 ERR_error_string(ERR_get_error(), ssl_err_buf));
1638 return NULL;
1639 }
Andy Green90c7cbc2011-01-27 06:26:52 +00001640
David Galeanocc148e42013-01-10 10:18:59 +08001641#ifdef SSL_OP_NO_COMPRESSION
David Galeanoc72f6f92013-01-10 10:11:57 +08001642 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_NO_COMPRESSION);
David Galeanocc148e42013-01-10 10:18:59 +08001643#endif
David Galeano77a677c2013-01-10 10:14:12 +08001644 SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
David Galeanof177f2a2013-01-10 10:15:19 +08001645 SSL_CTX_set_cipher_list(context->ssl_client_ctx, CIPHERS_LIST_STRING);
David Galeanoc72f6f92013-01-10 10:11:57 +08001646
Peter Hinz56885f32011-03-02 22:03:47 +00001647 /* openssl init for cert verification (for client sockets) */
David Galeano2f82be82013-01-09 16:25:54 +08001648 if (!ssl_ca_filepath) {
1649 if (!SSL_CTX_load_verify_locations(
1650 context->ssl_client_ctx, NULL,
1651 LWS_OPENSSL_CLIENT_CERTS))
Andy Green43db0452013-01-10 19:50:35 +08001652 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08001653 "Unable to load SSL Client certs from %s "
1654 "(set by --with-client-cert-dir= in configure) -- "
1655 " client ssl isn't going to work",
1656 LWS_OPENSSL_CLIENT_CERTS);
1657 } else
1658 if (!SSL_CTX_load_verify_locations(
1659 context->ssl_client_ctx, ssl_ca_filepath,
1660 NULL))
Andy Green43db0452013-01-10 19:50:35 +08001661 lwsl_err(
David Galeano2f82be82013-01-09 16:25:54 +08001662 "Unable to load SSL Client certs "
1663 "file from %s -- client ssl isn't "
1664 "going to work", ssl_ca_filepath);
Peter Hinz56885f32011-03-02 22:03:47 +00001665
1666 /*
1667 * callback allowing user code to load extra verification certs
1668 * helping the client to verify server identity
1669 */
1670
1671 context->protocols[0].callback(context, NULL,
1672 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
1673 context->ssl_client_ctx, NULL, 0);
Andy Green90c7cbc2011-01-27 06:26:52 +00001674 }
Andy Greena1ce6be2013-01-18 11:43:21 +08001675#endif
Andy Green6ee372f2012-04-09 15:09:01 +08001676
Andy Greenc6bf2c22011-02-20 11:10:47 +00001677 /* as a server, are we requiring clients to identify themselves? */
1678
1679 if (options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
1680
1681 /* absolutely require the client cert */
Andy Green6ee372f2012-04-09 15:09:01 +08001682
Peter Hinz56885f32011-03-02 22:03:47 +00001683 SSL_CTX_set_verify(context->ssl_ctx,
Andy Green6901cb32011-02-21 08:06:47 +00001684 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1685 OpenSSL_verify_callback);
Andy Greenc6bf2c22011-02-20 11:10:47 +00001686
1687 /*
1688 * give user code a chance to load certs into the server
1689 * allowing it to verify incoming client certs
1690 */
1691
Peter Hinz56885f32011-03-02 22:03:47 +00001692 context->protocols[0].callback(context, NULL,
Andy Greenc6bf2c22011-02-20 11:10:47 +00001693 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
Peter Hinz56885f32011-03-02 22:03:47 +00001694 context->ssl_ctx, NULL, 0);
Andy Greenc6bf2c22011-02-20 11:10:47 +00001695 }
1696
Peter Hinz56885f32011-03-02 22:03:47 +00001697 if (context->use_ssl) {
Andy Green90c7cbc2011-01-27 06:26:52 +00001698
1699 /* openssl init for server sockets */
1700
Andy Green3faa9c72010-11-08 17:03:03 +00001701 /* set the local certificate from CertFile */
David Galeano9b3d4b22013-01-10 10:11:21 +08001702 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
1703 ssl_cert_filepath);
Andy Green3faa9c72010-11-08 17:03:03 +00001704 if (n != 1) {
Andy Green43db0452013-01-10 19:50:35 +08001705 lwsl_err("problem getting cert '%s': %s\n",
Andy Green3faa9c72010-11-08 17:03:03 +00001706 ssl_cert_filepath,
1707 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00001708 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00001709 }
1710 /* set the private key from KeyFile */
Peter Hinz56885f32011-03-02 22:03:47 +00001711 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
1712 ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
Andy Green43db0452013-01-10 19:50:35 +08001713 lwsl_err("ssl problem getting key '%s': %s\n",
Andy Green018d8eb2010-11-08 21:04:23 +00001714 ssl_private_key_filepath,
1715 ERR_error_string(ERR_get_error(), ssl_err_buf));
Andy Greene92cd172011-01-19 13:11:55 +00001716 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00001717 }
1718 /* verify private key */
Peter Hinz56885f32011-03-02 22:03:47 +00001719 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
Andy Green43db0452013-01-10 19:50:35 +08001720 lwsl_err("Private SSL key doesn't match cert\n");
Andy Greene92cd172011-01-19 13:11:55 +00001721 return NULL;
Andy Green3faa9c72010-11-08 17:03:03 +00001722 }
1723
1724 /* SSL is happy and has a cert it's content with */
1725 }
1726#endif
Andy Greenb45993c2010-12-18 15:13:50 +00001727
Andy Greendf736162011-01-18 15:39:02 +00001728 /* selftest */
1729
1730 if (lws_b64_selftest())
Andy Greene92cd172011-01-19 13:11:55 +00001731 return NULL;
Andy Greendf736162011-01-18 15:39:02 +00001732
Andy Greena1ce6be2013-01-18 11:43:21 +08001733#ifndef LWS_NO_SERVER
Andy Greenb45993c2010-12-18 15:13:50 +00001734 /* set up our external listening socket we serve on */
Andy Green8f037e42010-12-19 22:13:26 +00001735
Andy Green4739e5c2011-01-22 12:51:57 +00001736 if (port) {
Andy Greena1ce6be2013-01-18 11:43:21 +08001737 extern int interface_to_sa(const char *ifname, struct sockaddr_in *addr, size_t addrlen);
1738 int sockfd;
Andy Green8f037e42010-12-19 22:13:26 +00001739
Andy Green4739e5c2011-01-22 12:51:57 +00001740 sockfd = socket(AF_INET, SOCK_STREAM, 0);
1741 if (sockfd < 0) {
Andy Greenf7609e92013-01-14 13:10:55 +08001742 lwsl_err("ERROR opening socket\n");
Andy Green4739e5c2011-01-22 12:51:57 +00001743 return NULL;
1744 }
Andy Green775c0dd2010-10-29 14:15:22 +01001745
Andy Green4739e5c2011-01-22 12:51:57 +00001746 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08001747 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
1748 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00001749
1750 /* Disable Nagle */
1751 opt = 1;
Andy Green6ee372f2012-04-09 15:09:01 +08001752 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
1753 (const void *)&opt, sizeof(opt));
Andy Green6c939552011-03-08 08:56:57 +00001754
Andy Green4739e5c2011-01-22 12:51:57 +00001755 bzero((char *) &serv_addr, sizeof(serv_addr));
1756 serv_addr.sin_family = AF_INET;
Peter Hinz56885f32011-03-02 22:03:47 +00001757 if (interf == NULL)
Andy Green32375b72011-02-19 08:32:53 +00001758 serv_addr.sin_addr.s_addr = INADDR_ANY;
1759 else
Peter Hinz56885f32011-03-02 22:03:47 +00001760 interface_to_sa(interf, &serv_addr,
Andy Green32375b72011-02-19 08:32:53 +00001761 sizeof(serv_addr));
Andy Green4739e5c2011-01-22 12:51:57 +00001762 serv_addr.sin_port = htons(port);
1763
1764 n = bind(sockfd, (struct sockaddr *) &serv_addr,
1765 sizeof(serv_addr));
1766 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001767 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Green8f037e42010-12-19 22:13:26 +00001768 port, n, errno);
Andy Green41c58032013-01-12 13:21:08 +08001769 close(sockfd);
Andy Green4739e5c2011-01-22 12:51:57 +00001770 return NULL;
1771 }
Andy Green0d338332011-02-12 11:57:43 +00001772
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001773 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08001774 if (wsi == NULL) {
1775 lwsl_err("Out of mem\n");
1776 close(sockfd);
1777 return NULL;
1778 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001779 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00001780 wsi->sock = sockfd;
Andy Greend6e09112011-03-05 16:12:15 +00001781 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00001782 wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
Andy Greendfb23042013-01-17 12:26:48 +08001783
1784 insert_wsi_socket_into_fds(context, wsi);
Andy Green0d338332011-02-12 11:57:43 +00001785
Andy Green65b0e912013-01-16 07:59:47 +08001786 context->listen_service_modulo = LWS_LISTEN_SERVICE_MODULO;
1787 context->listen_service_count = 0;
1788 context->listen_service_fd = sockfd;
1789
Andy Greena824d182013-01-15 20:52:29 +08001790 listen(sockfd, LWS_SOMAXCONN);
Andy Greenb3a614a2013-01-19 13:08:17 +08001791 lwsl_notice(" Listening on port %d\n", port);
Andy Green8f037e42010-12-19 22:13:26 +00001792 }
Andy Greena1ce6be2013-01-18 11:43:21 +08001793#endif
Andy Greenb45993c2010-12-18 15:13:50 +00001794
Andy Green6ee372f2012-04-09 15:09:01 +08001795 /*
1796 * drop any root privs for this process
1797 * to listen on port < 1023 we would have needed root, but now we are
1798 * listening, we don't want the power for anything else
1799 */
Peter Hinz56885f32011-03-02 22:03:47 +00001800#ifdef WIN32
1801#else
Andy Green3faa9c72010-11-08 17:03:03 +00001802 if (gid != -1)
1803 if (setgid(gid))
Andy Green43db0452013-01-10 19:50:35 +08001804 lwsl_warn("setgid: %s\n", strerror(errno));
Andy Green3faa9c72010-11-08 17:03:03 +00001805 if (uid != -1)
1806 if (setuid(uid))
Andy Green43db0452013-01-10 19:50:35 +08001807 lwsl_warn("setuid: %s\n", strerror(errno));
Peter Hinz56885f32011-03-02 22:03:47 +00001808#endif
Andy Greenb45993c2010-12-18 15:13:50 +00001809
1810 /* set up our internal broadcast trigger sockets per-protocol */
1811
Peter Hinz56885f32011-03-02 22:03:47 +00001812 for (context->count_protocols = 0;
1813 protocols[context->count_protocols].callback;
1814 context->count_protocols++) {
Andy Green2d1301e2011-05-24 10:14:41 +01001815
Andy Green43db0452013-01-10 19:50:35 +08001816 lwsl_parser(" Protocol: %s\n",
1817 protocols[context->count_protocols].name);
Andy Green2d1301e2011-05-24 10:14:41 +01001818
Peter Hinz56885f32011-03-02 22:03:47 +00001819 protocols[context->count_protocols].owning_server = context;
1820 protocols[context->count_protocols].protocol_index =
1821 context->count_protocols;
Andy Greenb45993c2010-12-18 15:13:50 +00001822
1823 fd = socket(AF_INET, SOCK_STREAM, 0);
1824 if (fd < 0) {
Andy Greenf7609e92013-01-14 13:10:55 +08001825 lwsl_err("ERROR opening socket\n");
Andy Greene92cd172011-01-19 13:11:55 +00001826 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00001827 }
Andy Green8f037e42010-12-19 22:13:26 +00001828
Andy Greenb45993c2010-12-18 15:13:50 +00001829 /* allow us to restart even if old sockets in TIME_WAIT */
Andy Green6ee372f2012-04-09 15:09:01 +08001830 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt,
1831 sizeof(opt));
Andy Greenb45993c2010-12-18 15:13:50 +00001832
1833 bzero((char *) &serv_addr, sizeof(serv_addr));
1834 serv_addr.sin_family = AF_INET;
1835 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
1836 serv_addr.sin_port = 0; /* pick the port for us */
1837
1838 n = bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
1839 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001840 lwsl_err("ERROR on binding to port %d (%d %d)\n",
Andy Greenb45993c2010-12-18 15:13:50 +00001841 port, n, errno);
Andy Greene92cd172011-01-19 13:11:55 +00001842 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00001843 }
1844
1845 slen = sizeof cli_addr;
1846 n = getsockname(fd, (struct sockaddr *)&cli_addr, &slen);
1847 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001848 lwsl_err("getsockname failed\n");
Andy Greene92cd172011-01-19 13:11:55 +00001849 return NULL;
Andy Greenb45993c2010-12-18 15:13:50 +00001850 }
Peter Hinz56885f32011-03-02 22:03:47 +00001851 protocols[context->count_protocols].broadcast_socket_port =
Andy Greenb45993c2010-12-18 15:13:50 +00001852 ntohs(cli_addr.sin_port);
1853 listen(fd, 5);
1854
Andy Green43db0452013-01-10 19:50:35 +08001855 lwsl_debug(" Protocol %s broadcast socket %d\n",
Peter Hinz56885f32011-03-02 22:03:47 +00001856 protocols[context->count_protocols].name,
Andy Greenb45993c2010-12-18 15:13:50 +00001857 ntohs(cli_addr.sin_port));
1858
Andy Green0d338332011-02-12 11:57:43 +00001859 /* dummy wsi per broadcast proxy socket */
1860
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001861 wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
Andy Green41c58032013-01-12 13:21:08 +08001862 if (wsi == NULL) {
1863 lwsl_err("Out of mem\n");
1864 close(fd);
1865 return NULL;
1866 }
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001867 memset(wsi, 0, sizeof (struct libwebsocket));
Andy Green0d338332011-02-12 11:57:43 +00001868 wsi->sock = fd;
1869 wsi->mode = LWS_CONNMODE_BROADCAST_PROXY_LISTENER;
Andy Greend6e09112011-03-05 16:12:15 +00001870 wsi->count_active_extensions = 0;
Andy Green0d338332011-02-12 11:57:43 +00001871 /* note which protocol we are proxying */
Peter Hinz56885f32011-03-02 22:03:47 +00001872 wsi->protocol_index_for_broadcast_proxy =
1873 context->count_protocols;
Andy Green0d338332011-02-12 11:57:43 +00001874
Andy Greendfb23042013-01-17 12:26:48 +08001875 insert_wsi_socket_into_fds(context, wsi);
Andy Greenb45993c2010-12-18 15:13:50 +00001876 }
1877
Andy Greena41314f2011-05-23 10:00:03 +01001878 /*
1879 * give all extensions a chance to create any per-context
1880 * allocations they need
1881 */
1882
1883 m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
1884 if (port)
1885 m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
Andrew Chambersd5512172012-05-20 08:17:09 +08001886
1887 if (extensions) {
1888 while (extensions->callback) {
Andy Green43db0452013-01-10 19:50:35 +08001889 lwsl_ext(" Extension: %s\n", extensions->name);
Aaron Zinman4550f1d2013-01-10 12:35:18 +08001890 extensions->callback(context, extensions, NULL,
1891 (enum libwebsocket_extension_callback_reasons)m,
1892 NULL, NULL, 0);
Andrew Chambersd5512172012-05-20 08:17:09 +08001893 extensions++;
1894 }
Andy Greena41314f2011-05-23 10:00:03 +01001895 }
1896
Peter Hinz56885f32011-03-02 22:03:47 +00001897 return context;
Andy Greene92cd172011-01-19 13:11:55 +00001898}
Andy Greenb45993c2010-12-18 15:13:50 +00001899
Andy Green4739e5c2011-01-22 12:51:57 +00001900
Andy Greened11a022011-01-20 10:23:50 +00001901#ifndef LWS_NO_FORK
1902
Andy Greene92cd172011-01-19 13:11:55 +00001903/**
1904 * libwebsockets_fork_service_loop() - Optional helper function forks off
1905 * a process for the websocket server loop.
Andy Green6964bb52011-01-23 16:50:33 +00001906 * You don't have to use this but if not, you
1907 * have to make sure you are calling
1908 * libwebsocket_service periodically to service
1909 * the websocket traffic
Peter Hinz56885f32011-03-02 22:03:47 +00001910 * @context: server context returned by creation function
Andy Greene92cd172011-01-19 13:11:55 +00001911 */
Andy Greenb45993c2010-12-18 15:13:50 +00001912
Andy Greene92cd172011-01-19 13:11:55 +00001913int
Peter Hinz56885f32011-03-02 22:03:47 +00001914libwebsockets_fork_service_loop(struct libwebsocket_context *context)
Andy Greene92cd172011-01-19 13:11:55 +00001915{
Andy Greene92cd172011-01-19 13:11:55 +00001916 int fd;
1917 struct sockaddr_in cli_addr;
1918 int n;
Andy Green3221f922011-02-12 13:14:11 +00001919 int p;
Andy Greenb45993c2010-12-18 15:13:50 +00001920
Andy Greened11a022011-01-20 10:23:50 +00001921 n = fork();
1922 if (n < 0)
1923 return n;
1924
1925 if (!n) {
1926
1927 /* main process context */
1928
Andy Green3221f922011-02-12 13:14:11 +00001929 /*
1930 * set up the proxy sockets to allow broadcast from
1931 * service process context
1932 */
1933
Peter Hinz56885f32011-03-02 22:03:47 +00001934 for (p = 0; p < context->count_protocols; p++) {
Andy Greened11a022011-01-20 10:23:50 +00001935 fd = socket(AF_INET, SOCK_STREAM, 0);
1936 if (fd < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001937 lwsl_err("Unable to create socket\n");
Andy Greened11a022011-01-20 10:23:50 +00001938 return -1;
1939 }
1940 cli_addr.sin_family = AF_INET;
1941 cli_addr.sin_port = htons(
Peter Hinz56885f32011-03-02 22:03:47 +00001942 context->protocols[p].broadcast_socket_port);
Andy Greened11a022011-01-20 10:23:50 +00001943 cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
1944 n = connect(fd, (struct sockaddr *)&cli_addr,
1945 sizeof cli_addr);
1946 if (n < 0) {
Andy Green43db0452013-01-10 19:50:35 +08001947 lwsl_err("Unable to connect to "
Andy Greened11a022011-01-20 10:23:50 +00001948 "broadcast socket %d, %s\n",
Andy Green3221f922011-02-12 13:14:11 +00001949 n, strerror(errno));
Andy Greened11a022011-01-20 10:23:50 +00001950 return -1;
1951 }
1952
Peter Hinz56885f32011-03-02 22:03:47 +00001953 context->protocols[p].broadcast_socket_user_fd = fd;
Andy Greened11a022011-01-20 10:23:50 +00001954 }
1955
Andy Greene92cd172011-01-19 13:11:55 +00001956 return 0;
Andy Greenb45993c2010-12-18 15:13:50 +00001957 }
1958
Artem Baguinski91531662011-12-14 22:14:03 +01001959#ifdef HAVE_SYS_PRCTL_H
Andy Greenb45993c2010-12-18 15:13:50 +00001960 /* we want a SIGHUP when our parent goes down */
1961 prctl(PR_SET_PDEATHSIG, SIGHUP);
Artem Baguinski91531662011-12-14 22:14:03 +01001962#endif
Andy Greenb45993c2010-12-18 15:13:50 +00001963
1964 /* in this forked process, sit and service websocket connections */
Andy Green8f037e42010-12-19 22:13:26 +00001965
Artem Baguinski91531662011-12-14 22:14:03 +01001966 while (1) {
Peter Hinz56885f32011-03-02 22:03:47 +00001967 if (libwebsocket_service(context, 1000))
Andy Green3928f612012-07-20 12:58:38 +08001968 break;
Andy Green5e8967a2012-10-17 20:10:44 +08001969//#ifndef HAVE_SYS_PRCTL_H
Artem Baguinski91531662011-12-14 22:14:03 +01001970/*
1971 * on systems without prctl() (i.e. anything but linux) we can notice that our
1972 * parent is dead if getppid() returns 1. FIXME apparently this is not true for
1973 * solaris, could remember ppid right after fork and wait for it to change.
1974 */
1975
1976 if (getppid() == 1)
1977 break;
Andy Green5e8967a2012-10-17 20:10:44 +08001978//#endif
Artem Baguinski91531662011-12-14 22:14:03 +01001979 }
1980
Andy Green8f037e42010-12-19 22:13:26 +00001981
Andy Green3928f612012-07-20 12:58:38 +08001982 return 1;
Andy Greenff95d7a2010-10-28 22:36:01 +01001983}
1984
Andy Greened11a022011-01-20 10:23:50 +00001985#endif
1986
Andy Greenb45993c2010-12-18 15:13:50 +00001987/**
1988 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +00001989 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +00001990 * @wsi: pointer to struct websocket you want to know the protocol of
1991 *
Andy Green8f037e42010-12-19 22:13:26 +00001992 *
1993 * This is useful to get the protocol to broadcast back to from inside
Andy Greenb45993c2010-12-18 15:13:50 +00001994 * the callback.
1995 */
Andy Greenab990e42010-10-31 12:42:52 +00001996
Andy Greenb45993c2010-12-18 15:13:50 +00001997const struct libwebsocket_protocols *
1998libwebsockets_get_protocol(struct libwebsocket *wsi)
1999{
2000 return wsi->protocol;
2001}
2002
2003/**
Andy Greene92cd172011-01-19 13:11:55 +00002004 * libwebsockets_broadcast() - Sends a buffer to the callback for all active
Andy Green8f037e42010-12-19 22:13:26 +00002005 * connections of the given protocol.
Andy Greenb45993c2010-12-18 15:13:50 +00002006 * @protocol: pointer to the protocol you will broadcast to all members of
2007 * @buf: buffer containing the data to be broadcase. NOTE: this has to be
Andy Green8f037e42010-12-19 22:13:26 +00002008 * allocated with LWS_SEND_BUFFER_PRE_PADDING valid bytes before
2009 * the pointer and LWS_SEND_BUFFER_POST_PADDING afterwards in the
2010 * case you are calling this function from callback context.
Andy Greenb45993c2010-12-18 15:13:50 +00002011 * @len: length of payload data in buf, starting from buf.
Andy Green8f037e42010-12-19 22:13:26 +00002012 *
2013 * This function allows bulk sending of a packet to every connection using
Andy Greenb45993c2010-12-18 15:13:50 +00002014 * the given protocol. It does not send the data directly; instead it calls
2015 * the callback with a reason type of LWS_CALLBACK_BROADCAST. If the callback
2016 * wants to actually send the data for that connection, the callback itself
2017 * should call libwebsocket_write().
2018 *
2019 * libwebsockets_broadcast() can be called from another fork context without
2020 * having to take any care about data visibility between the processes, it'll
2021 * "just work".
2022 */
2023
2024
2025int
Andy Green8f037e42010-12-19 22:13:26 +00002026libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
Andy Greenb45993c2010-12-18 15:13:50 +00002027 unsigned char *buf, size_t len)
2028{
Peter Hinz56885f32011-03-02 22:03:47 +00002029 struct libwebsocket_context *context = protocol->owning_server;
Andy Greenb45993c2010-12-18 15:13:50 +00002030 int n;
Andy Green6ee372f2012-04-09 15:09:01 +08002031 struct libwebsocket *wsi;
Andy Greenb45993c2010-12-18 15:13:50 +00002032
2033 if (!protocol->broadcast_socket_user_fd) {
2034 /*
Andy Greene92cd172011-01-19 13:11:55 +00002035 * We are either running unforked / flat, or we are being
2036 * called from poll thread context
Andy Greenb45993c2010-12-18 15:13:50 +00002037 * eg, from a callback. In that case don't use sockets for
2038 * broadcast IPC (since we can't open a socket connection to
2039 * a socket listening on our own thread) but directly do the
2040 * send action.
2041 *
2042 * Locking is not needed because we are by definition being
2043 * called in the poll thread context and are serialized.
2044 */
2045
Andy Greendfb23042013-01-17 12:26:48 +08002046 for (n = 0; n < context->fds_count; n++) {
Andy Greenb45993c2010-12-18 15:13:50 +00002047
Andy Greendfb23042013-01-17 12:26:48 +08002048 wsi = context->lws_lookup[context->fds[n].fd];
2049 if (!wsi)
2050 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00002051
Andy Greendfb23042013-01-17 12:26:48 +08002052 if (wsi->mode != LWS_CONNMODE_WS_SERVING)
2053 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00002054
Andy Greendfb23042013-01-17 12:26:48 +08002055 /*
2056 * never broadcast to non-established connections
2057 */
2058 if (wsi->state != WSI_STATE_ESTABLISHED)
2059 continue;
Andy Greenb45993c2010-12-18 15:13:50 +00002060
Andy Greendfb23042013-01-17 12:26:48 +08002061 /* only broadcast to guys using
2062 * requested protocol
2063 */
2064 if (wsi->protocol != protocol)
2065 continue;
Andy Green0d338332011-02-12 11:57:43 +00002066
Andy Green706961d2013-01-17 16:50:35 +08002067 user_callback_handle_rxflow(wsi->protocol->callback,
2068 context, wsi,
Andy Greendfb23042013-01-17 12:26:48 +08002069 LWS_CALLBACK_BROADCAST,
2070 wsi->user_space,
2071 buf, len);
Andy Greenb45993c2010-12-18 15:13:50 +00002072 }
2073
2074 return 0;
2075 }
2076
Andy Green0ca6a172010-12-19 20:50:01 +00002077 /*
2078 * We're being called from a different process context than the server
2079 * loop. Instead of broadcasting directly, we send our
2080 * payload on a socket to do the IPC; the server process will serialize
2081 * the broadcast action in its main poll() loop.
2082 *
2083 * There's one broadcast socket listening for each protocol supported
2084 * set up when the websocket server initializes
2085 */
2086
Andy Green6964bb52011-01-23 16:50:33 +00002087 n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
Andy Greenb45993c2010-12-18 15:13:50 +00002088
2089 return n;
2090}
Andy Green82c3d542011-03-07 21:16:31 +00002091
2092int
2093libwebsocket_is_final_fragment(struct libwebsocket *wsi)
2094{
2095 return wsi->final;
2096}
Alex Bligh49146db2011-11-07 17:19:25 +08002097
David Galeanoe2cf9922013-01-09 18:06:55 +08002098unsigned char
2099libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
2100{
2101 return wsi->rsv;
2102}
2103
Alex Bligh49146db2011-11-07 17:19:25 +08002104void *
2105libwebsocket_ensure_user_space(struct libwebsocket *wsi)
2106{
2107 /* allocate the per-connection user memory (if any) */
2108
2109 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
2110 wsi->user_space = malloc(
2111 wsi->protocol->per_session_data_size);
2112 if (wsi->user_space == NULL) {
Andy Green43db0452013-01-10 19:50:35 +08002113 lwsl_err("Out of memory for conn user space\n");
Alex Bligh49146db2011-11-07 17:19:25 +08002114 return NULL;
2115 }
Andy Green6ee372f2012-04-09 15:09:01 +08002116 memset(wsi->user_space, 0,
2117 wsi->protocol->per_session_data_size);
Alex Bligh49146db2011-11-07 17:19:25 +08002118 }
2119 return wsi->user_space;
2120}
Andy Green43db0452013-01-10 19:50:35 +08002121
Andy Greenacbaee62013-01-18 22:00:22 +08002122/**
2123 * lws_confirm_legit_wsi: returns nonzero if the wsi looks bad
2124 *
2125 * @wsi: struct libwebsocket to assess
2126 *
2127 * Performs consistecy checks on what the wsi claims and what the
2128 * polling arrays hold. This'll catch a closed wsi still in use.
2129 * Don't try to use on the listen (nonconnection) wsi as it will
2130 * fail it. Otherwise 0 return == wsi seems consistent.
2131 */
2132
2133int lws_confirm_legit_wsi(struct libwebsocket *wsi)
2134{
2135 struct libwebsocket_context *context;
2136
2137 if (!(wsi && wsi->protocol && wsi->protocol->owning_server))
2138 return 1;
2139
2140 context = wsi->protocol->owning_server;
2141
2142 if (!context)
2143 return 2;
2144
2145 if (!wsi->position_in_fds_table)
2146 return 3; /* position in fds table looks bad */
2147 if (context->fds[wsi->position_in_fds_table].fd != wsi->sock)
2148 return 4; /* pollfd entry does not wait on our socket descriptor */
2149 if (context->lws_lookup[wsi->sock] != wsi)
2150 return 5; /* lookup table does not agree with wsi */
2151
2152 return 0;
2153}
Andy Greende8f27a2013-01-12 09:17:42 +08002154
Andy Green0b319092013-01-19 11:17:56 +08002155static void lwsl_emit_stderr(int level, const char *line)
Andy Greende8f27a2013-01-12 09:17:42 +08002156{
Andy Green0b319092013-01-19 11:17:56 +08002157 char buf[300];
2158 struct timeval tv;
2159 int pos = 0;
2160 int n;
2161
2162 gettimeofday(&tv, NULL);
2163
2164 buf[0] = '\0';
2165 for (n = 0; n < LLL_COUNT; n++)
2166 if (level == (1 << n)) {
2167 pos = sprintf(buf, "[%ld:%04d] %s: ", tv.tv_sec,
2168 (int)(tv.tv_usec / 100), log_level_names[n]);
2169 break;
2170 }
2171
2172 fprintf(stderr, "%s%s", buf, line);
Andy Greende8f27a2013-01-12 09:17:42 +08002173}
2174
Andy Greenc11db202013-01-19 11:12:16 +08002175void lwsl_emit_syslog(int level, const char *line)
2176{
2177 int syslog_level = LOG_DEBUG;
2178
2179 switch (level) {
2180 case LLL_ERR:
2181 syslog_level = LOG_ERR;
2182 break;
2183 case LLL_WARN:
2184 syslog_level = LOG_WARNING;
2185 break;
2186 case LLL_NOTICE:
2187 syslog_level = LOG_NOTICE;
2188 break;
2189 case LLL_INFO:
2190 syslog_level = LOG_INFO;
2191 break;
2192 }
2193 syslog(syslog_level, line);
2194}
2195
Andy Green43db0452013-01-10 19:50:35 +08002196void _lws_log(int filter, const char *format, ...)
2197{
Andy Greende8f27a2013-01-12 09:17:42 +08002198 char buf[256];
Andy Green43db0452013-01-10 19:50:35 +08002199 va_list ap;
Andy Green43db0452013-01-10 19:50:35 +08002200
2201 if (!(log_level & filter))
2202 return;
2203
Andy Green43db0452013-01-10 19:50:35 +08002204 va_start(ap, format);
Andy Green0b319092013-01-19 11:17:56 +08002205 vsnprintf(buf, (sizeof buf), format, ap);
Andy Greende8f27a2013-01-12 09:17:42 +08002206 buf[(sizeof buf) - 1] = '\0';
2207 va_end(ap);
2208
Andy Green0b319092013-01-19 11:17:56 +08002209 lwsl_emit(filter, buf);
Andy Green43db0452013-01-10 19:50:35 +08002210}
2211
2212/**
2213 * lws_set_log_level() - Set the logging bitfield
2214 * @level: OR together the LLL_ debug contexts you want output from
Andy Greende8f27a2013-01-12 09:17:42 +08002215 * @log_emit_function: NULL to leave it as it is, or a user-supplied
2216 * function to perform log string emission instead of
2217 * the default stderr one.
Andy Green43db0452013-01-10 19:50:35 +08002218 *
Andy Greende8f27a2013-01-12 09:17:42 +08002219 * log level defaults to "err" and "warn" contexts enabled only and
2220 * emission on stderr.
Andy Green43db0452013-01-10 19:50:35 +08002221 */
2222
Andy Greende8f27a2013-01-12 09:17:42 +08002223void lws_set_log_level(int level, void (*log_emit_function)(const char *line))
Andy Green43db0452013-01-10 19:50:35 +08002224{
2225 log_level = level;
Andy Greende8f27a2013-01-12 09:17:42 +08002226 if (log_emit_function)
2227 lwsl_emit = log_emit_function;
Andy Green43db0452013-01-10 19:50:35 +08002228}