blob: e680481e6b2fc95e3cc3c8cd37b2dbb249a2b4fb [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 Green158e8042014-04-02 14:25:10 +08004 * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
Andy Greena0da8a82010-11-08 17:12:19 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301 USA
Andy Green05a0a7b2010-10-31 17:51:39 +000020 */
21
Andy Green7c212cc2010-11-08 20:20:42 +000022#include "private-libwebsockets.h"
Andy Greenff95d7a2010-10-28 22:36:01 +010023
Andy Green3d67f512014-04-03 07:29:50 +080024int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
Andy Green058ba812013-01-19 11:32:18 +080025static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
26
Andy Greenb5b23192013-02-11 17:13:32 +080027static const char * const log_level_names[] = {
Andy Green43db0452013-01-10 19:50:35 +080028 "ERR",
29 "WARN",
Andy Green7c19c342013-01-19 12:18:07 +080030 "NOTICE",
Andy Green43db0452013-01-10 19:50:35 +080031 "INFO",
32 "DEBUG",
33 "PARSER",
34 "HEADER",
35 "EXTENSION",
36 "CLIENT",
Andy Greend636e352013-01-29 12:36:17 +080037 "LATENCY",
Andy Green43db0452013-01-10 19:50:35 +080038};
39
Andy Green8f037e42010-12-19 22:13:26 +000040void
=?UTF-8?q?Joakim=20S=C3=B6derberg?=caf7e3d2015-06-25 17:51:07 +020041lws_free_wsi(struct libwebsocket *wsi)
42{
43 if (!wsi)
44 return;
45
46 /* Protocol user data may be allocated either internally by lws
47 * or by specified the user. Important we don't free external user data */
48 if (wsi->protocol && wsi->protocol->per_session_data_size
49 && wsi->user_space && !wsi->user_space_externally_allocated) {
50 lws_free(wsi->user_space);
51 }
52
53 lws_free2(wsi->rxflow_buffer);
54 lws_free2(wsi->truncated_send_malloc);
55
56 // TODO: Probably should handle the union structs in wsi->u here depending
57 // on connection mode as well. Too spaghetti for me to follow however...
58
59 lws_free_header_table(wsi);
60 lws_free(wsi);
61}
62
63void
Peter Hinz56885f32011-03-02 22:03:47 +000064libwebsocket_close_and_free_session(struct libwebsocket_context *context,
Andy Green687b0182011-02-26 11:04:01 +000065 struct libwebsocket *wsi, enum lws_close_status reason)
Andy Green251f6fa2010-11-03 11:13:06 +000066{
Andy Greene40aa9b2014-04-02 21:02:54 +080067 int n, m, ret;
Andy Green62c54d22011-02-14 09:14:25 +000068 int old_state;
Andy Green5e1fa172011-02-10 09:07:05 +000069 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
70 LWS_SEND_BUFFER_POST_PADDING];
Andy Greenc44159f2011-03-07 07:08:18 +000071 struct lws_tokens eff_buf;
Andy Greenb45993c2010-12-18 15:13:50 +000072
Andy Green4b6fbe12011-02-14 08:03:48 +000073 if (!wsi)
Andy Greenb45993c2010-12-18 15:13:50 +000074 return;
75
Andy Green62c54d22011-02-14 09:14:25 +000076 old_state = wsi->state;
Andy Green251f6fa2010-11-03 11:13:06 +000077
Andy Green408f5372015-04-12 08:17:26 +080078 if (wsi->socket_is_permanently_unusable ||
79 reason == LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY)
Andy Green1e499182014-10-16 08:23:46 +080080 goto just_kill_connection;
81
Andy Greena1a24d22014-04-10 14:25:24 +080082 switch (old_state) {
83 case WSI_STATE_DEAD_SOCKET:
Andy Green5e1fa172011-02-10 09:07:05 +000084 return;
85
Andy Green22524a62013-02-15 22:48:58 +080086 /* we tried the polite way... */
Andy Greena1a24d22014-04-10 14:25:24 +080087 case WSI_STATE_AWAITING_CLOSE_ACK:
Andy Green22524a62013-02-15 22:48:58 +080088 goto just_kill_connection;
89
Andy Greena1a24d22014-04-10 14:25:24 +080090 case WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE:
91 if (wsi->truncated_send_len) {
92 libwebsocket_callback_on_writable(context, wsi);
93 return;
94 }
95 lwsl_info("wsi %p completed WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
96 goto just_kill_connection;
97 default:
98 if (wsi->truncated_send_len) {
99 lwsl_info("wsi %p entering WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
100 wsi->state = WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE;
Andy Green9f02c5d2015-04-01 05:34:18 +0800101 libwebsocket_set_timeout(wsi, PENDING_FLUSH_STORED_SEND_BEFORE_CLOSE, 5);
Andy Greena1a24d22014-04-10 14:25:24 +0800102 return;
103 }
104 break;
105 }
106
Andy Green623a98d2013-01-21 11:04:23 +0800107 wsi->u.ws.close_reason = reason;
Andy Greenda527df2011-03-07 07:08:12 +0000108
Andy Green5dc62ea2013-09-20 20:26:12 +0800109 if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT ||
Andy Green0c8a8542015-10-28 19:50:41 +0800110 wsi->mode == LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE)
Andy Green5dc62ea2013-09-20 20:26:12 +0800111 goto just_kill_connection;
Andy Green5dc62ea2013-09-20 20:26:12 +0800112
Drew Noakes6a779772015-01-28 04:15:13 +0800113 if (wsi->mode == LWS_CONNMODE_HTTP_SERVING)
114 context->protocols[0].callback(context, wsi,
115 LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0);
116
kapejodce64fb02013-11-19 13:38:16 +0100117 if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) {
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100118 if (wsi->u.http.fd != LWS_INVALID_FILE) {
=?UTF-8?q?Joakim=20S=C3=B6derberg?=caf7e3d2015-06-25 17:51:07 +0200119 // TODO: If we're just closing with LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY this file descriptor might leak?
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100120 lwsl_debug("closing http file\n");
Andy Green158e8042014-04-02 14:25:10 +0800121 compatible_file_close(wsi->u.http.fd);
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100122 wsi->u.http.fd = LWS_INVALID_FILE;
kapejodce64fb02013-11-19 13:38:16 +0100123 context->protocols[0].callback(context, wsi,
124 LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0);
125 }
Andy Greenb8b247d2013-01-22 07:20:08 +0800126 }
127
Andy Greenda527df2011-03-07 07:08:12 +0000128 /*
Andy Green68b45042011-05-25 21:41:57 +0100129 * are his extensions okay with him closing? Eg he might be a mux
130 * parent and just his ch1 aspect is closing?
131 */
Andy Greene40aa9b2014-04-02 21:02:54 +0800132
133 if (lws_ext_callback_for_each_active(wsi,
134 LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE, NULL, 0) > 0) {
135 lwsl_ext("extension vetoed close\n");
136 return;
Andy Green68b45042011-05-25 21:41:57 +0100137 }
138
Andy Green68b45042011-05-25 21:41:57 +0100139 /*
Andy Greenc44159f2011-03-07 07:08:18 +0000140 * flush any tx pending from extensions, since we may send close packet
141 * if there are problems with send, just nuke the connection
142 */
143
Andy Greene40aa9b2014-04-02 21:02:54 +0800144 do {
Andy Greenc44159f2011-03-07 07:08:18 +0000145 ret = 0;
146 eff_buf.token = NULL;
147 eff_buf.token_len = 0;
148
149 /* show every extension the new incoming data */
150
Andy Greene40aa9b2014-04-02 21:02:54 +0800151 m = lws_ext_callback_for_each_active(wsi,
152 LWS_EXT_CALLBACK_FLUSH_PENDING_TX, &eff_buf, 0);
153 if (m < 0) {
154 lwsl_ext("Extension reports fatal error\n");
155 goto just_kill_connection;
Andy Greenc44159f2011-03-07 07:08:18 +0000156 }
Andy Greene40aa9b2014-04-02 21:02:54 +0800157 if (m)
158 /*
159 * at least one extension told us he has more
160 * to spill, so we will go around again after
161 */
162 ret = 1;
Andy Greenc44159f2011-03-07 07:08:18 +0000163
164 /* assuming they left us something to send, send it */
165
166 if (eff_buf.token_len)
167 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
Andy Greenfc7c5e42013-02-23 10:50:10 +0800168 eff_buf.token_len) != eff_buf.token_len) {
Andy Greenb5b23192013-02-11 17:13:32 +0800169 lwsl_debug("close: ext spill failed\n");
Andy Greenc44159f2011-03-07 07:08:18 +0000170 goto just_kill_connection;
Andy Green0303db42013-01-17 14:46:43 +0800171 }
Andy Greene40aa9b2014-04-02 21:02:54 +0800172 } while (ret);
Andy Greenc44159f2011-03-07 07:08:18 +0000173
174 /*
Drew Noakesefe10b02014-10-23 15:34:26 +0100175 * signal we are closing, libwebsocket_write will
Andy Greenda527df2011-03-07 07:08:12 +0000176 * add any necessary version-specific stuff. If the write fails,
177 * no worries we are closing anyway. If we didn't initiate this
178 * close, then our state has been changed to
179 * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
180 *
181 * Likewise if it's a second call to close this connection after we
182 * sent the close indication to the peer already, we are in state
183 * WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
184 */
185
186 if (old_state == WSI_STATE_ESTABLISHED &&
Andy Green8ec78022015-03-25 01:53:58 +0800187 reason != LWS_CLOSE_STATUS_NOSTATUS &&
188 reason != LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY) {
Andy Green66a16f32011-05-24 22:07:45 +0100189
Andy Green43db0452013-01-10 19:50:35 +0800190 lwsl_debug("sending close indication...\n");
Andy Green66a16f32011-05-24 22:07:45 +0100191
Andy Greenfdd305a2013-02-11 14:32:48 +0800192 /* make valgrind happy */
Andy Greenb5b23192013-02-11 17:13:32 +0800193 memset(buf, 0, sizeof(buf));
194 n = libwebsocket_write(wsi,
195 &buf[LWS_SEND_BUFFER_PRE_PADDING + 2],
Andy Greenda527df2011-03-07 07:08:12 +0000196 0, LWS_WRITE_CLOSE);
Andy Greenfc7c5e42013-02-23 10:50:10 +0800197 if (n >= 0) {
Andy Greenda527df2011-03-07 07:08:12 +0000198 /*
199 * we have sent a nice protocol level indication we
200 * now wish to close, we should not send anything more
201 */
202
203 wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
204
Andy Greenb5b23192013-02-11 17:13:32 +0800205 /*
206 * ...and we should wait for a reply for a bit
207 * out of politeness
208 */
Andy Greenda527df2011-03-07 07:08:12 +0000209
210 libwebsocket_set_timeout(wsi,
Andy Green0303db42013-01-17 14:46:43 +0800211 PENDING_TIMEOUT_CLOSE_ACK, 1);
Andy Greenda527df2011-03-07 07:08:12 +0000212
Andy Green43db0452013-01-10 19:50:35 +0800213 lwsl_debug("sent close indication, awaiting ack\n");
Andy Greenda527df2011-03-07 07:08:12 +0000214
215 return;
216 }
217
Andy Greenb5b23192013-02-11 17:13:32 +0800218 lwsl_info("close: sending close packet failed, hanging up\n");
Andy Green0303db42013-01-17 14:46:43 +0800219
Andy Greenda527df2011-03-07 07:08:12 +0000220 /* else, the send failed and we should just hang up */
221 }
222
Andy Greenc44159f2011-03-07 07:08:18 +0000223just_kill_connection:
Andy Green66a16f32011-05-24 22:07:45 +0100224
Andy Greenb5b23192013-02-11 17:13:32 +0800225 lwsl_debug("close: just_kill_connection\n");
Andy Green66a16f32011-05-24 22:07:45 +0100226
Andy Greenda527df2011-03-07 07:08:12 +0000227 /*
228 * we won't be servicing or receiving anything further from this guy
Andy Greendfb23042013-01-17 12:26:48 +0800229 * delete socket from the internal poll list if still present
Andy Greenda527df2011-03-07 07:08:12 +0000230 */
Andy Green4b6fbe12011-02-14 08:03:48 +0000231
Andy Green52815602015-01-29 08:36:18 +0800232 lws_ssl_remove_wsi_from_buffered_list(context, wsi);
233
Andy Green1963c9a2015-10-15 07:39:33 +0800234 // checking return redundant since we anyway close
Andy Greendfb23042013-01-17 12:26:48 +0800235 remove_wsi_socket_from_fds(context, wsi);
Andy Green4b6fbe12011-02-14 08:03:48 +0000236
Andy Green251f6fa2010-11-03 11:13:06 +0000237 wsi->state = WSI_STATE_DEAD_SOCKET;
Alejandro Meryac3ec392014-12-05 00:09:20 +0100238
239 lws_free2(wsi->rxflow_buffer);
=?UTF-8?q?Joakim=20S=C3=B6derberg?=caf7e3d2015-06-25 17:51:07 +0200240 lws_free_header_table(wsi);
Alejandro Meryac3ec392014-12-05 00:09:20 +0100241
Andy Greenb5b23192013-02-11 17:13:32 +0800242 if ((old_state == WSI_STATE_ESTABLISHED ||
243 wsi->mode == LWS_CONNMODE_WS_SERVING ||
Andy Green3ee9b312013-02-12 12:52:39 +0800244 wsi->mode == LWS_CONNMODE_WS_CLIENT)) {
245
Alejandro Meryac3ec392014-12-05 00:09:20 +0100246 lws_free2(wsi->u.ws.rx_user_buffer);
Andy Green024eb6c2014-10-08 12:00:53 +0800247
Andy Green2764eba2013-12-09 14:16:17 +0800248 if (wsi->truncated_send_malloc) {
Andy Green1f4267b2013-10-17 08:09:19 +0800249 /* not going to be completed... nuke it */
Alejandro Meryac3ec392014-12-05 00:09:20 +0100250 lws_free2(wsi->truncated_send_malloc);
Andy Greene254d952014-03-23 11:41:15 +0800251 wsi->truncated_send_len = 0;
Andy Green1f4267b2013-10-17 08:09:19 +0800252 }
Andy Green82bac6b2014-08-24 14:39:19 +0800253 if (wsi->u.ws.ping_payload_buf) {
Alejandro Meryac3ec392014-12-05 00:09:20 +0100254 lws_free2(wsi->u.ws.ping_payload_buf);
Andy Green82bac6b2014-08-24 14:39:19 +0800255 wsi->u.ws.ping_payload_alloc = 0;
256 wsi->u.ws.ping_payload_len = 0;
Andy Green2fd6e6f2015-03-24 21:07:01 +0800257 wsi->u.ws.ping_pending_flag = 0;
Andy Green82bac6b2014-08-24 14:39:19 +0800258 }
Andy Green54495112013-02-06 21:10:16 +0900259 }
260
Andy Green4b6fbe12011-02-14 08:03:48 +0000261 /* tell the user it's all over for this guy */
262
Andy Greend4302732011-02-28 07:45:29 +0000263 if (wsi->protocol && wsi->protocol->callback &&
Andy Green6ee372f2012-04-09 15:09:01 +0800264 ((old_state == WSI_STATE_ESTABLISHED) ||
265 (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
Stefan Schuermansb944cc12014-09-08 14:01:58 +0800266 (old_state == WSI_STATE_AWAITING_CLOSE_ACK) ||
267 (old_state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE))) {
Andy Green43db0452013-01-10 19:50:35 +0800268 lwsl_debug("calling back CLOSED\n");
Peter Hinz56885f32011-03-02 22:03:47 +0000269 wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
Andy Greene77ddd82010-11-13 10:03:47 +0000270 wsi->user_space, NULL, 0);
Andy Green158e8042014-04-02 14:25:10 +0800271 } else if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) {
Niall T. Davidsondb761be2013-06-29 10:16:18 +0800272 lwsl_debug("calling back CLOSED_HTTP\n");
273 context->protocols[0].callback(context, wsi,
274 LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0 );
Andy Greenb7a721f2015-04-27 19:07:38 +0800275 } else if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY ||
276 wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT) {
Andy Greenbb90f9b2015-04-16 19:55:42 +0800277 lwsl_debug("Connection closed before server reply\n");
278 context->protocols[0].callback(context, wsi,
279 LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
280 wsi->user_space, NULL, 0 );
Andy Greencc012472011-11-07 19:53:23 +0800281 } else
Andy Greenbb90f9b2015-04-16 19:55:42 +0800282 lwsl_debug("not calling back closed mode=%d state=%d\n",
283 wsi->mode, old_state);
Andy Green251f6fa2010-11-03 11:13:06 +0000284
Andy Greenef660a92011-03-06 10:29:38 +0000285 /* deallocate any active extension contexts */
Andy Greene40aa9b2014-04-02 21:02:54 +0800286
287 if (lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_DESTROY, NULL, 0) < 0)
288 lwsl_warn("extension destruction failed\n");
289#ifndef LWS_NO_EXTENSIONS
290 for (n = 0; n < wsi->count_active_extensions; n++)
Alejandro Mery6ff28242014-12-04 23:59:35 +0100291 lws_free(wsi->active_extensions_user[n]);
Andy Greene40aa9b2014-04-02 21:02:54 +0800292#endif
Andy Greena41314f2011-05-23 10:00:03 +0100293 /*
294 * inform all extensions in case they tracked this guy out of band
295 * even though not active on him specifically
296 */
Andy Greene40aa9b2014-04-02 21:02:54 +0800297 if (lws_ext_callback_for_each_extension_type(context, wsi,
298 LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING, NULL, 0) < 0)
299 lwsl_warn("ext destroy wsi failed\n");
Andy Greena41314f2011-05-23 10:00:03 +0100300
Andy Green43db0452013-01-10 19:50:35 +0800301/* lwsl_info("closing fd=%d\n", wsi->sock); */
Andy Green251f6fa2010-11-03 11:13:06 +0000302
Andy Greencdb9bf92014-04-12 10:07:02 +0800303 if (!lws_ssl_close(wsi) && wsi->sock >= 0) {
304 n = shutdown(wsi->sock, SHUT_RDWR);
305 if (n)
306 lwsl_debug("closing: shutdown ret %d\n", LWS_ERRNO);
Andy Green3fc2c652013-01-14 15:35:02 +0800307
Andy Greencdb9bf92014-04-12 10:07:02 +0800308 n = compatible_close(wsi->sock);
309 if (n)
310 lwsl_debug("closing: close ret %d\n", LWS_ERRNO);
Andy Green3faa9c72010-11-08 17:03:03 +0000311 }
Andy Green76b6ea12014-02-15 19:25:50 +0800312
313 /* outermost destroy notification for wsi (user_space still intact) */
314 context->protocols[0].callback(context, wsi,
315 LWS_CALLBACK_WSI_DESTROY, wsi->user_space, NULL, 0);
316
=?UTF-8?q?Joakim=20S=C3=B6derberg?=caf7e3d2015-06-25 17:51:07 +0200317 lws_free_wsi(wsi);
Andy Green251f6fa2010-11-03 11:13:06 +0000318}
319
Andy Green7e37d102015-01-28 21:03:49 +0800320LWS_VISIBLE int
321libwebsockets_get_addresses(struct libwebsocket_context *context,
322 void *ads, char *name, int name_len,
323 char *rip, int rip_len)
324{
325 struct addrinfo ai, *res;
Andrejs Haninsf94dd2e2015-10-15 13:02:03 +0300326 struct sockaddr_in addr4;
Andy Green7e37d102015-01-28 21:03:49 +0800327
328 rip[0] = '\0';
329 name[0] = '\0';
Andrejs Haninsf94dd2e2015-10-15 13:02:03 +0300330 addr4.sin_family = AF_UNSPEC;
Andy Green7e37d102015-01-28 21:03:49 +0800331
332#ifdef LWS_USE_IPV6
333 if (LWS_IPV6_ENABLED(context)) {
334 if (!lws_plat_inet_ntop(AF_INET6, &((struct sockaddr_in6 *)ads)->sin6_addr, rip, rip_len)) {
335 lwsl_err("inet_ntop", strerror(LWS_ERRNO));
336 return -1;
337 }
338
339 // Strip off the IPv4 to IPv6 header if one exists
340 if (strncmp(rip, "::ffff:", 7) == 0)
341 memmove(rip, rip + 7, strlen(rip) - 6);
342
343 getnameinfo((struct sockaddr *)ads,
344 sizeof(struct sockaddr_in6), name,
345 name_len, NULL, 0, 0);
346
347 return 0;
348 } else
349#endif
350 {
Andrejs Haninsf94dd2e2015-10-15 13:02:03 +0300351 struct addrinfo *result;
352
Andy Green7e37d102015-01-28 21:03:49 +0800353 memset(&ai, 0, sizeof ai);
354 ai.ai_family = PF_UNSPEC;
355 ai.ai_socktype = SOCK_STREAM;
356 ai.ai_flags = AI_CANONNAME;
357
358 if (getnameinfo((struct sockaddr *)ads,
359 sizeof(struct sockaddr_in),
360 name, name_len, NULL, 0, 0))
361 return -1;
362
363 if (!rip)
364 return 0;
365
Andrejs Haninsf94dd2e2015-10-15 13:02:03 +0300366 if (getaddrinfo(name, NULL, &ai, &result))
Andy Green7e37d102015-01-28 21:03:49 +0800367 return -1;
368
Andrejs Haninsf94dd2e2015-10-15 13:02:03 +0300369 res = result;
370 while (addr4.sin_family == AF_UNSPEC && res) {
Andy Green7e37d102015-01-28 21:03:49 +0800371 switch (res->ai_family) {
372 case AF_INET:
Andrejs Haninsf94dd2e2015-10-15 13:02:03 +0300373 addr4.sin_addr = ((struct sockaddr_in *)res->ai_addr)->sin_addr;
374 addr4.sin_family = AF_INET;
Andy Green7e37d102015-01-28 21:03:49 +0800375 break;
376 }
377
378 res = res->ai_next;
379 }
Andrejs Haninsf94dd2e2015-10-15 13:02:03 +0300380 freeaddrinfo(result);
Andy Green7e37d102015-01-28 21:03:49 +0800381 }
382
Andrejs Haninsf94dd2e2015-10-15 13:02:03 +0300383 if (addr4.sin_family == AF_UNSPEC)
Andy Green7e37d102015-01-28 21:03:49 +0800384 return -1;
385
Andrejs Haninsf94dd2e2015-10-15 13:02:03 +0300386 lws_plat_inet_ntop(AF_INET, &addr4.sin_addr, rip, rip_len);
Andy Green7e37d102015-01-28 21:03:49 +0800387
388 return 0;
389}
390
Andy Green07034092011-02-13 08:37:12 +0000391/**
392 * libwebsockets_get_peer_addresses() - Get client address information
Andy Greenaaf0b9f2013-01-30 08:12:20 +0800393 * @context: Libwebsockets context
394 * @wsi: Local struct libwebsocket associated with
Andy Green07034092011-02-13 08:37:12 +0000395 * @fd: Connection socket descriptor
396 * @name: Buffer to take client address name
397 * @name_len: Length of client address name buffer
Drew Noakesefe10b02014-10-23 15:34:26 +0100398 * @rip: Buffer to take client address IP dotted quad
Andy Green07034092011-02-13 08:37:12 +0000399 * @rip_len: Length of client address IP buffer
400 *
401 * This function fills in @name and @rip with the name and IP of
Andy Green6ee372f2012-04-09 15:09:01 +0800402 * the client connected with socket descriptor @fd. Names may be
403 * truncated if there is not enough room. If either cannot be
404 * determined, they will be returned as valid zero-length strings.
Andy Green07034092011-02-13 08:37:12 +0000405 */
406
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800407LWS_VISIBLE void
Andy Greenaaf0b9f2013-01-30 08:12:20 +0800408libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
409 struct libwebsocket *wsi, int fd, char *name, int name_len,
Andy Green07034092011-02-13 08:37:12 +0000410 char *rip, int rip_len)
411{
Bob Robertsac049112013-04-25 09:16:30 +0800412 socklen_t len;
Andy Green055f2972014-03-24 16:09:25 +0800413#ifdef LWS_USE_IPV6
James Devine3f13ea22014-03-24 16:09:25 +0800414 struct sockaddr_in6 sin6;
415#endif
416 struct sockaddr_in sin4;
James Devine3f13ea22014-03-24 16:09:25 +0800417 int ret = -1;
Andy Green7e37d102015-01-28 21:03:49 +0800418 void *p;
Andy Green07034092011-02-13 08:37:12 +0000419
420 rip[0] = '\0';
421 name[0] = '\0';
422
Andy Greenaaf0b9f2013-01-30 08:12:20 +0800423 lws_latency_pre(context, wsi);
424
Andy Green055f2972014-03-24 16:09:25 +0800425#ifdef LWS_USE_IPV6
James Devine3f13ea22014-03-24 16:09:25 +0800426 if (LWS_IPV6_ENABLED(context)) {
James Devine3f13ea22014-03-24 16:09:25 +0800427 len = sizeof(sin6);
Andy Green7e37d102015-01-28 21:03:49 +0800428 p = &sin6;
James Devine3f13ea22014-03-24 16:09:25 +0800429 } else
Peter Hinzbb45a902011-03-10 18:14:01 +0000430#endif
James Devine3f13ea22014-03-24 16:09:25 +0800431 {
432 len = sizeof(sin4);
Andy Green7e37d102015-01-28 21:03:49 +0800433 p = &sin4;
Andy Green07034092011-02-13 08:37:12 +0000434 }
Andy Greenaaf0b9f2013-01-30 08:12:20 +0800435
Andy Green7e37d102015-01-28 21:03:49 +0800436 if (getpeername(fd, p, &len) < 0) {
437 lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
438 goto bail;
439 }
440
441 ret = libwebsockets_get_addresses(context, p, name, name_len, rip, rip_len);
442
Andy Greenaaf0b9f2013-01-30 08:12:20 +0800443bail:
444 lws_latency(context, wsi, "libwebsockets_get_peer_addresses", ret, 1);
Andy Green07034092011-02-13 08:37:12 +0000445}
Andy Green9f990342011-02-12 11:57:45 +0000446
Andy Greend88146d2013-01-22 12:40:35 +0800447/**
Andy Greenb5b23192013-02-11 17:13:32 +0800448 * libwebsocket_context_user() - get the user data associated with the context
Andy Greend88146d2013-01-22 12:40:35 +0800449 * @context: Websocket context
450 *
451 * This returns the optional user allocation that can be attached to
452 * the context the sockets live in at context_create time. It's a way
453 * to let all sockets serviced in the same context share data without
454 * using globals statics in the user code.
455 */
Alon Levy0291eb32012-10-19 11:21:56 +0200456LWS_EXTERN void *
457libwebsocket_context_user(struct libwebsocket_context *context)
458{
Andy Greenb5b23192013-02-11 17:13:32 +0800459 return context->user_space;
Alon Levy0291eb32012-10-19 11:21:56 +0200460}
461
Andy Greene92cd172011-01-19 13:11:55 +0000462
Andy Greenbe93fef2011-02-14 20:25:43 +0000463/**
Andy Greene39e6ef2014-02-15 16:36:38 +0800464 * libwebsocket_callback_all_protocol() - Callback all connections using
465 * the given protocol with the given reason
466 *
467 * @protocol: Protocol whose connections will get callbacks
468 * @reason: Callback reason index
469 */
470
471LWS_VISIBLE int
472libwebsocket_callback_all_protocol(
473 const struct libwebsocket_protocols *protocol, int reason)
474{
475 struct libwebsocket_context *context = protocol->owning_server;
476 int n;
477 struct libwebsocket *wsi;
478
479 for (n = 0; n < context->fds_count; n++) {
Bud Davis229bfec2015-01-30 10:13:01 +0800480 wsi = wsi_from_fd(context, context->fds[n].fd);
Andy Greene39e6ef2014-02-15 16:36:38 +0800481 if (!wsi)
482 continue;
483 if (wsi->protocol == protocol)
484 protocol->callback(context, wsi,
485 reason, wsi->user_space, NULL, 0);
486 }
487
488 return 0;
489}
490
491/**
Andy Greenbe93fef2011-02-14 20:25:43 +0000492 * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
493 *
494 * You will not need this unless you are doing something special
495 *
496 * @wsi: Websocket connection instance
497 * @reason: timeout reason
498 * @secs: how many seconds
499 */
500
Craig McQueene7fd8b12014-02-19 09:24:17 +1100501LWS_VISIBLE void
Andy Greenbe93fef2011-02-14 20:25:43 +0000502libwebsocket_set_timeout(struct libwebsocket *wsi,
503 enum pending_timeout reason, int secs)
504{
Patrick Gansterer92792b42014-02-26 21:37:31 +0100505 time_t now;
Andy Greenbe93fef2011-02-14 20:25:43 +0000506
Patrick Gansterer92792b42014-02-26 21:37:31 +0100507 time(&now);
Andy Greenbe93fef2011-02-14 20:25:43 +0000508
Patrick Gansterer92792b42014-02-26 21:37:31 +0100509 wsi->pending_timeout_limit = now + secs;
Andy Greenbe93fef2011-02-14 20:25:43 +0000510 wsi->pending_timeout = reason;
511}
512
Andy Greena6cbece2011-01-27 20:06:03 +0000513
514/**
515 * libwebsocket_get_socket_fd() - returns the socket file descriptor
516 *
517 * You will not need this unless you are doing something special
518 *
519 * @wsi: Websocket connection instance
520 */
521
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800522LWS_VISIBLE int
Andy Greena6cbece2011-01-27 20:06:03 +0000523libwebsocket_get_socket_fd(struct libwebsocket *wsi)
524{
525 return wsi->sock;
526}
527
Andy Greend636e352013-01-29 12:36:17 +0800528#ifdef LWS_LATENCY
529void
Andy Greenb5b23192013-02-11 17:13:32 +0800530lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi,
531 const char *action, int ret, int completed)
Andy Greend636e352013-01-29 12:36:17 +0800532{
Patrick Gansterer92792b42014-02-26 21:37:31 +0100533 unsigned long long u;
Andy Greend636e352013-01-29 12:36:17 +0800534 char buf[256];
535
Patrick Gansterer92792b42014-02-26 21:37:31 +0100536 u = time_in_microseconds();
Andy Greend636e352013-01-29 12:36:17 +0800537
Andy Greenbfaea952014-03-31 11:01:32 +0800538 if (!action) {
Andy Greend636e352013-01-29 12:36:17 +0800539 wsi->latency_start = u;
540 if (!wsi->action_start)
541 wsi->action_start = u;
Andy Greenbfaea952014-03-31 11:01:32 +0800542 return;
Andy Greend636e352013-01-29 12:36:17 +0800543 }
Andy Greenbfaea952014-03-31 11:01:32 +0800544 if (completed) {
545 if (wsi->action_start == wsi->latency_start)
546 sprintf(buf,
Cong Ma10da1172014-07-05 10:50:47 +0800547 "Completion first try lat %lluus: %p: ret %d: %s\n",
Andy Greenbfaea952014-03-31 11:01:32 +0800548 u - wsi->latency_start,
549 (void *)wsi, ret, action);
550 else
551 sprintf(buf,
Cong Ma10da1172014-07-05 10:50:47 +0800552 "Completion %lluus: lat %lluus: %p: ret %d: %s\n",
Andy Greenbfaea952014-03-31 11:01:32 +0800553 u - wsi->action_start,
554 u - wsi->latency_start,
555 (void *)wsi, ret, action);
556 wsi->action_start = 0;
557 } else
Cong Ma10da1172014-07-05 10:50:47 +0800558 sprintf(buf, "lat %lluus: %p: ret %d: %s\n",
Andy Greenbfaea952014-03-31 11:01:32 +0800559 u - wsi->latency_start, (void *)wsi, ret, action);
560
561 if (u - wsi->latency_start > context->worst_latency) {
562 context->worst_latency = u - wsi->latency_start;
563 strcpy(context->worst_latency_info, buf);
564 }
565 lwsl_latency("%s", buf);
Andy Greend636e352013-01-29 12:36:17 +0800566}
567#endif
568
Andy Green706961d2013-01-17 16:50:35 +0800569
Andy Green706961d2013-01-17 16:50:35 +0800570
Andy Green90c7cbc2011-01-27 06:26:52 +0000571/**
572 * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
Drew Noakesefe10b02014-10-23 15:34:26 +0100573 * received packets.
Andy Green90c7cbc2011-01-27 06:26:52 +0000574 *
575 * If the output side of a server process becomes choked, this allows flow
576 * control for the input side.
577 *
578 * @wsi: Websocket connection instance to get callback for
579 * @enable: 0 = disable read servicing for this connection, 1 = enable
580 */
581
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800582LWS_VISIBLE int
Andy Green90c7cbc2011-01-27 06:26:52 +0000583libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
584{
Andy Green024eb6c2014-10-08 12:00:53 +0800585 if (enable == (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW))
Andy Greenca0a1292013-03-16 11:24:23 +0800586 return 0;
587
588 lwsl_info("libwebsocket_rx_flow_control(0x%p, %d)\n", wsi, enable);
Andy Green024eb6c2014-10-08 12:00:53 +0800589 wsi->rxflow_change_to = LWS_RXFLOW_PENDING_CHANGE | !!enable;
Andy Green90c7cbc2011-01-27 06:26:52 +0000590
Andy Green706961d2013-01-17 16:50:35 +0800591 return 0;
Andy Green90c7cbc2011-01-27 06:26:52 +0000592}
593
Andy Greenb55451c2013-03-16 12:32:27 +0800594/**
595 * libwebsocket_rx_flow_allow_all_protocol() - Allow all connections with this protocol to receive
596 *
597 * When the user server code realizes it can accept more input, it can
598 * call this to have the RX flow restriction removed from all connections using
599 * the given protocol.
600 *
601 * @protocol: all connections using this protocol will be allowed to receive
602 */
603
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800604LWS_VISIBLE void
Andy Greenb55451c2013-03-16 12:32:27 +0800605libwebsocket_rx_flow_allow_all_protocol(
606 const struct libwebsocket_protocols *protocol)
607{
608 struct libwebsocket_context *context = protocol->owning_server;
609 int n;
610 struct libwebsocket *wsi;
611
612 for (n = 0; n < context->fds_count; n++) {
Bud Davis229bfec2015-01-30 10:13:01 +0800613 wsi = wsi_from_fd(context, context->fds[n].fd);
Andy Greenb55451c2013-03-16 12:32:27 +0800614 if (!wsi)
615 continue;
616 if (wsi->protocol == protocol)
617 libwebsocket_rx_flow_control(wsi, LWS_RXFLOW_ALLOW);
618 }
619}
620
Andy Green706961d2013-01-17 16:50:35 +0800621
Andy Green2ac5a6f2011-01-28 10:00:18 +0000622/**
623 * libwebsocket_canonical_hostname() - returns this host's hostname
624 *
625 * This is typically used by client code to fill in the host parameter
626 * when making a client connection. You can only call it after the context
627 * has been created.
628 *
Peter Hinz56885f32011-03-02 22:03:47 +0000629 * @context: Websocket context
Andy Green2ac5a6f2011-01-28 10:00:18 +0000630 */
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800631LWS_VISIBLE extern const char *
Peter Hinz56885f32011-03-02 22:03:47 +0000632libwebsocket_canonical_hostname(struct libwebsocket_context *context)
Andy Green2ac5a6f2011-01-28 10:00:18 +0000633{
Peter Hinz56885f32011-03-02 22:03:47 +0000634 return (const char *)context->canonical_hostname;
Andy Green2ac5a6f2011-01-28 10:00:18 +0000635}
636
Andy Green706961d2013-01-17 16:50:35 +0800637int user_callback_handle_rxflow(callback_function callback_function,
Andy Greenb5b23192013-02-11 17:13:32 +0800638 struct libwebsocket_context *context,
Andy Green706961d2013-01-17 16:50:35 +0800639 struct libwebsocket *wsi,
640 enum libwebsocket_callback_reasons reason, void *user,
641 void *in, size_t len)
642{
643 int n;
644
645 n = callback_function(context, wsi, reason, user, in, len);
Andy Greenaedc9532013-02-10 21:21:24 +0800646 if (!n)
647 n = _libwebsocket_rx_flow_control(wsi);
Andy Green706961d2013-01-17 16:50:35 +0800648
Andy Greenaedc9532013-02-10 21:21:24 +0800649 return n;
Andy Green706961d2013-01-17 16:50:35 +0800650}
651
Andy Greenb45993c2010-12-18 15:13:50 +0000652
Andy Greenb45993c2010-12-18 15:13:50 +0000653/**
shysb4e800e2013-10-24 22:12:03 +0800654 * libwebsocket_set_proxy() - Setups proxy to libwebsocket_context.
655 * @context: pointer to struct libwebsocket_context you want set proxy to
656 * @proxy: pointer to c string containing proxy in format address:port
657 *
658 * Returns 0 if proxy string was parsed and proxy was setup.
659 * Returns -1 if @proxy is NULL or has incorrect format.
660 *
661 * This is only required if your OS does not provide the http_proxy
Drew Noakesefe10b02014-10-23 15:34:26 +0100662 * environment variable (eg, OSX)
shysb4e800e2013-10-24 22:12:03 +0800663 *
664 * IMPORTANT! You should call this function right after creation of the
665 * libwebsocket_context and before call to connect. If you call this
666 * function after connect behavior is undefined.
667 * This function will override proxy settings made on libwebsocket_context
668 * creation with genenv() call.
669 */
670
671LWS_VISIBLE int
672libwebsocket_set_proxy(struct libwebsocket_context *context, const char *proxy)
673{
674 char *p;
675
676 if (!proxy)
677 return -1;
678
679 strncpy(context->http_proxy_address, proxy,
680 sizeof(context->http_proxy_address) - 1);
681 context->http_proxy_address[
682 sizeof(context->http_proxy_address) - 1] = '\0';
683
684 p = strchr(context->http_proxy_address, ':');
685 if (!p) {
686 lwsl_err("http_proxy needs to be ads:port\n");
687
688 return -1;
689 }
690 *p = '\0';
691 context->http_proxy_port = atoi(p + 1);
692
693 lwsl_notice(" Proxy %s:%u\n", context->http_proxy_address,
694 context->http_proxy_port);
695
696 return 0;
697}
698
699/**
Andy Greenb45993c2010-12-18 15:13:50 +0000700 * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
Andy Green8f037e42010-12-19 22:13:26 +0000701 * connection.
Andy Greenb45993c2010-12-18 15:13:50 +0000702 * @wsi: pointer to struct websocket you want to know the protocol of
703 *
Andy Green8f037e42010-12-19 22:13:26 +0000704 *
Andy Green6f520a52013-01-29 17:57:39 +0800705 * Some apis can act on all live connections of a given protocol,
706 * this is how you can get a pointer to the active protocol if needed.
Andy Greenb45993c2010-12-18 15:13:50 +0000707 */
Andy Greenab990e42010-10-31 12:42:52 +0000708
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800709LWS_VISIBLE const struct libwebsocket_protocols *
Andy Greenb45993c2010-12-18 15:13:50 +0000710libwebsockets_get_protocol(struct libwebsocket *wsi)
711{
712 return wsi->protocol;
713}
714
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800715LWS_VISIBLE int
Andy Green82c3d542011-03-07 21:16:31 +0000716libwebsocket_is_final_fragment(struct libwebsocket *wsi)
717{
Andy Green623a98d2013-01-21 11:04:23 +0800718 return wsi->u.ws.final;
Andy Green82c3d542011-03-07 21:16:31 +0000719}
Alex Bligh49146db2011-11-07 17:19:25 +0800720
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800721LWS_VISIBLE unsigned char
David Galeanoe2cf9922013-01-09 18:06:55 +0800722libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
723{
Andy Green623a98d2013-01-21 11:04:23 +0800724 return wsi->u.ws.rsv;
David Galeanoe2cf9922013-01-09 18:06:55 +0800725}
726
Andy Green2af4d5b2013-02-18 16:30:10 +0800727int
Alex Bligh49146db2011-11-07 17:19:25 +0800728libwebsocket_ensure_user_space(struct libwebsocket *wsi)
729{
Andy Green7df53c52014-10-22 15:37:28 +0800730 lwsl_info("%s: %p protocol %p\n", __func__, wsi, wsi->protocol);
Andy Green67d556c2013-02-15 22:31:55 +0800731 if (!wsi->protocol)
Andy Green2af4d5b2013-02-18 16:30:10 +0800732 return 1;
Andy Green67d556c2013-02-15 22:31:55 +0800733
Alex Bligh49146db2011-11-07 17:19:25 +0800734 /* allocate the per-connection user memory (if any) */
735
736 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
Alejandro Mery6ff28242014-12-04 23:59:35 +0100737 wsi->user_space = lws_zalloc(wsi->protocol->per_session_data_size);
Alex Bligh49146db2011-11-07 17:19:25 +0800738 if (wsi->user_space == NULL) {
Andy Green43db0452013-01-10 19:50:35 +0800739 lwsl_err("Out of memory for conn user space\n");
Andy Green2af4d5b2013-02-18 16:30:10 +0800740 return 1;
Alex Bligh49146db2011-11-07 17:19:25 +0800741 }
Andy Green7df53c52014-10-22 15:37:28 +0800742 } else
743 lwsl_info("%s: %p protocol pss %u, user_space=%d\n", __func__, wsi, wsi->protocol->per_session_data_size, wsi->user_space);
Andy Green2af4d5b2013-02-18 16:30:10 +0800744 return 0;
Alex Bligh49146db2011-11-07 17:19:25 +0800745}
Andy Green43db0452013-01-10 19:50:35 +0800746
Andy Greenb25b85f2014-04-03 23:34:09 +0800747LWS_VISIBLE void lwsl_emit_stderr(int level, const char *line)
Andy Greende8f27a2013-01-12 09:17:42 +0800748{
Andy Green0b319092013-01-19 11:17:56 +0800749 char buf[300];
Patrick Gansterer92792b42014-02-26 21:37:31 +0100750 unsigned long long now;
Andy Green0b319092013-01-19 11:17:56 +0800751 int n;
752
Andy Green0b319092013-01-19 11:17:56 +0800753 buf[0] = '\0';
754 for (n = 0; n < LLL_COUNT; n++)
755 if (level == (1 << n)) {
Patrick Gansterer92792b42014-02-26 21:37:31 +0100756 now = time_in_microseconds() / 100;
Imo Farcher97a748a2015-01-26 15:39:36 +0800757 sprintf(buf, "[%llu:%04d] %s: ", (unsigned long long) now / 10000,
Patrick Gansterer92792b42014-02-26 21:37:31 +0100758 (int)(now % 10000), log_level_names[n]);
Andy Green0b319092013-01-19 11:17:56 +0800759 break;
760 }
Andy Greenb5b23192013-02-11 17:13:32 +0800761
Andy Green0b319092013-01-19 11:17:56 +0800762 fprintf(stderr, "%s%s", buf, line);
Andy Greende8f27a2013-01-12 09:17:42 +0800763}
764
Andy Greenc11db202013-01-19 11:12:16 +0800765
Neal Horman98e491f2014-12-10 18:50:28 -0600766LWS_VISIBLE void _lws_logv(int filter, const char *format, va_list vl)
Andy Green43db0452013-01-10 19:50:35 +0800767{
Andy Greende8f27a2013-01-12 09:17:42 +0800768 char buf[256];
Andy Green43db0452013-01-10 19:50:35 +0800769
770 if (!(log_level & filter))
771 return;
772
Neal Horman98e491f2014-12-10 18:50:28 -0600773 vsnprintf(buf, sizeof(buf), format, vl);
Andy Greenb5b23192013-02-11 17:13:32 +0800774 buf[sizeof(buf) - 1] = '\0';
Andy Greende8f27a2013-01-12 09:17:42 +0800775
Andy Green0b319092013-01-19 11:17:56 +0800776 lwsl_emit(filter, buf);
Andy Green43db0452013-01-10 19:50:35 +0800777}
778
Neal Horman98e491f2014-12-10 18:50:28 -0600779LWS_VISIBLE void _lws_log(int filter, const char *format, ...)
780{
781 va_list ap;
782
783 va_start(ap, format);
784 _lws_logv(filter, format, ap);
785 va_end(ap);
786}
787
Andy Green43db0452013-01-10 19:50:35 +0800788/**
789 * lws_set_log_level() - Set the logging bitfield
790 * @level: OR together the LLL_ debug contexts you want output from
Andy Greende8f27a2013-01-12 09:17:42 +0800791 * @log_emit_function: NULL to leave it as it is, or a user-supplied
792 * function to perform log string emission instead of
793 * the default stderr one.
Andy Green43db0452013-01-10 19:50:35 +0800794 *
Andy Greenc6511a02013-02-19 10:01:48 +0800795 * log level defaults to "err", "warn" and "notice" contexts enabled and
Andy Greende8f27a2013-01-12 09:17:42 +0800796 * emission on stderr.
Andy Green43db0452013-01-10 19:50:35 +0800797 */
798
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800799LWS_VISIBLE void lws_set_log_level(int level, void (*log_emit_function)(int level,
Andy Greenb5b23192013-02-11 17:13:32 +0800800 const char *line))
Andy Green43db0452013-01-10 19:50:35 +0800801{
802 log_level = level;
Andy Greende8f27a2013-01-12 09:17:42 +0800803 if (log_emit_function)
804 lwsl_emit = log_emit_function;
vpeter44dd8ada2014-04-27 13:28:22 +0200805}
Andy Greenb128ccc2014-08-16 09:54:27 +0800806
807/**
808 * lws_use_ssl() - Find out if connection is using SSL
809 * @wsi: websocket connection to check
810 *
811 * Returns 0 if the connection is not using SSL, 1 if using SSL and
812 * using verified cert, and 2 if using SSL but the cert was not
813 * checked (appears for client wsi told to skip check on connection)
814 */
815LWS_VISIBLE int
816lws_is_ssl(struct libwebsocket *wsi)
817{
Andy Greenfc9871e2014-08-19 08:41:26 +0800818#ifdef LWS_OPENSSL_SUPPORT
Andy Greenb128ccc2014-08-16 09:54:27 +0800819 return wsi->use_ssl;
Andy Greenfc9871e2014-08-19 08:41:26 +0800820#else
821 return 0;
822#endif
Andy Greenb128ccc2014-08-16 09:54:27 +0800823}
Andy Green14425ea2014-08-18 22:49:39 +0800824
825/**
826 * lws_partial_buffered() - find out if lws buffered the last write
827 * @wsi: websocket connection to check
828 *
829 * Returns 1 if you cannot use libwebsocket_write because the last
830 * write on this connection is still buffered, and can't be cleared without
831 * returning to the service loop and waiting for the connection to be
832 * writeable again.
833 *
834 * If you will try to do >1 libwebsocket_write call inside a single
835 * WRITEABLE callback, you must check this after every write and bail if
836 * set, ask for a new writeable callback and continue writing from there.
837 *
838 * This is never set at the start of a writeable callback, but any write
839 * may set it.
840 */
841
842LWS_VISIBLE int
843lws_partial_buffered(struct libwebsocket *wsi)
844{
845 return !!wsi->truncated_send_len;
846}
Andy Green024eb6c2014-10-08 12:00:53 +0800847
848void lws_set_protocol_write_pending(struct libwebsocket_context *context,
849 struct libwebsocket *wsi,
850 enum lws_pending_protocol_send pend)
851{
Andy Green97ee57f2014-10-29 09:39:08 +0800852 lwsl_info("setting pps %d\n", pend);
Andy Green024eb6c2014-10-08 12:00:53 +0800853
854 if (wsi->pps)
855 lwsl_err("pps overwrite\n");
856 wsi->pps = pend;
857 libwebsocket_rx_flow_control(wsi, 0);
858 libwebsocket_callback_on_writable(context, wsi);
Andy Green260a0fc2014-10-18 18:52:39 +0800859}
Andy Green97ee57f2014-10-29 09:39:08 +0800860
861LWS_VISIBLE size_t
862lws_get_peer_write_allowance(struct libwebsocket *wsi)
863{
864#ifdef LWS_USE_HTTP2
865 /* only if we are using HTTP2 on this connection */
866 if (wsi->mode != LWS_CONNMODE_HTTP2_SERVING)
867 return -1;
868 /* user is only interested in how much he can send, or that he can't */
869 if (wsi->u.http2.tx_credit <= 0)
870 return 0;
871
872 return wsi->u.http2.tx_credit;
873#else
874 return -1;
875#endif
876}
Andy Green44c11612014-11-08 11:18:47 +0800877
878LWS_VISIBLE void
879lws_union_transition(struct libwebsocket *wsi, enum connection_mode mode)
880{
881 memset(&wsi->u, 0, sizeof(wsi->u));
882 wsi->mode = mode;
883}