2011-03-07 17:54:06 +00:00
|
|
|
/*
|
2010-11-08 17:12:19 +00:00
|
|
|
* libwebsockets - small server side websockets and web server implementation
|
2010-12-19 22:13:26 +00:00
|
|
|
*
|
2014-04-02 14:25:10 +08:00
|
|
|
* Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
|
2010-11-08 17:12:19 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation:
|
|
|
|
* version 2.1 of the License.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
* MA 02110-1301 USA
|
2010-10-31 17:51:39 +00:00
|
|
|
*/
|
|
|
|
|
2010-11-08 20:20:42 +00:00
|
|
|
#include "private-libwebsockets.h"
|
2010-10-28 22:36:01 +01:00
|
|
|
|
2014-04-03 07:29:50 +08:00
|
|
|
int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
|
2013-01-19 11:32:18 +08:00
|
|
|
static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
|
|
|
|
|
2013-02-11 17:13:32 +08:00
|
|
|
static const char * const log_level_names[] = {
|
2013-01-10 19:50:35 +08:00
|
|
|
"ERR",
|
|
|
|
"WARN",
|
2013-01-19 12:18:07 +08:00
|
|
|
"NOTICE",
|
2013-01-10 19:50:35 +08:00
|
|
|
"INFO",
|
|
|
|
"DEBUG",
|
|
|
|
"PARSER",
|
|
|
|
"HEADER",
|
|
|
|
"EXTENSION",
|
|
|
|
"CLIENT",
|
2013-01-29 12:36:17 +08:00
|
|
|
"LATENCY",
|
2013-01-10 19:50:35 +08:00
|
|
|
};
|
|
|
|
|
2015-06-25 17:51:07 +02:00
|
|
|
void
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_free_wsi(struct lws *wsi)
|
2015-06-25 17:51:07 +02:00
|
|
|
{
|
|
|
|
if (!wsi)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Protocol user data may be allocated either internally by lws
|
2015-12-04 16:54:12 +08:00
|
|
|
* or by specified the user.
|
|
|
|
* We should only free what we allocated. */
|
|
|
|
if (wsi->protocol && wsi->protocol->per_session_data_size &&
|
|
|
|
wsi->user_space && !wsi->user_space_externally_allocated)
|
2015-06-25 17:51:07 +02:00
|
|
|
lws_free(wsi->user_space);
|
|
|
|
|
|
|
|
lws_free2(wsi->rxflow_buffer);
|
|
|
|
lws_free2(wsi->truncated_send_malloc);
|
|
|
|
lws_free_header_table(wsi);
|
|
|
|
lws_free(wsi);
|
|
|
|
}
|
|
|
|
|
2010-12-19 22:13:26 +00:00
|
|
|
void
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_close_and_free_session(struct lws_context *context,
|
2015-12-04 11:30:53 +08:00
|
|
|
struct lws *wsi, enum lws_close_status reason)
|
2010-11-03 11:13:06 +00:00
|
|
|
{
|
2015-12-04 16:54:12 +08:00
|
|
|
int n, m, ret, old_state;
|
2011-03-07 07:08:18 +00:00
|
|
|
struct lws_tokens eff_buf;
|
2015-12-04 16:54:12 +08:00
|
|
|
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
|
|
|
|
LWS_SEND_BUFFER_POST_PADDING];
|
2010-12-18 15:13:50 +00:00
|
|
|
|
2011-02-14 08:03:48 +00:00
|
|
|
if (!wsi)
|
2010-12-18 15:13:50 +00:00
|
|
|
return;
|
|
|
|
|
2011-02-14 09:14:25 +00:00
|
|
|
old_state = wsi->state;
|
2010-11-03 11:13:06 +00:00
|
|
|
|
2015-12-04 16:54:12 +08:00
|
|
|
if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED &&
|
|
|
|
wsi->u.http.fd != LWS_INVALID_FILE) {
|
|
|
|
lwsl_debug("closing http file\n");
|
|
|
|
compatible_file_close(wsi->u.http.fd);
|
|
|
|
wsi->u.http.fd = LWS_INVALID_FILE;
|
|
|
|
context->protocols[0].callback(context, wsi,
|
|
|
|
LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0);
|
|
|
|
}
|
2015-04-12 08:17:26 +08:00
|
|
|
if (wsi->socket_is_permanently_unusable ||
|
|
|
|
reason == LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY)
|
2014-10-16 08:23:46 +08:00
|
|
|
goto just_kill_connection;
|
|
|
|
|
2014-04-10 14:25:24 +08:00
|
|
|
switch (old_state) {
|
|
|
|
case WSI_STATE_DEAD_SOCKET:
|
2011-02-10 09:07:05 +00:00
|
|
|
return;
|
|
|
|
|
2013-02-15 22:48:58 +08:00
|
|
|
/* we tried the polite way... */
|
2014-04-10 14:25:24 +08:00
|
|
|
case WSI_STATE_AWAITING_CLOSE_ACK:
|
2013-02-15 22:48:58 +08:00
|
|
|
goto just_kill_connection;
|
|
|
|
|
2014-04-10 14:25:24 +08:00
|
|
|
case WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE:
|
|
|
|
if (wsi->truncated_send_len) {
|
2015-12-04 08:43:54 +08:00
|
|
|
lws_callback_on_writable(context, wsi);
|
2014-04-10 14:25:24 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
lwsl_info("wsi %p completed WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
|
|
|
|
goto just_kill_connection;
|
|
|
|
default:
|
|
|
|
if (wsi->truncated_send_len) {
|
|
|
|
lwsl_info("wsi %p entering WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
|
|
|
|
wsi->state = WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE;
|
2015-12-04 08:43:54 +08:00
|
|
|
lws_set_timeout(wsi, PENDING_FLUSH_STORED_SEND_BEFORE_CLOSE, 5);
|
2014-04-10 14:25:24 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-01-21 11:04:23 +08:00
|
|
|
wsi->u.ws.close_reason = reason;
|
2011-03-07 07:08:12 +00:00
|
|
|
|
2013-09-20 20:26:12 +08:00
|
|
|
if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT ||
|
2015-12-04 16:54:12 +08:00
|
|
|
wsi->mode == LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE)
|
2013-09-20 20:26:12 +08:00
|
|
|
goto just_kill_connection;
|
|
|
|
|
2015-01-28 04:15:13 +08:00
|
|
|
if (wsi->mode == LWS_CONNMODE_HTTP_SERVING)
|
|
|
|
context->protocols[0].callback(context, wsi,
|
|
|
|
LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0);
|
|
|
|
|
2011-05-25 21:41:57 +01:00
|
|
|
/*
|
|
|
|
* are his extensions okay with him closing? Eg he might be a mux
|
|
|
|
* parent and just his ch1 aspect is closing?
|
|
|
|
*/
|
2014-04-02 21:02:54 +08:00
|
|
|
|
|
|
|
if (lws_ext_callback_for_each_active(wsi,
|
|
|
|
LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE, NULL, 0) > 0) {
|
|
|
|
lwsl_ext("extension vetoed close\n");
|
|
|
|
return;
|
2011-05-25 21:41:57 +01:00
|
|
|
}
|
|
|
|
|
2011-03-07 07:08:18 +00:00
|
|
|
/*
|
|
|
|
* flush any tx pending from extensions, since we may send close packet
|
|
|
|
* if there are problems with send, just nuke the connection
|
|
|
|
*/
|
|
|
|
|
2014-04-02 21:02:54 +08:00
|
|
|
do {
|
2011-03-07 07:08:18 +00:00
|
|
|
ret = 0;
|
|
|
|
eff_buf.token = NULL;
|
|
|
|
eff_buf.token_len = 0;
|
|
|
|
|
|
|
|
/* show every extension the new incoming data */
|
|
|
|
|
2014-04-02 21:02:54 +08:00
|
|
|
m = lws_ext_callback_for_each_active(wsi,
|
|
|
|
LWS_EXT_CALLBACK_FLUSH_PENDING_TX, &eff_buf, 0);
|
|
|
|
if (m < 0) {
|
|
|
|
lwsl_ext("Extension reports fatal error\n");
|
|
|
|
goto just_kill_connection;
|
2011-03-07 07:08:18 +00:00
|
|
|
}
|
2014-04-02 21:02:54 +08:00
|
|
|
if (m)
|
|
|
|
/*
|
|
|
|
* at least one extension told us he has more
|
|
|
|
* to spill, so we will go around again after
|
|
|
|
*/
|
|
|
|
ret = 1;
|
2011-03-07 07:08:18 +00:00
|
|
|
|
|
|
|
/* assuming they left us something to send, send it */
|
|
|
|
|
|
|
|
if (eff_buf.token_len)
|
|
|
|
if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
|
2015-12-04 16:54:12 +08:00
|
|
|
eff_buf.token_len) !=
|
|
|
|
eff_buf.token_len) {
|
2013-02-11 17:13:32 +08:00
|
|
|
lwsl_debug("close: ext spill failed\n");
|
2011-03-07 07:08:18 +00:00
|
|
|
goto just_kill_connection;
|
2013-01-17 14:46:43 +08:00
|
|
|
}
|
2014-04-02 21:02:54 +08:00
|
|
|
} while (ret);
|
2011-03-07 07:08:18 +00:00
|
|
|
|
2011-03-07 07:08:12 +00:00
|
|
|
/*
|
2015-12-04 08:43:54 +08:00
|
|
|
* signal we are closing, lws_write will
|
2011-03-07 07:08:12 +00:00
|
|
|
* add any necessary version-specific stuff. If the write fails,
|
|
|
|
* no worries we are closing anyway. If we didn't initiate this
|
|
|
|
* close, then our state has been changed to
|
|
|
|
* WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
|
|
|
|
*
|
|
|
|
* Likewise if it's a second call to close this connection after we
|
|
|
|
* sent the close indication to the peer already, we are in state
|
|
|
|
* WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (old_state == WSI_STATE_ESTABLISHED &&
|
2015-03-25 01:53:58 +08:00
|
|
|
reason != LWS_CLOSE_STATUS_NOSTATUS &&
|
|
|
|
reason != LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY) {
|
2011-05-24 22:07:45 +01:00
|
|
|
|
2013-01-10 19:50:35 +08:00
|
|
|
lwsl_debug("sending close indication...\n");
|
2011-05-24 22:07:45 +01:00
|
|
|
|
2013-02-11 14:32:48 +08:00
|
|
|
/* make valgrind happy */
|
2013-02-11 17:13:32 +08:00
|
|
|
memset(buf, 0, sizeof(buf));
|
2015-12-04 16:54:12 +08:00
|
|
|
n = lws_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING + 2],
|
|
|
|
0, LWS_WRITE_CLOSE);
|
2013-02-23 10:50:10 +08:00
|
|
|
if (n >= 0) {
|
2011-03-07 07:08:12 +00:00
|
|
|
/*
|
|
|
|
* we have sent a nice protocol level indication we
|
|
|
|
* now wish to close, we should not send anything more
|
|
|
|
*/
|
|
|
|
wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
|
|
|
|
|
2013-02-11 17:13:32 +08:00
|
|
|
/*
|
|
|
|
* ...and we should wait for a reply for a bit
|
|
|
|
* out of politeness
|
|
|
|
*/
|
2015-12-04 16:54:12 +08:00
|
|
|
lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_ACK, 1);
|
2013-01-10 19:50:35 +08:00
|
|
|
lwsl_debug("sent close indication, awaiting ack\n");
|
2011-03-07 07:08:12 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-02-11 17:13:32 +08:00
|
|
|
lwsl_info("close: sending close packet failed, hanging up\n");
|
2013-01-17 14:46:43 +08:00
|
|
|
|
2011-03-07 07:08:12 +00:00
|
|
|
/* else, the send failed and we should just hang up */
|
|
|
|
}
|
|
|
|
|
2011-03-07 07:08:18 +00:00
|
|
|
just_kill_connection:
|
2011-05-24 22:07:45 +01:00
|
|
|
|
2013-02-11 17:13:32 +08:00
|
|
|
lwsl_debug("close: just_kill_connection\n");
|
2011-05-24 22:07:45 +01:00
|
|
|
|
2011-03-07 07:08:12 +00:00
|
|
|
/*
|
|
|
|
* we won't be servicing or receiving anything further from this guy
|
2013-01-17 12:26:48 +08:00
|
|
|
* delete socket from the internal poll list if still present
|
2011-03-07 07:08:12 +00:00
|
|
|
*/
|
2015-01-29 08:36:18 +08:00
|
|
|
lws_ssl_remove_wsi_from_buffered_list(context, wsi);
|
|
|
|
|
2015-12-04 16:54:12 +08:00
|
|
|
/* checking return redundant since we anyway close */
|
2013-01-17 12:26:48 +08:00
|
|
|
remove_wsi_socket_from_fds(context, wsi);
|
2011-02-14 08:03:48 +00:00
|
|
|
|
2010-11-03 11:13:06 +00:00
|
|
|
wsi->state = WSI_STATE_DEAD_SOCKET;
|
2014-12-05 00:09:20 +01:00
|
|
|
|
|
|
|
lws_free2(wsi->rxflow_buffer);
|
2015-06-25 17:51:07 +02:00
|
|
|
lws_free_header_table(wsi);
|
2014-12-05 00:09:20 +01:00
|
|
|
|
2013-02-11 17:13:32 +08:00
|
|
|
if ((old_state == WSI_STATE_ESTABLISHED ||
|
|
|
|
wsi->mode == LWS_CONNMODE_WS_SERVING ||
|
2013-02-12 12:52:39 +08:00
|
|
|
wsi->mode == LWS_CONNMODE_WS_CLIENT)) {
|
|
|
|
|
2014-12-05 00:09:20 +01:00
|
|
|
lws_free2(wsi->u.ws.rx_user_buffer);
|
2014-10-08 12:00:53 +08:00
|
|
|
|
2015-12-04 16:54:12 +08:00
|
|
|
if (wsi->truncated_send_malloc)
|
add explicit error for partial send
This patch adds code to handle the situation that a prepared user buffer could not all be sent on the
socket at once. There are two kinds of situation to handle
1) User code handles it: The connection only has extensions active that do not rewrite the buffer.
In this case, the patch caused libwebsocket_write() to simply return the amount of user buffer that
was consumed (this is specifically the amount of user buffer used in sending what was accepted,
nothing else). So user code can just advance its buffer that much and resume sending when the socket
is writable again. This continues the frame rather than starting a new one or new fragment.
2) The connections has extensions active which actually send something quite different than what the
user buffer contains, for example a compression extension. In this case, libwebsockets will dynamically
malloc a buffer to contain a copy of the remaining unsent data, request notifiction when writeable again,
and automatically spill and free this buffer with the highest priority before passing on the writable
notification to anything else. For this situation, the call to write will return that it used the
whole user buffer, even though part is still rebuffered.
This patch should enable libwebsockets to detect the two cases and take the appropriate action.
There are also two choices for user code to deal with partial sends.
1) Leave the no_buffer_all_partial_tx member in the protocol struct at zero. The library will dyamically
buffer anything you send that did not get completely written to the socket, and automatically spill it next
time the socket is writable. You can use this method if your sent frames are relatvely small and unlikely to get
truncated anyway.
2) Set the no_buffer_all_partial_tx member in the protocol struct. User code now needs to take care of the
return value from libwebsocket_write() and deal with resending the remainder if not all of the requested amount
got sent. You should use this method if you are sending large messages and want to maximize throughput and efficiency.
Since the new member no_buffer_all_partial_tx will be zero by default, this patch will auto-rebuffer any
partial sends by default. That's good for most cases but if you attempt to send large blocks, make sure you
follow option 2) above.
Signed-off-by: Andy Green <andy.green@linaro.org>
2013-10-17 08:09:19 +08:00
|
|
|
/* not going to be completed... nuke it */
|
2014-12-05 00:09:20 +01:00
|
|
|
lws_free2(wsi->truncated_send_malloc);
|
2015-12-04 16:54:12 +08:00
|
|
|
|
2014-08-24 14:39:19 +08:00
|
|
|
if (wsi->u.ws.ping_payload_buf) {
|
2014-12-05 00:09:20 +01:00
|
|
|
lws_free2(wsi->u.ws.ping_payload_buf);
|
2014-08-24 14:39:19 +08:00
|
|
|
wsi->u.ws.ping_payload_alloc = 0;
|
|
|
|
wsi->u.ws.ping_payload_len = 0;
|
2015-03-24 21:07:01 +08:00
|
|
|
wsi->u.ws.ping_pending_flag = 0;
|
2014-08-24 14:39:19 +08:00
|
|
|
}
|
2013-02-06 21:10:16 +09:00
|
|
|
}
|
|
|
|
|
2011-02-14 08:03:48 +00:00
|
|
|
/* tell the user it's all over for this guy */
|
|
|
|
|
2011-02-28 07:45:29 +00:00
|
|
|
if (wsi->protocol && wsi->protocol->callback &&
|
2015-12-04 16:54:12 +08:00
|
|
|
((old_state == WSI_STATE_ESTABLISHED) ||
|
|
|
|
(old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
|
|
|
|
(old_state == WSI_STATE_AWAITING_CLOSE_ACK) ||
|
|
|
|
(old_state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE))) {
|
2013-01-10 19:50:35 +08:00
|
|
|
lwsl_debug("calling back CLOSED\n");
|
2011-03-02 22:03:47 +00:00
|
|
|
wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
|
2015-12-04 16:54:12 +08:00
|
|
|
wsi->user_space, NULL, 0);
|
2014-04-02 14:25:10 +08:00
|
|
|
} else if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) {
|
2013-06-29 10:16:18 +08:00
|
|
|
lwsl_debug("calling back CLOSED_HTTP\n");
|
|
|
|
context->protocols[0].callback(context, wsi,
|
|
|
|
LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0 );
|
2015-04-27 19:07:38 +08:00
|
|
|
} else if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY ||
|
|
|
|
wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT) {
|
2015-04-16 19:55:42 +08:00
|
|
|
lwsl_debug("Connection closed before server reply\n");
|
|
|
|
context->protocols[0].callback(context, wsi,
|
2015-12-04 16:54:12 +08:00
|
|
|
LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
|
|
|
|
wsi->user_space, NULL, 0);
|
2011-11-07 19:53:23 +08:00
|
|
|
} else
|
2015-04-16 19:55:42 +08:00
|
|
|
lwsl_debug("not calling back closed mode=%d state=%d\n",
|
|
|
|
wsi->mode, old_state);
|
2010-11-03 11:13:06 +00:00
|
|
|
|
2011-03-06 10:29:38 +00:00
|
|
|
/* deallocate any active extension contexts */
|
2014-04-02 21:02:54 +08:00
|
|
|
|
2015-12-04 16:54:12 +08:00
|
|
|
if (lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_DESTROY,
|
|
|
|
NULL, 0) < 0)
|
2014-04-02 21:02:54 +08:00
|
|
|
lwsl_warn("extension destruction failed\n");
|
|
|
|
#ifndef LWS_NO_EXTENSIONS
|
|
|
|
for (n = 0; n < wsi->count_active_extensions; n++)
|
2014-12-04 23:59:35 +01:00
|
|
|
lws_free(wsi->active_extensions_user[n]);
|
2014-04-02 21:02:54 +08:00
|
|
|
#endif
|
2011-05-23 10:00:03 +01:00
|
|
|
/*
|
|
|
|
* inform all extensions in case they tracked this guy out of band
|
|
|
|
* even though not active on him specifically
|
|
|
|
*/
|
2014-04-02 21:02:54 +08:00
|
|
|
if (lws_ext_callback_for_each_extension_type(context, wsi,
|
|
|
|
LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING, NULL, 0) < 0)
|
|
|
|
lwsl_warn("ext destroy wsi failed\n");
|
2011-05-23 10:00:03 +01:00
|
|
|
|
2015-11-14 13:48:58 +08:00
|
|
|
if (!lws_ssl_close(wsi) && lws_socket_is_valid(wsi->sock)) {
|
2015-11-02 20:34:12 +08:00
|
|
|
#if LWS_POSIX
|
2014-04-12 10:07:02 +08:00
|
|
|
n = shutdown(wsi->sock, SHUT_RDWR);
|
|
|
|
if (n)
|
|
|
|
lwsl_debug("closing: shutdown ret %d\n", LWS_ERRNO);
|
|
|
|
|
|
|
|
n = compatible_close(wsi->sock);
|
|
|
|
if (n)
|
|
|
|
lwsl_debug("closing: close ret %d\n", LWS_ERRNO);
|
2015-11-02 20:34:12 +08:00
|
|
|
|
2015-11-08 12:10:26 +08:00
|
|
|
#else
|
|
|
|
compatible_close(wsi->sock);
|
2015-11-02 20:34:12 +08:00
|
|
|
#endif
|
2015-11-08 12:10:26 +08:00
|
|
|
wsi->sock = LWS_SOCK_INVALID;
|
2010-11-08 17:03:03 +00:00
|
|
|
}
|
2014-02-15 19:25:50 +08:00
|
|
|
|
|
|
|
/* outermost destroy notification for wsi (user_space still intact) */
|
2015-12-04 16:54:12 +08:00
|
|
|
context->protocols[0].callback(context, wsi, LWS_CALLBACK_WSI_DESTROY,
|
|
|
|
wsi->user_space, NULL, 0);
|
2014-02-15 19:25:50 +08:00
|
|
|
|
2015-06-25 17:51:07 +02:00
|
|
|
lws_free_wsi(wsi);
|
2010-11-03 11:13:06 +00:00
|
|
|
}
|
|
|
|
|
2015-01-28 21:03:49 +08:00
|
|
|
LWS_VISIBLE int
|
2015-12-04 11:30:53 +08:00
|
|
|
lws_get_addresses(struct lws_context *context, void *ads, char *name,
|
|
|
|
int name_len, char *rip, int rip_len)
|
2015-01-28 21:03:49 +08:00
|
|
|
{
|
2015-11-02 20:34:12 +08:00
|
|
|
#if LWS_POSIX
|
2015-01-28 21:03:49 +08:00
|
|
|
struct addrinfo ai, *res;
|
2015-10-15 13:02:03 +03:00
|
|
|
struct sockaddr_in addr4;
|
2015-01-28 21:03:49 +08:00
|
|
|
|
|
|
|
rip[0] = '\0';
|
|
|
|
name[0] = '\0';
|
2015-10-15 13:02:03 +03:00
|
|
|
addr4.sin_family = AF_UNSPEC;
|
2015-01-28 21:03:49 +08:00
|
|
|
|
|
|
|
#ifdef LWS_USE_IPV6
|
|
|
|
if (LWS_IPV6_ENABLED(context)) {
|
|
|
|
if (!lws_plat_inet_ntop(AF_INET6, &((struct sockaddr_in6 *)ads)->sin6_addr, rip, rip_len)) {
|
|
|
|
lwsl_err("inet_ntop", strerror(LWS_ERRNO));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Strip off the IPv4 to IPv6 header if one exists
|
|
|
|
if (strncmp(rip, "::ffff:", 7) == 0)
|
|
|
|
memmove(rip, rip + 7, strlen(rip) - 6);
|
|
|
|
|
|
|
|
getnameinfo((struct sockaddr *)ads,
|
|
|
|
sizeof(struct sockaddr_in6), name,
|
|
|
|
name_len, NULL, 0, 0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
2015-10-15 13:02:03 +03:00
|
|
|
struct addrinfo *result;
|
|
|
|
|
2015-01-28 21:03:49 +08:00
|
|
|
memset(&ai, 0, sizeof ai);
|
|
|
|
ai.ai_family = PF_UNSPEC;
|
|
|
|
ai.ai_socktype = SOCK_STREAM;
|
|
|
|
ai.ai_flags = AI_CANONNAME;
|
|
|
|
|
|
|
|
if (getnameinfo((struct sockaddr *)ads,
|
|
|
|
sizeof(struct sockaddr_in),
|
|
|
|
name, name_len, NULL, 0, 0))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!rip)
|
|
|
|
return 0;
|
|
|
|
|
2015-10-15 13:02:03 +03:00
|
|
|
if (getaddrinfo(name, NULL, &ai, &result))
|
2015-01-28 21:03:49 +08:00
|
|
|
return -1;
|
|
|
|
|
2015-10-15 13:02:03 +03:00
|
|
|
res = result;
|
|
|
|
while (addr4.sin_family == AF_UNSPEC && res) {
|
2015-01-28 21:03:49 +08:00
|
|
|
switch (res->ai_family) {
|
|
|
|
case AF_INET:
|
2015-10-15 13:02:03 +03:00
|
|
|
addr4.sin_addr = ((struct sockaddr_in *)res->ai_addr)->sin_addr;
|
|
|
|
addr4.sin_family = AF_INET;
|
2015-01-28 21:03:49 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
res = res->ai_next;
|
|
|
|
}
|
2015-10-15 13:02:03 +03:00
|
|
|
freeaddrinfo(result);
|
2015-01-28 21:03:49 +08:00
|
|
|
}
|
|
|
|
|
2015-10-15 13:02:03 +03:00
|
|
|
if (addr4.sin_family == AF_UNSPEC)
|
2015-01-28 21:03:49 +08:00
|
|
|
return -1;
|
|
|
|
|
2015-10-15 13:02:03 +03:00
|
|
|
lws_plat_inet_ntop(AF_INET, &addr4.sin_addr, rip, rip_len);
|
2015-01-28 21:03:49 +08:00
|
|
|
|
|
|
|
return 0;
|
2015-11-02 20:34:12 +08:00
|
|
|
#else
|
|
|
|
(void)context;
|
|
|
|
(void)ads;
|
|
|
|
(void)name;
|
|
|
|
(void)name_len;
|
|
|
|
(void)rip;
|
|
|
|
(void)rip_len;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
#endif
|
2015-01-28 21:03:49 +08:00
|
|
|
}
|
|
|
|
|
2011-02-13 08:37:12 +00:00
|
|
|
/**
|
2015-12-04 08:43:54 +08:00
|
|
|
* lws_get_peer_addresses() - Get client address information
|
2013-01-30 08:12:20 +08:00
|
|
|
* @context: Libwebsockets context
|
2015-12-04 11:08:32 +08:00
|
|
|
* @wsi: Local struct lws associated with
|
2011-02-13 08:37:12 +00:00
|
|
|
* @fd: Connection socket descriptor
|
|
|
|
* @name: Buffer to take client address name
|
|
|
|
* @name_len: Length of client address name buffer
|
2014-10-23 15:34:26 +01:00
|
|
|
* @rip: Buffer to take client address IP dotted quad
|
2011-02-13 08:37:12 +00:00
|
|
|
* @rip_len: Length of client address IP buffer
|
|
|
|
*
|
|
|
|
* This function fills in @name and @rip with the name and IP of
|
2012-04-09 15:09:01 +08:00
|
|
|
* the client connected with socket descriptor @fd. Names may be
|
|
|
|
* truncated if there is not enough room. If either cannot be
|
|
|
|
* determined, they will be returned as valid zero-length strings.
|
2011-02-13 08:37:12 +00:00
|
|
|
*/
|
|
|
|
|
2013-03-30 09:52:21 +08:00
|
|
|
LWS_VISIBLE void
|
2015-12-04 11:30:53 +08:00
|
|
|
lws_get_peer_addresses(struct lws_context *context, struct lws *wsi,
|
|
|
|
lws_sockfd_type fd, char *name, int name_len,
|
|
|
|
char *rip, int rip_len)
|
2011-02-13 08:37:12 +00:00
|
|
|
{
|
2015-11-02 20:34:12 +08:00
|
|
|
#if LWS_POSIX
|
2013-04-25 09:16:30 +08:00
|
|
|
socklen_t len;
|
2014-03-24 16:09:25 +08:00
|
|
|
#ifdef LWS_USE_IPV6
|
2014-03-24 16:09:25 +08:00
|
|
|
struct sockaddr_in6 sin6;
|
|
|
|
#endif
|
|
|
|
struct sockaddr_in sin4;
|
|
|
|
int ret = -1;
|
2015-01-28 21:03:49 +08:00
|
|
|
void *p;
|
2011-02-13 08:37:12 +00:00
|
|
|
|
|
|
|
rip[0] = '\0';
|
|
|
|
name[0] = '\0';
|
|
|
|
|
2013-01-30 08:12:20 +08:00
|
|
|
lws_latency_pre(context, wsi);
|
|
|
|
|
2014-03-24 16:09:25 +08:00
|
|
|
#ifdef LWS_USE_IPV6
|
2014-03-24 16:09:25 +08:00
|
|
|
if (LWS_IPV6_ENABLED(context)) {
|
|
|
|
len = sizeof(sin6);
|
2015-01-28 21:03:49 +08:00
|
|
|
p = &sin6;
|
2014-03-24 16:09:25 +08:00
|
|
|
} else
|
2011-03-10 18:14:01 +00:00
|
|
|
#endif
|
2014-03-24 16:09:25 +08:00
|
|
|
{
|
|
|
|
len = sizeof(sin4);
|
2015-01-28 21:03:49 +08:00
|
|
|
p = &sin4;
|
|
|
|
}
|
2011-02-13 08:37:12 +00:00
|
|
|
|
2015-01-28 21:03:49 +08:00
|
|
|
if (getpeername(fd, p, &len) < 0) {
|
|
|
|
lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
|
|
|
|
goto bail;
|
2011-02-13 08:37:12 +00:00
|
|
|
}
|
2015-01-28 21:03:49 +08:00
|
|
|
|
2015-12-04 09:23:56 +08:00
|
|
|
ret = lws_get_addresses(context, p, name, name_len, rip, rip_len);
|
2013-01-30 08:12:20 +08:00
|
|
|
|
|
|
|
bail:
|
2015-12-04 08:43:54 +08:00
|
|
|
lws_latency(context, wsi, "lws_get_peer_addresses", ret, 1);
|
2015-11-02 20:34:12 +08:00
|
|
|
#else
|
|
|
|
(void)context;
|
|
|
|
(void)wsi;
|
|
|
|
(void)fd;
|
|
|
|
(void)name;
|
|
|
|
(void)name_len;
|
|
|
|
(void)rip;
|
|
|
|
(void)rip_len;
|
|
|
|
#endif
|
2011-02-13 08:37:12 +00:00
|
|
|
}
|
2011-02-12 11:57:45 +00:00
|
|
|
|
2013-01-22 12:40:35 +08:00
|
|
|
/**
|
2015-12-04 08:43:54 +08:00
|
|
|
* lws_context_user() - get the user data associated with the context
|
2013-01-22 12:40:35 +08:00
|
|
|
* @context: Websocket context
|
|
|
|
*
|
|
|
|
* This returns the optional user allocation that can be attached to
|
|
|
|
* the context the sockets live in at context_create time. It's a way
|
|
|
|
* to let all sockets serviced in the same context share data without
|
|
|
|
* using globals statics in the user code.
|
|
|
|
*/
|
2012-10-19 11:21:56 +02:00
|
|
|
LWS_EXTERN void *
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_context_user(struct lws_context *context)
|
2012-10-19 11:21:56 +02:00
|
|
|
{
|
2013-02-11 17:13:32 +08:00
|
|
|
return context->user_space;
|
2012-10-19 11:21:56 +02:00
|
|
|
}
|
|
|
|
|
2011-01-19 13:11:55 +00:00
|
|
|
|
2014-02-15 16:36:38 +08:00
|
|
|
/**
|
2015-12-04 08:43:54 +08:00
|
|
|
* lws_callback_all_protocol() - Callback all connections using
|
2014-02-15 16:36:38 +08:00
|
|
|
* the given protocol with the given reason
|
|
|
|
*
|
|
|
|
* @protocol: Protocol whose connections will get callbacks
|
|
|
|
* @reason: Callback reason index
|
|
|
|
*/
|
|
|
|
|
|
|
|
LWS_VISIBLE int
|
2015-12-04 16:54:12 +08:00
|
|
|
lws_callback_all_protocol(const struct lws_protocols *protocol, int reason)
|
2014-02-15 16:36:38 +08:00
|
|
|
{
|
2015-12-04 11:08:32 +08:00
|
|
|
struct lws_context *context = protocol->owning_server;
|
|
|
|
struct lws *wsi;
|
2015-12-04 16:54:12 +08:00
|
|
|
int n;
|
2014-02-15 16:36:38 +08:00
|
|
|
|
|
|
|
for (n = 0; n < context->fds_count; n++) {
|
2015-01-30 10:13:01 +08:00
|
|
|
wsi = wsi_from_fd(context, context->fds[n].fd);
|
2014-02-15 16:36:38 +08:00
|
|
|
if (!wsi)
|
|
|
|
continue;
|
|
|
|
if (wsi->protocol == protocol)
|
|
|
|
protocol->callback(context, wsi,
|
2015-12-04 16:54:12 +08:00
|
|
|
reason, wsi->user_space, NULL, 0);
|
2014-02-15 16:36:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-02-14 20:25:43 +00:00
|
|
|
/**
|
2015-12-04 08:43:54 +08:00
|
|
|
* lws_set_timeout() - marks the wsi as subject to a timeout
|
2011-02-14 20:25:43 +00:00
|
|
|
*
|
|
|
|
* You will not need this unless you are doing something special
|
|
|
|
*
|
|
|
|
* @wsi: Websocket connection instance
|
|
|
|
* @reason: timeout reason
|
|
|
|
* @secs: how many seconds
|
|
|
|
*/
|
|
|
|
|
2014-02-19 09:24:17 +11:00
|
|
|
LWS_VISIBLE void
|
2015-12-04 16:54:12 +08:00
|
|
|
lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
|
2011-02-14 20:25:43 +00:00
|
|
|
{
|
2014-02-26 21:37:31 +01:00
|
|
|
time_t now;
|
2011-02-14 20:25:43 +00:00
|
|
|
|
2014-02-26 21:37:31 +01:00
|
|
|
time(&now);
|
2011-02-14 20:25:43 +00:00
|
|
|
|
2014-02-26 21:37:31 +01:00
|
|
|
wsi->pending_timeout_limit = now + secs;
|
2011-02-14 20:25:43 +00:00
|
|
|
wsi->pending_timeout = reason;
|
|
|
|
}
|
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2015-11-02 20:34:12 +08:00
|
|
|
#if LWS_POSIX
|
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
/**
|
2015-12-04 08:43:54 +08:00
|
|
|
* lws_get_socket_fd() - returns the socket file descriptor
|
2011-01-27 20:06:03 +00:00
|
|
|
*
|
|
|
|
* You will not need this unless you are doing something special
|
|
|
|
*
|
|
|
|
* @wsi: Websocket connection instance
|
|
|
|
*/
|
|
|
|
|
2013-03-30 09:52:21 +08:00
|
|
|
LWS_VISIBLE int
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_get_socket_fd(struct lws *wsi)
|
2011-01-27 20:06:03 +00:00
|
|
|
{
|
|
|
|
return wsi->sock;
|
|
|
|
}
|
|
|
|
|
2015-11-02 20:34:12 +08:00
|
|
|
#endif
|
|
|
|
|
2013-01-29 12:36:17 +08:00
|
|
|
#ifdef LWS_LATENCY
|
|
|
|
void
|
2015-12-04 11:30:53 +08:00
|
|
|
lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
|
|
|
|
int ret, int completed)
|
2013-01-29 12:36:17 +08:00
|
|
|
{
|
2014-02-26 21:37:31 +01:00
|
|
|
unsigned long long u;
|
2013-01-29 12:36:17 +08:00
|
|
|
char buf[256];
|
|
|
|
|
2014-02-26 21:37:31 +01:00
|
|
|
u = time_in_microseconds();
|
2013-01-29 12:36:17 +08:00
|
|
|
|
2014-03-31 11:01:32 +08:00
|
|
|
if (!action) {
|
2013-01-29 12:36:17 +08:00
|
|
|
wsi->latency_start = u;
|
|
|
|
if (!wsi->action_start)
|
|
|
|
wsi->action_start = u;
|
2014-03-31 11:01:32 +08:00
|
|
|
return;
|
2013-01-29 12:36:17 +08:00
|
|
|
}
|
2014-03-31 11:01:32 +08:00
|
|
|
if (completed) {
|
|
|
|
if (wsi->action_start == wsi->latency_start)
|
|
|
|
sprintf(buf,
|
2014-07-05 10:50:47 +08:00
|
|
|
"Completion first try lat %lluus: %p: ret %d: %s\n",
|
2014-03-31 11:01:32 +08:00
|
|
|
u - wsi->latency_start,
|
|
|
|
(void *)wsi, ret, action);
|
|
|
|
else
|
|
|
|
sprintf(buf,
|
2014-07-05 10:50:47 +08:00
|
|
|
"Completion %lluus: lat %lluus: %p: ret %d: %s\n",
|
2014-03-31 11:01:32 +08:00
|
|
|
u - wsi->action_start,
|
|
|
|
u - wsi->latency_start,
|
|
|
|
(void *)wsi, ret, action);
|
|
|
|
wsi->action_start = 0;
|
|
|
|
} else
|
2014-07-05 10:50:47 +08:00
|
|
|
sprintf(buf, "lat %lluus: %p: ret %d: %s\n",
|
2014-03-31 11:01:32 +08:00
|
|
|
u - wsi->latency_start, (void *)wsi, ret, action);
|
|
|
|
|
|
|
|
if (u - wsi->latency_start > context->worst_latency) {
|
|
|
|
context->worst_latency = u - wsi->latency_start;
|
|
|
|
strcpy(context->worst_latency_info, buf);
|
|
|
|
}
|
|
|
|
lwsl_latency("%s", buf);
|
2013-01-29 12:36:17 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-01-17 16:50:35 +08:00
|
|
|
|
2011-01-27 06:26:52 +00:00
|
|
|
|
2013-01-17 16:50:35 +08:00
|
|
|
/**
|
2015-12-04 08:43:54 +08:00
|
|
|
* lws_rx_flow_control() - Enable and disable socket servicing for
|
2014-10-23 15:34:26 +01:00
|
|
|
* received packets.
|
2013-01-17 16:50:35 +08:00
|
|
|
*
|
|
|
|
* If the output side of a server process becomes choked, this allows flow
|
|
|
|
* control for the input side.
|
|
|
|
*
|
|
|
|
* @wsi: Websocket connection instance to get callback for
|
|
|
|
* @enable: 0 = disable read servicing for this connection, 1 = enable
|
|
|
|
*/
|
|
|
|
|
2013-03-30 09:52:21 +08:00
|
|
|
LWS_VISIBLE int
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_rx_flow_control(struct lws *wsi, int enable)
|
2013-01-17 16:50:35 +08:00
|
|
|
{
|
2014-10-08 12:00:53 +08:00
|
|
|
if (enable == (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW))
|
2013-03-16 11:24:23 +08:00
|
|
|
return 0;
|
|
|
|
|
2015-12-04 16:54:12 +08:00
|
|
|
lwsl_info("%s: (0x%p, %d)\n", __func__, wsi, enable);
|
2014-10-08 12:00:53 +08:00
|
|
|
wsi->rxflow_change_to = LWS_RXFLOW_PENDING_CHANGE | !!enable;
|
2013-01-17 16:50:35 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-03-16 12:32:27 +08:00
|
|
|
/**
|
2015-12-04 08:43:54 +08:00
|
|
|
* lws_rx_flow_allow_all_protocol() - Allow all connections with this protocol to receive
|
2013-03-16 12:32:27 +08:00
|
|
|
*
|
|
|
|
* When the user server code realizes it can accept more input, it can
|
|
|
|
* call this to have the RX flow restriction removed from all connections using
|
|
|
|
* the given protocol.
|
|
|
|
*
|
|
|
|
* @protocol: all connections using this protocol will be allowed to receive
|
|
|
|
*/
|
|
|
|
|
2013-03-30 09:52:21 +08:00
|
|
|
LWS_VISIBLE void
|
2015-12-04 11:30:53 +08:00
|
|
|
lws_rx_flow_allow_all_protocol(const struct lws_protocols *protocol)
|
2013-03-16 12:32:27 +08:00
|
|
|
{
|
2015-12-04 11:08:32 +08:00
|
|
|
struct lws_context *context = protocol->owning_server;
|
2013-03-16 12:32:27 +08:00
|
|
|
int n;
|
2015-12-04 11:08:32 +08:00
|
|
|
struct lws *wsi;
|
2013-03-16 12:32:27 +08:00
|
|
|
|
|
|
|
for (n = 0; n < context->fds_count; n++) {
|
2015-01-30 10:13:01 +08:00
|
|
|
wsi = wsi_from_fd(context, context->fds[n].fd);
|
2013-03-16 12:32:27 +08:00
|
|
|
if (!wsi)
|
|
|
|
continue;
|
|
|
|
if (wsi->protocol == protocol)
|
2015-12-04 08:43:54 +08:00
|
|
|
lws_rx_flow_control(wsi, LWS_RXFLOW_ALLOW);
|
2013-03-16 12:32:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-17 16:50:35 +08:00
|
|
|
|
2011-01-28 10:00:18 +00:00
|
|
|
/**
|
2015-12-04 08:43:54 +08:00
|
|
|
* lws_canonical_hostname() - returns this host's hostname
|
2011-01-28 10:00:18 +00:00
|
|
|
*
|
|
|
|
* This is typically used by client code to fill in the host parameter
|
|
|
|
* when making a client connection. You can only call it after the context
|
|
|
|
* has been created.
|
|
|
|
*
|
2011-03-02 22:03:47 +00:00
|
|
|
* @context: Websocket context
|
2011-01-28 10:00:18 +00:00
|
|
|
*/
|
2013-03-30 09:52:21 +08:00
|
|
|
LWS_VISIBLE extern const char *
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_canonical_hostname(struct lws_context *context)
|
2011-01-28 10:00:18 +00:00
|
|
|
{
|
2011-03-02 22:03:47 +00:00
|
|
|
return (const char *)context->canonical_hostname;
|
2011-01-28 10:00:18 +00:00
|
|
|
}
|
|
|
|
|
2013-01-17 16:50:35 +08:00
|
|
|
int user_callback_handle_rxflow(callback_function callback_function,
|
2015-12-04 11:30:53 +08:00
|
|
|
struct lws_context *context, struct lws *wsi,
|
|
|
|
enum lws_callback_reasons reason, void *user,
|
|
|
|
void *in, size_t len)
|
2013-01-17 16:50:35 +08:00
|
|
|
{
|
|
|
|
int n;
|
|
|
|
|
|
|
|
n = callback_function(context, wsi, reason, user, in, len);
|
2013-02-10 21:21:24 +08:00
|
|
|
if (!n)
|
2015-12-04 08:43:54 +08:00
|
|
|
n = _lws_rx_flow_control(wsi);
|
2013-01-17 16:50:35 +08:00
|
|
|
|
2013-02-10 21:21:24 +08:00
|
|
|
return n;
|
2013-01-17 16:50:35 +08:00
|
|
|
}
|
|
|
|
|
2010-12-18 15:13:50 +00:00
|
|
|
|
2013-10-24 22:12:03 +08:00
|
|
|
/**
|
2015-12-04 11:08:32 +08:00
|
|
|
* lws_set_proxy() - Setups proxy to lws_context.
|
|
|
|
* @context: pointer to struct lws_context you want set proxy to
|
2013-10-24 22:12:03 +08:00
|
|
|
* @proxy: pointer to c string containing proxy in format address:port
|
|
|
|
*
|
|
|
|
* Returns 0 if proxy string was parsed and proxy was setup.
|
|
|
|
* Returns -1 if @proxy is NULL or has incorrect format.
|
|
|
|
*
|
|
|
|
* This is only required if your OS does not provide the http_proxy
|
2014-10-23 15:34:26 +01:00
|
|
|
* environment variable (eg, OSX)
|
2013-10-24 22:12:03 +08:00
|
|
|
*
|
|
|
|
* IMPORTANT! You should call this function right after creation of the
|
2015-12-04 11:08:32 +08:00
|
|
|
* lws_context and before call to connect. If you call this
|
2013-10-24 22:12:03 +08:00
|
|
|
* function after connect behavior is undefined.
|
2015-12-04 11:08:32 +08:00
|
|
|
* This function will override proxy settings made on lws_context
|
2013-10-24 22:12:03 +08:00
|
|
|
* creation with genenv() call.
|
|
|
|
*/
|
|
|
|
|
|
|
|
LWS_VISIBLE int
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_set_proxy(struct lws_context *context, const char *proxy)
|
2013-10-24 22:12:03 +08:00
|
|
|
{
|
|
|
|
char *p;
|
2015-11-08 10:15:01 +08:00
|
|
|
char authstring[96];
|
2013-10-24 22:12:03 +08:00
|
|
|
|
|
|
|
if (!proxy)
|
|
|
|
return -1;
|
|
|
|
|
2015-11-08 10:15:01 +08:00
|
|
|
p = strchr(proxy, '@');
|
|
|
|
if (p) { /* auth is around */
|
|
|
|
|
2015-11-08 12:10:26 +08:00
|
|
|
if ((unsigned int)(p - proxy) > sizeof(authstring) - 1)
|
2015-11-08 10:15:01 +08:00
|
|
|
goto auth_too_long;
|
|
|
|
|
2015-11-18 19:32:01 +08:00
|
|
|
strncpy(authstring, proxy, p - proxy);
|
2015-11-08 10:15:01 +08:00
|
|
|
// null termination not needed on input
|
|
|
|
if (lws_b64_encode_string(authstring, (p - proxy),
|
|
|
|
context->proxy_basic_auth_token,
|
|
|
|
sizeof context->proxy_basic_auth_token) < 0)
|
|
|
|
goto auth_too_long;
|
|
|
|
|
|
|
|
lwsl_notice(" Proxy auth in use\n");
|
|
|
|
|
|
|
|
proxy = p + 1;
|
|
|
|
} else
|
|
|
|
context->proxy_basic_auth_token[0] = '\0';
|
|
|
|
|
2013-10-24 22:12:03 +08:00
|
|
|
strncpy(context->http_proxy_address, proxy,
|
|
|
|
sizeof(context->http_proxy_address) - 1);
|
|
|
|
context->http_proxy_address[
|
|
|
|
sizeof(context->http_proxy_address) - 1] = '\0';
|
2015-11-08 10:15:01 +08:00
|
|
|
|
2013-10-24 22:12:03 +08:00
|
|
|
p = strchr(context->http_proxy_address, ':');
|
2015-11-08 10:15:01 +08:00
|
|
|
if (!p && !context->http_proxy_port) {
|
2013-10-24 22:12:03 +08:00
|
|
|
lwsl_err("http_proxy needs to be ads:port\n");
|
|
|
|
|
|
|
|
return -1;
|
2015-11-08 10:15:01 +08:00
|
|
|
} else {
|
|
|
|
*p = '\0';
|
|
|
|
context->http_proxy_port = atoi(p + 1);
|
2013-10-24 22:12:03 +08:00
|
|
|
}
|
2015-11-08 10:15:01 +08:00
|
|
|
|
2013-10-24 22:12:03 +08:00
|
|
|
lwsl_notice(" Proxy %s:%u\n", context->http_proxy_address,
|
|
|
|
context->http_proxy_port);
|
|
|
|
|
|
|
|
return 0;
|
2015-11-08 10:15:01 +08:00
|
|
|
|
|
|
|
auth_too_long:
|
|
|
|
lwsl_err("proxy auth too long\n");
|
|
|
|
|
|
|
|
return -1;
|
2013-10-24 22:12:03 +08:00
|
|
|
}
|
|
|
|
|
2010-12-18 15:13:50 +00:00
|
|
|
/**
|
2015-12-04 08:43:54 +08:00
|
|
|
* lws_get_protocol() - Returns a protocol pointer from a websocket
|
2010-12-19 22:13:26 +00:00
|
|
|
* connection.
|
2010-12-18 15:13:50 +00:00
|
|
|
* @wsi: pointer to struct websocket you want to know the protocol of
|
|
|
|
*
|
2010-12-19 22:13:26 +00:00
|
|
|
*
|
2013-01-29 17:57:39 +08:00
|
|
|
* Some apis can act on all live connections of a given protocol,
|
|
|
|
* this is how you can get a pointer to the active protocol if needed.
|
2010-12-18 15:13:50 +00:00
|
|
|
*/
|
2010-10-28 22:36:01 +01:00
|
|
|
|
2015-12-04 11:08:32 +08:00
|
|
|
LWS_VISIBLE const struct lws_protocols *
|
|
|
|
lws_get_protocol(struct lws *wsi)
|
2010-12-18 15:13:50 +00:00
|
|
|
{
|
|
|
|
return wsi->protocol;
|
|
|
|
}
|
|
|
|
|
2013-03-30 09:52:21 +08:00
|
|
|
LWS_VISIBLE int
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_is_final_fragment(struct lws *wsi)
|
2011-03-07 21:16:31 +00:00
|
|
|
{
|
2013-01-21 11:04:23 +08:00
|
|
|
return wsi->u.ws.final;
|
2011-03-07 21:16:31 +00:00
|
|
|
}
|
2011-11-07 17:19:25 +08:00
|
|
|
|
2013-03-30 09:52:21 +08:00
|
|
|
LWS_VISIBLE unsigned char
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_get_reserved_bits(struct lws *wsi)
|
2013-01-09 18:06:55 +08:00
|
|
|
{
|
2013-01-21 11:04:23 +08:00
|
|
|
return wsi->u.ws.rsv;
|
2013-01-09 18:06:55 +08:00
|
|
|
}
|
|
|
|
|
2013-02-18 16:30:10 +08:00
|
|
|
int
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_ensure_user_space(struct lws *wsi)
|
2011-11-07 17:19:25 +08:00
|
|
|
{
|
2014-10-22 15:37:28 +08:00
|
|
|
lwsl_info("%s: %p protocol %p\n", __func__, wsi, wsi->protocol);
|
2013-02-15 22:31:55 +08:00
|
|
|
if (!wsi->protocol)
|
2013-02-18 16:30:10 +08:00
|
|
|
return 1;
|
2013-02-15 22:31:55 +08:00
|
|
|
|
2011-11-07 17:19:25 +08:00
|
|
|
/* allocate the per-connection user memory (if any) */
|
|
|
|
|
|
|
|
if (wsi->protocol->per_session_data_size && !wsi->user_space) {
|
2014-12-04 23:59:35 +01:00
|
|
|
wsi->user_space = lws_zalloc(wsi->protocol->per_session_data_size);
|
2011-11-07 17:19:25 +08:00
|
|
|
if (wsi->user_space == NULL) {
|
2013-01-10 19:50:35 +08:00
|
|
|
lwsl_err("Out of memory for conn user space\n");
|
2013-02-18 16:30:10 +08:00
|
|
|
return 1;
|
2011-11-07 17:19:25 +08:00
|
|
|
}
|
2014-10-22 15:37:28 +08:00
|
|
|
} else
|
2015-12-04 16:54:12 +08:00
|
|
|
lwsl_info("%s: %p protocol pss %u, user_space=%d\n",
|
|
|
|
__func__, wsi, wsi->protocol->per_session_data_size,
|
|
|
|
wsi->user_space);
|
2013-02-18 16:30:10 +08:00
|
|
|
return 0;
|
2011-11-07 17:19:25 +08:00
|
|
|
}
|
2013-01-10 19:50:35 +08:00
|
|
|
|
2015-12-04 16:54:12 +08:00
|
|
|
#if LWS_POSIX
|
2014-04-03 23:34:09 +08:00
|
|
|
LWS_VISIBLE void lwsl_emit_stderr(int level, const char *line)
|
2013-01-12 09:17:42 +08:00
|
|
|
{
|
2014-02-26 21:37:31 +01:00
|
|
|
unsigned long long now;
|
2015-12-04 16:54:12 +08:00
|
|
|
char buf[300];
|
2013-01-19 11:17:56 +08:00
|
|
|
int n;
|
2013-01-10 19:50:35 +08:00
|
|
|
|
2013-01-19 11:17:56 +08:00
|
|
|
buf[0] = '\0';
|
2015-12-04 16:54:12 +08:00
|
|
|
for (n = 0; n < LLL_COUNT; n++) {
|
|
|
|
if (level != (1 << n))
|
|
|
|
continue;
|
|
|
|
now = time_in_microseconds() / 100;
|
|
|
|
sprintf(buf, "[%llu:%04d] %s: ",
|
|
|
|
(unsigned long long) now / 10000,
|
|
|
|
(int)(now % 10000), log_level_names[n]);
|
|
|
|
break;
|
|
|
|
}
|
2013-02-11 17:13:32 +08:00
|
|
|
|
2013-01-19 11:17:56 +08:00
|
|
|
fprintf(stderr, "%s%s", buf, line);
|
|
|
|
}
|
2015-12-04 16:54:12 +08:00
|
|
|
#endif
|
2013-01-19 11:12:16 +08:00
|
|
|
|
2014-12-10 18:50:28 -06:00
|
|
|
LWS_VISIBLE void _lws_logv(int filter, const char *format, va_list vl)
|
2013-01-19 11:17:56 +08:00
|
|
|
{
|
|
|
|
char buf[256];
|
|
|
|
|
|
|
|
if (!(log_level & filter))
|
|
|
|
return;
|
2013-01-10 19:50:35 +08:00
|
|
|
|
2014-12-10 18:50:28 -06:00
|
|
|
vsnprintf(buf, sizeof(buf), format, vl);
|
2013-02-11 17:13:32 +08:00
|
|
|
buf[sizeof(buf) - 1] = '\0';
|
2013-01-12 09:17:42 +08:00
|
|
|
|
2013-01-19 11:17:56 +08:00
|
|
|
lwsl_emit(filter, buf);
|
2013-01-10 19:50:35 +08:00
|
|
|
}
|
|
|
|
|
2014-12-10 18:50:28 -06:00
|
|
|
LWS_VISIBLE void _lws_log(int filter, const char *format, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
_lws_logv(filter, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2013-01-10 19:50:35 +08:00
|
|
|
/**
|
|
|
|
* lws_set_log_level() - Set the logging bitfield
|
|
|
|
* @level: OR together the LLL_ debug contexts you want output from
|
2013-01-12 09:17:42 +08:00
|
|
|
* @log_emit_function: NULL to leave it as it is, or a user-supplied
|
|
|
|
* function to perform log string emission instead of
|
|
|
|
* the default stderr one.
|
2013-01-10 19:50:35 +08:00
|
|
|
*
|
2013-02-19 10:01:48 +08:00
|
|
|
* log level defaults to "err", "warn" and "notice" contexts enabled and
|
2013-01-12 09:17:42 +08:00
|
|
|
* emission on stderr.
|
2013-01-10 19:50:35 +08:00
|
|
|
*/
|
|
|
|
|
2015-12-04 11:30:53 +08:00
|
|
|
LWS_VISIBLE void lws_set_log_level(int level,
|
2015-12-04 16:54:12 +08:00
|
|
|
void (*func)(int level, const char *line))
|
2013-01-10 19:50:35 +08:00
|
|
|
{
|
|
|
|
log_level = level;
|
2015-12-04 16:54:12 +08:00
|
|
|
if (func)
|
|
|
|
lwsl_emit = func;
|
2014-04-27 13:28:22 +02:00
|
|
|
}
|
2014-08-16 09:54:27 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* lws_use_ssl() - Find out if connection is using SSL
|
|
|
|
* @wsi: websocket connection to check
|
|
|
|
*
|
|
|
|
* Returns 0 if the connection is not using SSL, 1 if using SSL and
|
|
|
|
* using verified cert, and 2 if using SSL but the cert was not
|
|
|
|
* checked (appears for client wsi told to skip check on connection)
|
|
|
|
*/
|
|
|
|
LWS_VISIBLE int
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_is_ssl(struct lws *wsi)
|
2014-08-16 09:54:27 +08:00
|
|
|
{
|
2014-08-19 08:41:26 +08:00
|
|
|
#ifdef LWS_OPENSSL_SUPPORT
|
2014-08-16 09:54:27 +08:00
|
|
|
return wsi->use_ssl;
|
2014-08-19 08:41:26 +08:00
|
|
|
#else
|
2015-11-02 13:10:33 +08:00
|
|
|
(void)wsi;
|
2014-08-19 08:41:26 +08:00
|
|
|
return 0;
|
|
|
|
#endif
|
2014-08-16 09:54:27 +08:00
|
|
|
}
|
2014-08-18 22:49:39 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* lws_partial_buffered() - find out if lws buffered the last write
|
|
|
|
* @wsi: websocket connection to check
|
|
|
|
*
|
2015-12-04 08:43:54 +08:00
|
|
|
* Returns 1 if you cannot use lws_write because the last
|
2014-08-18 22:49:39 +08:00
|
|
|
* write on this connection is still buffered, and can't be cleared without
|
|
|
|
* returning to the service loop and waiting for the connection to be
|
|
|
|
* writeable again.
|
|
|
|
*
|
2015-12-04 08:43:54 +08:00
|
|
|
* If you will try to do >1 lws_write call inside a single
|
2014-08-18 22:49:39 +08:00
|
|
|
* WRITEABLE callback, you must check this after every write and bail if
|
|
|
|
* set, ask for a new writeable callback and continue writing from there.
|
|
|
|
*
|
|
|
|
* This is never set at the start of a writeable callback, but any write
|
|
|
|
* may set it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
LWS_VISIBLE int
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_partial_buffered(struct lws *wsi)
|
2014-08-18 22:49:39 +08:00
|
|
|
{
|
|
|
|
return !!wsi->truncated_send_len;
|
|
|
|
}
|
2014-10-08 12:00:53 +08:00
|
|
|
|
2015-12-04 11:08:32 +08:00
|
|
|
void lws_set_protocol_write_pending(struct lws_context *context,
|
|
|
|
struct lws *wsi,
|
2014-10-08 12:00:53 +08:00
|
|
|
enum lws_pending_protocol_send pend)
|
|
|
|
{
|
2014-10-29 09:39:08 +08:00
|
|
|
lwsl_info("setting pps %d\n", pend);
|
2014-10-08 12:00:53 +08:00
|
|
|
|
|
|
|
if (wsi->pps)
|
|
|
|
lwsl_err("pps overwrite\n");
|
|
|
|
wsi->pps = pend;
|
2015-12-04 08:43:54 +08:00
|
|
|
lws_rx_flow_control(wsi, 0);
|
|
|
|
lws_callback_on_writable(context, wsi);
|
2014-10-18 18:52:39 +08:00
|
|
|
}
|
2014-10-29 09:39:08 +08:00
|
|
|
|
|
|
|
LWS_VISIBLE size_t
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_get_peer_write_allowance(struct lws *wsi)
|
2014-10-29 09:39:08 +08:00
|
|
|
{
|
|
|
|
#ifdef LWS_USE_HTTP2
|
|
|
|
/* only if we are using HTTP2 on this connection */
|
|
|
|
if (wsi->mode != LWS_CONNMODE_HTTP2_SERVING)
|
|
|
|
return -1;
|
|
|
|
/* user is only interested in how much he can send, or that he can't */
|
|
|
|
if (wsi->u.http2.tx_credit <= 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return wsi->u.http2.tx_credit;
|
|
|
|
#else
|
2015-11-02 13:10:33 +08:00
|
|
|
(void)wsi;
|
2014-10-29 09:39:08 +08:00
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
}
|
2014-11-08 11:18:47 +08:00
|
|
|
|
|
|
|
LWS_VISIBLE void
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_union_transition(struct lws *wsi, enum connection_mode mode)
|
2014-11-08 11:18:47 +08:00
|
|
|
{
|
|
|
|
memset(&wsi->u, 0, sizeof(wsi->u));
|
|
|
|
wsi->mode = mode;
|
|
|
|
}
|
2015-12-04 10:39:23 +08:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef LWS_WITH_OLD_API_WRAPPERS
|
|
|
|
|
|
|
|
/*
|
|
|
|
* To maintain .so abi, also produce wrappers using old api naming.
|
|
|
|
*
|
|
|
|
* This is disabled by default, use "LWS_WITH_OLD_API_WRAPPERS" on cmake to
|
|
|
|
* enable.
|
|
|
|
*
|
|
|
|
* You only need these if you have existing binary applications using the old
|
|
|
|
* api names and you don't want to / can't recompile them against new lws.
|
|
|
|
* With these new lws .so is compatible with old and new api names.
|
|
|
|
*
|
|
|
|
* If you can recompile your application (using old api names still) against
|
|
|
|
* current lws, you don't need these compatibility helpers since
|
|
|
|
* libwebsockets.h will map them at compile time.
|
|
|
|
*/
|
|
|
|
|
2015-12-04 11:08:32 +08:00
|
|
|
#undef libwebsocket
|
|
|
|
|
2015-12-04 10:39:23 +08:00
|
|
|
#undef libwebsocket_create_context
|
2015-12-04 11:08:32 +08:00
|
|
|
LWS_VISIBLE LWS_EXTERN struct lws_context *
|
2015-12-04 10:39:23 +08:00
|
|
|
libwebsocket_create_context(struct lws_context_creation_info *info)
|
|
|
|
{
|
|
|
|
return lws_create_context(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_set_proxy
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_set_proxy(struct lws_context *context, const char *proxy)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_set_proxy(context, proxy);
|
|
|
|
}
|
|
|
|
|
2015-12-04 11:57:48 +08:00
|
|
|
#undef libwebsocket_context_destroy
|
2015-12-04 10:39:23 +08:00
|
|
|
LWS_VISIBLE LWS_EXTERN void
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_context_destroy(struct lws_context *context)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
lws_context_destroy(context);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_service
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_service(struct lws_context *context, int timeout_ms)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_service(context, timeout_ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_cancel_service
|
|
|
|
LWS_VISIBLE LWS_EXTERN void
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_cancel_service(struct lws_context *context)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
lws_cancel_service(context);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef LWS_USE_LIBEV
|
|
|
|
#undef libwebsocket_sigint_cfg
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 16:54:12 +08:00
|
|
|
libwebsocket_sigint_cfg(struct lws_context *context, int use_ev_sigint,
|
|
|
|
lws_ev_signal_cb* cb)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_sigint_cfg(context, use_ev_sigint, cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_initloop
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_initloop(struct lws_context *context, struct ev_loop *loop)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_initloop(context, loop);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_sigint_cb
|
|
|
|
LWS_VISIBLE void
|
|
|
|
libwebsocket_sigint_cb(
|
|
|
|
struct ev_loop *loop, struct ev_signal *watcher, int revents)
|
|
|
|
{
|
|
|
|
lws_sigint_cb(loop, watcher, revents);
|
|
|
|
}
|
|
|
|
#endif /* LWS_USE_LIBEV */
|
|
|
|
|
|
|
|
#undef libwebsocket_service_fd
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_service_fd(struct lws_context *context,
|
|
|
|
struct lws_pollfd *pollfd)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_service_fd(context, pollfd);
|
|
|
|
}
|
|
|
|
|
2015-12-04 11:57:48 +08:00
|
|
|
#undef libwebsocket_context_user
|
2015-12-04 10:39:23 +08:00
|
|
|
LWS_VISIBLE LWS_EXTERN void *
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_context_user(struct lws_context *context)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_context_user(context);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_set_timeout
|
|
|
|
LWS_VISIBLE LWS_EXTERN void
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_set_timeout(struct lws *wsi,
|
2015-12-04 10:39:23 +08:00
|
|
|
enum pending_timeout reason, int secs)
|
|
|
|
{
|
|
|
|
lws_set_timeout(wsi, reason, secs);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_write
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_write(struct lws *wsi, unsigned char *buf, size_t len,
|
2015-12-04 10:39:23 +08:00
|
|
|
enum lws_write_protocol protocol)
|
|
|
|
{
|
|
|
|
return lws_write(wsi, buf, len, protocol);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsockets_serve_http_file_fragment
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsockets_serve_http_file_fragment(struct lws_context *context,
|
|
|
|
struct lws *wsi)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_serve_http_file_fragment(context, wsi);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsockets_serve_http_file
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsockets_serve_http_file(struct lws_context *context,
|
|
|
|
struct lws *wsi, const char *file,
|
2015-12-04 10:39:23 +08:00
|
|
|
const char *content_type, const char *other_headers,
|
|
|
|
int other_headers_len)
|
|
|
|
{
|
|
|
|
return lws_serve_http_file(context, wsi, file, content_type,
|
|
|
|
other_headers, other_headers_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsockets_return_http_status
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
|
|
|
libwebsockets_return_http_status(
|
2015-12-04 11:08:32 +08:00
|
|
|
struct lws_context *context,
|
|
|
|
struct lws *wsi, unsigned int code,
|
2015-12-04 10:39:23 +08:00
|
|
|
const char *html_body)
|
|
|
|
{
|
|
|
|
return lws_return_http_status(context, wsi, code, html_body);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsockets_get_protocol
|
2015-12-04 11:08:32 +08:00
|
|
|
LWS_VISIBLE LWS_EXTERN const struct lws_protocols *
|
|
|
|
libwebsockets_get_protocol(struct lws *wsi)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_get_protocol(wsi);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_callback_on_writable_all_protocol
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
|
|
|
libwebsocket_callback_on_writable_all_protocol(
|
2015-12-04 11:08:32 +08:00
|
|
|
const struct lws_protocols *protocol)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_callback_on_writable_all_protocol(protocol);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_callback_on_writable
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_callback_on_writable(struct lws_context *context,
|
|
|
|
struct lws *wsi)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_callback_on_writable(context, wsi);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_callback_all_protocol
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
|
|
|
libwebsocket_callback_all_protocol(
|
2015-12-04 11:08:32 +08:00
|
|
|
const struct lws_protocols *protocol, int reason)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_callback_all_protocol(protocol, reason);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_get_socket_fd
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_get_socket_fd(struct lws *wsi)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_get_socket_fd(wsi);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_is_final_fragment
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_is_final_fragment(struct lws *wsi)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_is_final_fragment(wsi);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_get_reserved_bits
|
|
|
|
LWS_VISIBLE LWS_EXTERN unsigned char
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_get_reserved_bits(struct lws *wsi)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_get_reserved_bits(wsi);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_rx_flow_control
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_rx_flow_control(struct lws *wsi, int enable)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_rx_flow_control(wsi, enable);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_rx_flow_allow_all_protocol
|
|
|
|
LWS_VISIBLE LWS_EXTERN void
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_rx_flow_allow_all_protocol(const struct lws_protocols *protocol)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
lws_rx_flow_allow_all_protocol(protocol);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsockets_remaining_packet_payload
|
|
|
|
LWS_VISIBLE LWS_EXTERN size_t
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsockets_remaining_packet_payload(struct lws *wsi)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_remaining_packet_payload(wsi);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_client_connect
|
2015-12-04 11:08:32 +08:00
|
|
|
LWS_VISIBLE LWS_EXTERN struct lws *
|
|
|
|
libwebsocket_client_connect(struct lws_context *clients,
|
2015-12-04 10:39:23 +08:00
|
|
|
const char *address,
|
|
|
|
int port,
|
|
|
|
int ssl_connection,
|
|
|
|
const char *path,
|
|
|
|
const char *host,
|
|
|
|
const char *origin,
|
|
|
|
const char *protocol,
|
|
|
|
int ietf_version_or_minus_one)
|
|
|
|
{
|
|
|
|
return lws_client_connect(clients, address, port, ssl_connection,
|
|
|
|
path, host, origin, protocol, ietf_version_or_minus_one);
|
|
|
|
}
|
2015-12-04 11:08:32 +08:00
|
|
|
LWS_VISIBLE LWS_EXTERN struct lws *
|
|
|
|
libwebsocket_client_connect_extended(struct lws_context *clients,
|
2015-12-04 10:39:23 +08:00
|
|
|
const char *address,
|
|
|
|
int port,
|
|
|
|
int ssl_connection,
|
|
|
|
const char *path,
|
|
|
|
const char *host,
|
|
|
|
const char *origin,
|
|
|
|
const char *protocol,
|
|
|
|
int ietf_version_or_minus_one, void *userdata)
|
|
|
|
{
|
|
|
|
return lws_client_connect_extended(clients, address, port, ssl_connection,
|
|
|
|
path, host, origin, protocol, ietf_version_or_minus_one,
|
|
|
|
userdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsocket_canonical_hostname
|
|
|
|
LWS_VISIBLE LWS_EXTERN const char *
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_canonical_hostname(struct lws_context *context)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_canonical_hostname(context);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsockets_get_peer_addresses
|
|
|
|
LWS_VISIBLE LWS_EXTERN void
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsockets_get_peer_addresses(struct lws_context *context,
|
|
|
|
struct lws *wsi, lws_sockfd_type fd, char *name,
|
2015-12-04 10:39:23 +08:00
|
|
|
int name_len, char *rip, int rip_len)
|
|
|
|
{
|
|
|
|
lws_get_peer_addresses(context, wsi, fd, name, name_len, rip, rip_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef libwebsockets_get_random
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsockets_get_random(struct lws_context *context, void *buf, int len)
|
2015-12-04 10:39:23 +08:00
|
|
|
{
|
|
|
|
return lws_get_random(context, buf, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef LWS_SHA1_USE_OPENSSL_NAME
|
|
|
|
#undef libwebsockets_SHA1
|
|
|
|
LWS_VISIBLE LWS_EXTERN unsigned char *
|
|
|
|
libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md)
|
|
|
|
{
|
|
|
|
return lws_SHA1(d, n, md);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#undef libwebsocket_read
|
|
|
|
LWS_VISIBLE LWS_EXTERN int
|
2015-12-04 11:08:32 +08:00
|
|
|
libwebsocket_read(struct lws_context *context, struct lws *wsi,
|
2015-12-04 10:39:23 +08:00
|
|
|
unsigned char *buf, size_t len)
|
|
|
|
{
|
|
|
|
return lws_read(context, wsi, buf, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef LWS_NO_EXTENSIONS
|
|
|
|
#undef libwebsocket_get_internal_extensions
|
2015-12-04 11:08:32 +08:00
|
|
|
LWS_VISIBLE LWS_EXTERN struct lws_extension *
|
2015-12-04 10:39:23 +08:00
|
|
|
libwebsocket_get_internal_extensions()
|
|
|
|
{
|
|
|
|
return lws_get_internal_extensions();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|