mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
style cleanup
This brings the library sources into compliance with checkpatch style except for three or four exceptions like WIN32 related stuff and one long string constant I don't want to break into multiple sprintf calls. There should be no functional or compilability change from all this (hopefully). Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
ad68639a7b
commit
b5b23199f6
18 changed files with 1165 additions and 971 deletions
|
@ -28,8 +28,12 @@ struct libwebsocket *__libwebsocket_client_connect_2(
|
|||
|
||||
/* OK from now on we talk via the proxy, so connect to that */
|
||||
|
||||
/* (will overwrite existing pointer, leaving old string/frag there but unreferenced) */
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, context->http_proxy_address))
|
||||
/*
|
||||
* (will overwrite existing pointer,
|
||||
* leaving old string/frag there but unreferenced)
|
||||
*/
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
|
||||
context->http_proxy_address))
|
||||
goto oom4;
|
||||
wsi->u.hdr.c_port = context->http_proxy_port;
|
||||
}
|
||||
|
@ -89,7 +93,8 @@ struct libwebsocket *__libwebsocket_client_connect_2(
|
|||
}
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE, AWAITING_TIMEOUT);
|
||||
PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY;
|
||||
|
||||
|
@ -180,7 +185,7 @@ libwebsocket_client_connect(struct libwebsocket_context *context,
|
|||
if (wsi == NULL)
|
||||
goto bail1;
|
||||
|
||||
memset(wsi, 0, sizeof *wsi);
|
||||
memset(wsi, 0, sizeof(*wsi));
|
||||
|
||||
/* -1 means just use latest supported */
|
||||
|
||||
|
@ -220,14 +225,16 @@ libwebsocket_client_connect(struct libwebsocket_context *context,
|
|||
goto bail1;
|
||||
|
||||
if (origin)
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN, origin))
|
||||
if (lws_hdr_simple_create(wsi,
|
||||
_WSI_TOKEN_CLIENT_ORIGIN, origin))
|
||||
goto bail1;
|
||||
/*
|
||||
* this is a list of protocols we tell the server we're okay with
|
||||
* stash it for later when we compare server response with it
|
||||
*/
|
||||
if (protocol)
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS, protocol))
|
||||
if (lws_hdr_simple_create(wsi,
|
||||
_WSI_TOKEN_CLIENT_SENT_PROTOCOLS, protocol))
|
||||
goto bail1;
|
||||
|
||||
wsi->protocol = &context->protocols[0];
|
||||
|
@ -259,7 +266,8 @@ libwebsocket_client_connect(struct libwebsocket_context *context,
|
|||
lwsl_client("libwebsocket_client_connect: ext handling conn\n");
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE, AWAITING_TIMEOUT);
|
||||
PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT;
|
||||
return wsi;
|
||||
|
@ -292,7 +300,7 @@ bail:
|
|||
* the server, or just one. The server will pick the one it
|
||||
* likes best.
|
||||
* @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
|
||||
* protocol supported, or the specific protocol ordinal
|
||||
* protocol supported, or the specific protocol ordinal
|
||||
* @userdata: Pre-allocated user data
|
||||
*
|
||||
* This function creates a connection to a remote server
|
||||
|
@ -308,13 +316,15 @@ libwebsocket_client_connect_extended(struct libwebsocket_context *context,
|
|||
const char *origin,
|
||||
const char *protocol,
|
||||
int ietf_version_or_minus_one,
|
||||
void *userdata)
|
||||
void *userdata)
|
||||
{
|
||||
struct libwebsocket *ws =
|
||||
libwebsocket_client_connect(context, address, port, ssl_connection, path, host, origin, protocol, ietf_version_or_minus_one) ;
|
||||
libwebsocket_client_connect(context, address, port,
|
||||
ssl_connection, path, host, origin, protocol,
|
||||
ietf_version_or_minus_one);
|
||||
|
||||
if (ws && !ws->user_space && userdata)
|
||||
ws->user_space = userdata ;
|
||||
|
||||
return ws ;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,6 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
|||
int m;
|
||||
#endif
|
||||
|
||||
// lwsl_parser(" CRX: %02X %d\n", c, wsi->lws_rx_parse_state);
|
||||
|
||||
switch (wsi->lws_rx_parse_state) {
|
||||
case LWS_RXPS_NEW:
|
||||
|
||||
|
@ -45,15 +43,15 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
|||
switch (wsi->u.ws.opcode) {
|
||||
case LWS_WS_OPCODE_07__TEXT_FRAME:
|
||||
case LWS_WS_OPCODE_07__BINARY_FRAME:
|
||||
wsi->u.ws.frame_is_binary = wsi->u.ws.opcode == LWS_WS_OPCODE_07__BINARY_FRAME;
|
||||
wsi->u.ws.frame_is_binary = wsi->u.ws.opcode ==
|
||||
LWS_WS_OPCODE_07__BINARY_FRAME;
|
||||
break;
|
||||
}
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
|
||||
break;
|
||||
|
||||
default:
|
||||
lwsl_err("client_rx_sm doesn't know how "
|
||||
"to handle spec version %02d\n",
|
||||
lwsl_err("unknown spec version %02d\n",
|
||||
wsi->ietf_spec_revision);
|
||||
break;
|
||||
}
|
||||
|
@ -228,13 +226,15 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
|||
else
|
||||
wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
|
||||
(wsi->u.ws.rx_user_buffer_head++)] =
|
||||
c ^ wsi->u.ws.frame_masking_nonce_04[(wsi->u.ws.frame_mask_index++) & 3];
|
||||
c ^ wsi->u.ws.frame_masking_nonce_04[
|
||||
(wsi->u.ws.frame_mask_index++) & 3];
|
||||
|
||||
if (--wsi->u.ws.rx_packet_length == 0) {
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
if (wsi->u.ws.rx_user_buffer_head != wsi->protocol->rx_buffer_size)
|
||||
if (wsi->u.ws.rx_user_buffer_head !=
|
||||
wsi->protocol->rx_buffer_size)
|
||||
break;
|
||||
spill:
|
||||
|
||||
|
@ -256,12 +256,14 @@ spill:
|
|||
lwsl_parser("seen server's close ack\n");
|
||||
return -1;
|
||||
}
|
||||
lwsl_parser("client sees server close packet len = %d\n", wsi->u.ws.rx_user_buffer_head);
|
||||
lwsl_parser("client sees server close len = %d\n",
|
||||
wsi->u.ws.rx_user_buffer_head);
|
||||
/* parrot the close packet payload back */
|
||||
n = libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head, LWS_WRITE_CLOSE);
|
||||
lwsl_parser("client writing close ack returned %d\n", n);
|
||||
&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head, LWS_WRITE_CLOSE);
|
||||
lwsl_parser("client send close ack returned %d\n", n);
|
||||
wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
|
||||
/* close the connection */
|
||||
return -1;
|
||||
|
@ -270,14 +272,17 @@ spill:
|
|||
lwsl_info("client received ping, doing pong\n");
|
||||
/* parrot the ping packet payload back as a pong*/
|
||||
n = libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head, LWS_WRITE_PONG);
|
||||
&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head,
|
||||
LWS_WRITE_PONG);
|
||||
handled = 1;
|
||||
break;
|
||||
|
||||
case LWS_WS_OPCODE_07__PONG:
|
||||
lwsl_info("client receied pong\n");
|
||||
lwsl_hexdump(&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
lwsl_hexdump(&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head);
|
||||
|
||||
/* issue it */
|
||||
|
@ -291,7 +296,7 @@ spill:
|
|||
|
||||
default:
|
||||
|
||||
lwsl_parser("Reserved opcode 0x%2X\n", wsi->u.ws.opcode);
|
||||
lwsl_parser("Reserved opc 0x%2X\n", wsi->u.ws.opcode);
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
/*
|
||||
* It's something special we can't understand here.
|
||||
|
@ -318,8 +323,8 @@ spill:
|
|||
#else
|
||||
{
|
||||
#endif
|
||||
lwsl_ext("Unhandled extended opcode "
|
||||
"0x%x - ignoring frame\n", wsi->u.ws.opcode);
|
||||
lwsl_ext("Unhandled ext opc 0x%x\n",
|
||||
wsi->u.ws.opcode);
|
||||
wsi->u.ws.rx_user_buffer_head = 0;
|
||||
|
||||
return 0;
|
||||
|
@ -349,27 +354,31 @@ spill:
|
|||
&eff_buf, 0);
|
||||
if (m < 0) {
|
||||
lwsl_ext(
|
||||
"Extension '%s' failed to handle payload!\n",
|
||||
wsi->active_extensions[n]->name);
|
||||
"Ext '%s' failed to handle payload!\n",
|
||||
wsi->active_extensions[n]->name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (eff_buf.token_len > 0) {
|
||||
eff_buf.token[eff_buf.token_len] = '\0';
|
||||
if (eff_buf.token_len <= 0)
|
||||
goto already_done;
|
||||
|
||||
if (wsi->protocol->callback) {
|
||||
if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
|
||||
lwsl_info("Client doing pong callback\n");
|
||||
wsi->protocol->callback(
|
||||
wsi->protocol->owning_server,
|
||||
wsi,
|
||||
eff_buf.token[eff_buf.token_len] = '\0';
|
||||
|
||||
if (!wsi->protocol->callback)
|
||||
goto already_done;
|
||||
|
||||
if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
|
||||
lwsl_info("Client doing pong callback\n");
|
||||
|
||||
wsi->protocol->callback(
|
||||
wsi->protocol->owning_server,
|
||||
wsi,
|
||||
(enum libwebsocket_callback_reasons)callback_action,
|
||||
wsi->user_space,
|
||||
eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
}
|
||||
}
|
||||
wsi->user_space,
|
||||
eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
|
||||
already_done:
|
||||
wsi->u.ws.rx_user_buffer_head = 0;
|
||||
break;
|
||||
|
@ -382,8 +391,7 @@ already_done:
|
|||
|
||||
illegal_ctl_length:
|
||||
|
||||
lwsl_warn("Control frame asking for "
|
||||
"extended length is illegal\n");
|
||||
lwsl_warn("Control frame asking for extended length is illegal\n");
|
||||
/* kill the connection */
|
||||
return -1;
|
||||
|
||||
|
|
187
lib/client.c
187
lib/client.c
|
@ -35,11 +35,8 @@
|
|||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
extern int openssl_websocket_private_data_index;
|
||||
#endif
|
||||
|
||||
int lws_client_socket_service(struct libwebsocket_context *context, struct libwebsocket *wsi, struct pollfd *pollfd)
|
||||
int lws_client_socket_service(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct pollfd *pollfd)
|
||||
{
|
||||
int n;
|
||||
char *p = (char *)&context->service_buffer[0];
|
||||
|
@ -63,7 +60,7 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe
|
|||
}
|
||||
|
||||
n = recv(wsi->sock, context->service_buffer,
|
||||
sizeof context->service_buffer, 0);
|
||||
sizeof(context->service_buffer), 0);
|
||||
if (n < 0) {
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
|
@ -75,7 +72,7 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe
|
|||
if (strcmp((char *)context->service_buffer, "HTTP/1.0 200 ")) {
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
lwsl_err("ERROR from proxy: %s\n", context->service_buffer);
|
||||
lwsl_err("ERROR proxy: %s\n", context->service_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -106,31 +103,35 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe
|
|||
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
|
||||
(void *)(long)wsi->sock, NULL, POLLOUT);
|
||||
|
||||
/* we can retry this... so just cook the SSL BIO the first time */
|
||||
/* we can retry this... just cook the SSL BIO the first time */
|
||||
|
||||
if (wsi->use_ssl && !wsi->ssl) {
|
||||
|
||||
wsi->ssl = SSL_new(context->ssl_client_ctx);
|
||||
|
||||
#ifdef USE_CYASSL
|
||||
/* CyaSSL does certificate verification differently from OpenSSL.
|
||||
* If we should ignore the certificate, we need to set this before
|
||||
* SSL_new and SSL_connect is called. Otherwise the connect will
|
||||
* simply fail with error code -155 */
|
||||
if (wsi->use_ssl == 2) {
|
||||
CyaSSL_set_verify(wsi->ssl, SSL_VERIFY_NONE, NULL);
|
||||
}
|
||||
#endif // USE_CYASSL
|
||||
|
||||
wsi->client_bio = BIO_new_socket(wsi->sock, BIO_NOCLOSE);
|
||||
#ifdef USE_CYASSL
|
||||
/*
|
||||
* CyaSSL does certificate verification differently
|
||||
* from OpenSSL.
|
||||
* If we should ignore the certificate, we need to set
|
||||
* this before SSL_new and SSL_connect is called.
|
||||
* Otherwise the connect will simply fail with error
|
||||
* code -155
|
||||
*/
|
||||
if (wsi->use_ssl == 2)
|
||||
CyaSSL_set_verify(wsi->ssl,
|
||||
SSL_VERIFY_NONE, NULL);
|
||||
#endif /* USE_CYASSL */
|
||||
|
||||
wsi->client_bio =
|
||||
BIO_new_socket(wsi->sock, BIO_NOCLOSE);
|
||||
SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
|
||||
|
||||
#ifdef USE_CYASSL
|
||||
#ifdef USE_CYASSL
|
||||
CyaSSL_set_using_nonblock(wsi->ssl, 1);
|
||||
#else
|
||||
#else
|
||||
BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
SSL_set_ex_data(wsi->ssl,
|
||||
openssl_websocket_private_data_index,
|
||||
|
@ -140,7 +141,9 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe
|
|||
if (wsi->use_ssl) {
|
||||
lws_latency_pre(context, wsi);
|
||||
n = SSL_connect(wsi->ssl);
|
||||
lws_latency(context, wsi, "SSL_connect LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE", n, n > 0);
|
||||
lws_latency(context, wsi,
|
||||
"SSL_connect LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE",
|
||||
n, n > 0);
|
||||
|
||||
if (n < 0) {
|
||||
n = SSL_get_error(wsi->ssl, n);
|
||||
|
@ -148,18 +151,22 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe
|
|||
if (n == SSL_ERROR_WANT_READ ||
|
||||
n == SSL_ERROR_WANT_WRITE) {
|
||||
/*
|
||||
* wants us to retry connect due to state of the
|
||||
* underlying ssl layer... but since it may be
|
||||
* stalled on blocked write, no incoming data may
|
||||
* arrive to trigger the retry. Force (possibly
|
||||
* many if the SSL state persists in returning the
|
||||
* condition code, but other sockets are getting
|
||||
* serviced inbetweentimes) us to get called back
|
||||
* when writable.
|
||||
* wants us to retry connect due to
|
||||
* state of the underlying ssl layer...
|
||||
* but since it may be stalled on
|
||||
* blocked write, no incoming data may
|
||||
* arrive to trigger the retry.
|
||||
* Force (possibly many times if the SSL
|
||||
* state persists in returning the
|
||||
* condition code, but other sockets
|
||||
* are getting serviced inbetweentimes)
|
||||
* us to get called back when writable.
|
||||
*/
|
||||
|
||||
lwsl_info("SSL_connect -> SSL_ERROR_WANT_... retrying\n");
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
lwsl_info(
|
||||
"SSL_connect WANT_... retrying\n");
|
||||
libwebsocket_callback_on_writable(
|
||||
context, wsi);
|
||||
|
||||
return 0; /* no error */
|
||||
}
|
||||
|
@ -174,33 +181,38 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe
|
|||
|
||||
lwsl_err("SSL connect error %s\n",
|
||||
ERR_error_string(ERR_get_error(),
|
||||
(char *)context->service_buffer));
|
||||
(char *)context->service_buffer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef USE_CYASSL
|
||||
/* See note above about CyaSSL certificate verification */
|
||||
/*
|
||||
* See comment above about CyaSSL certificate
|
||||
* verification
|
||||
*/
|
||||
lws_latency_pre(context, wsi);
|
||||
n = SSL_get_verify_result(wsi->ssl);
|
||||
lws_latency(context, wsi, "SSL_get_verify_result LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE", n, n > 0);
|
||||
lws_latency(context, wsi,
|
||||
"SSL_get_verify_result LWS_CONNMODE..HANDSHAKE",
|
||||
n, n > 0);
|
||||
if ((n != X509_V_OK) && (
|
||||
n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
|
||||
wsi->use_ssl != 2)) {
|
||||
|
||||
lwsl_err("server's cert didn't "
|
||||
"look good %d\n", n);
|
||||
lwsl_err(
|
||||
"server's cert didn't look good %d\n", n);
|
||||
libwebsocket_close_and_free_session(context,
|
||||
wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
}
|
||||
#endif // USE_CYASSL
|
||||
#endif /* USE_CYASSL */
|
||||
} else
|
||||
wsi->ssl = NULL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
p = libwebsockets_generate_client_handshake(context, wsi, p);
|
||||
if (p == NULL) {
|
||||
lwsl_err("Failed to generate handshake for client, closing it\n");
|
||||
lwsl_err("Failed to generate handshake for client\n");
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
|
@ -209,13 +221,17 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe
|
|||
/* send our request to the server */
|
||||
|
||||
lws_latency_pre(context, wsi);
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
if (wsi->use_ssl)
|
||||
n = SSL_write(wsi->ssl, context->service_buffer, p - (char *)context->service_buffer);
|
||||
n = SSL_write(wsi->ssl, context->service_buffer,
|
||||
p - (char *)context->service_buffer);
|
||||
else
|
||||
#endif
|
||||
n = send(wsi->sock, context->service_buffer, p - (char *)context->service_buffer, 0);
|
||||
lws_latency(context, wsi, "send or SSL_write LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE", n, n >= 0);
|
||||
#endif
|
||||
n = send(wsi->sock, context->service_buffer,
|
||||
p - (char *)context->service_buffer, 0);
|
||||
lws_latency(context, wsi,
|
||||
"send or SSL_write LWS_CONNMODE...HANDSHAKE",
|
||||
n, n >= 0);
|
||||
|
||||
if (n < 0) {
|
||||
lwsl_debug("ERROR writing to client socket\n");
|
||||
|
@ -228,8 +244,8 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe
|
|||
wsi->u.hdr.lextable_pos = 0;
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, AWAITING_TIMEOUT);
|
||||
|
||||
PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
|
||||
AWAITING_TIMEOUT);
|
||||
break;
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
|
||||
|
@ -268,14 +284,15 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe
|
|||
*/
|
||||
|
||||
len = 1;
|
||||
while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE && len > 0) {
|
||||
while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE &&
|
||||
len > 0) {
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
if (wsi->use_ssl) {
|
||||
len = SSL_read(wsi->ssl, &c, 1);
|
||||
if (len < 0) {
|
||||
n = SSL_get_error(wsi->ssl, len);
|
||||
if (n == SSL_ERROR_WANT_READ ||
|
||||
n == SSL_ERROR_WANT_WRITE)
|
||||
n == SSL_ERROR_WANT_WRITE)
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
|
@ -309,7 +326,8 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe
|
|||
return lws_client_interpret_server_handshake(context, wsi);
|
||||
|
||||
bail3:
|
||||
lwsl_info("closing connection at LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY\n");
|
||||
lwsl_info(
|
||||
"closing connection at LWS_CONNMODE...SERVER_REPLY\n");
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
|
@ -371,8 +389,8 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
|||
if (!p)
|
||||
goto bail3;
|
||||
if (p && strncmp(p, "101", 3)) {
|
||||
lwsl_warn("libwebsocket_client_handshake "
|
||||
"server sent bad HTTP response '%s'\n", p);
|
||||
lwsl_warn(
|
||||
"lws_client_handshake: got bad HTTP response '%s'\n", p);
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
|
@ -381,8 +399,8 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
|||
goto bail3;
|
||||
strtolower(p);
|
||||
if (strcmp(p, "websocket")) {
|
||||
lwsl_warn("libwebsocket_client_handshake server "
|
||||
"sent bad Upgrade header '%s'\n", p);
|
||||
lwsl_warn(
|
||||
"lws_client_handshake: got bad Upgrade header '%s'\n", p);
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
|
@ -391,18 +409,15 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
|||
goto bail3;
|
||||
strtolower(p);
|
||||
if (strcmp(p, "upgrade")) {
|
||||
lwsl_warn("libwebsocket_client_handshake server "
|
||||
"sent bad Connection hdr '%s'\n", p);
|
||||
lwsl_warn("lws_client_int_s_hs: bad header %s\n", p);
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
|
||||
if (pc == NULL)
|
||||
lwsl_parser("lws_client_interpret_server_handshake: "
|
||||
"NULL c_protocol\n");
|
||||
lwsl_parser("lws_client_int_s_hs: no protocol list\n");
|
||||
else
|
||||
lwsl_parser("lws_client_interpret_server_handshake: "
|
||||
"cPprotocol='%s'\n", pc);
|
||||
lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc);
|
||||
|
||||
/*
|
||||
* confirm the protocol the server wants to talk was in the list
|
||||
|
@ -412,8 +427,7 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
|||
len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
|
||||
if (!len) {
|
||||
|
||||
lwsl_info("lws_client_interpret_server_handshake "
|
||||
"WSI_TOKEN_PROTOCOL is null\n");
|
||||
lwsl_info("lws_client_int_s_hs: WSI_TOKEN_PROTOCOL is null\n");
|
||||
/*
|
||||
* no protocol name to work from,
|
||||
* default to first protocol
|
||||
|
@ -426,7 +440,8 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
|||
len = strlen(p);
|
||||
|
||||
while (*pc && !okay) {
|
||||
if (!strncmp(pc, p, len) && (pc[len] == ',' || pc[len] == '\0')) {
|
||||
if (!strncmp(pc, p, len) &&
|
||||
(pc[len] == ',' || pc[len] == '\0')) {
|
||||
okay = 1;
|
||||
continue;
|
||||
}
|
||||
|
@ -437,8 +452,7 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
|||
}
|
||||
|
||||
if (!okay) {
|
||||
lwsl_err("libwebsocket_client_handshake server "
|
||||
"sent bad protocol '%s'\n", p);
|
||||
lwsl_err("lws_client_int_s_hs: got bad protocol %s\n", p);
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
|
@ -456,9 +470,7 @@ lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
|||
}
|
||||
|
||||
if (wsi->protocol == NULL) {
|
||||
lwsl_err("libwebsocket_client_handshake server "
|
||||
"requested protocol '%s', which we "
|
||||
"said we supported but we don't!\n", p);
|
||||
lwsl_err("lws_client_int_s_hs: fail protocol %s\n", p);
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
|
@ -477,7 +489,8 @@ check_extensions:
|
|||
* and go through matching them or identifying bogons
|
||||
*/
|
||||
|
||||
if (lws_hdr_copy(wsi, (char *)context->service_buffer, sizeof(context->service_buffer), WSI_TOKEN_EXTENSIONS) < 0)
|
||||
if (lws_hdr_copy(wsi, (char *)context->service_buffer,
|
||||
sizeof(context->service_buffer), WSI_TOKEN_EXTENSIONS) < 0)
|
||||
goto bail2;
|
||||
|
||||
c = (char *)context->service_buffer;
|
||||
|
@ -547,8 +560,7 @@ check_extensions:
|
|||
}
|
||||
|
||||
if (n == 0) {
|
||||
lwsl_warn("Server said we should use"
|
||||
"an unknown extension '%s'!\n", ext_name);
|
||||
lwsl_warn("Unknown ext '%s'!\n", ext_name);
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
|
@ -564,8 +576,7 @@ check_accept:
|
|||
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT);
|
||||
if (strcmp(p, wsi->u.hdr.initial_handshake_hash_base64)) {
|
||||
lwsl_warn("libwebsocket_client_handshake server "
|
||||
"sent bad ACCEPT '%s' vs computed '%s'\n", p,
|
||||
lwsl_warn("lws_client_int_s_hs: accept %s wrong vs %s\n", p,
|
||||
wsi->u.hdr.initial_handshake_hash_base64);
|
||||
goto bail2;
|
||||
}
|
||||
|
@ -599,7 +610,7 @@ check_accept:
|
|||
|
||||
/* union transition */
|
||||
|
||||
memset(&wsi->u, 0, sizeof wsi->u);
|
||||
memset(&wsi->u, 0, sizeof(wsi->u));
|
||||
|
||||
/*
|
||||
* create the frame buffer for this connection according to the
|
||||
|
@ -699,7 +710,7 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
lws_b64_encode_string(hash, 16, key_b64, sizeof key_b64);
|
||||
lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64));
|
||||
|
||||
/*
|
||||
* 00 example client handshake
|
||||
|
@ -727,24 +738,26 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
|
|||
* Sec-WebSocket-Version: 4
|
||||
*/
|
||||
|
||||
p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a", lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI));
|
||||
p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI));
|
||||
|
||||
p += sprintf(p, "Pragma: no-cache\x0d\x0a"
|
||||
"Cache-Control: no-cache\x0d\x0a");
|
||||
p += sprintf(p,
|
||||
"Pragma: no-cache\x0d\x0a""Cache-Control: no-cache\x0d\x0a");
|
||||
|
||||
p += sprintf(p, "Host: %s\x0d\x0a", lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
|
||||
p += sprintf(p, "Upgrade: websocket\x0d\x0a"
|
||||
"Connection: Upgrade\x0d\x0a"
|
||||
"Sec-WebSocket-Key: ");
|
||||
p += sprintf(p, "Host: %s\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
|
||||
p += sprintf(p,
|
||||
"Upgrade: websocket\x0d\x0aConnection: Upgrade\x0d\x0aSec-WebSocket-Key: ");
|
||||
strcpy(p, key_b64);
|
||||
p += strlen(key_b64);
|
||||
p += sprintf(p, "\x0d\x0a");
|
||||
if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN))
|
||||
p += sprintf(p, "Origin: %s\x0d\x0a", lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN));
|
||||
p += sprintf(p, "Origin: %s\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN));
|
||||
|
||||
if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS))
|
||||
p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS));
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS));
|
||||
|
||||
/* tell the server what extensions we could support */
|
||||
|
||||
|
@ -812,13 +825,13 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
|
|||
|
||||
/* prepare the expected server accept response */
|
||||
|
||||
n = snprintf(buf, sizeof buf, "%s%s", key_b64, magic_websocket_guid);
|
||||
n = snprintf(buf, sizeof(buf), "%s%s", key_b64, magic_websocket_guid);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
SHA1((unsigned char *)buf, n, (unsigned char *)hash);
|
||||
|
||||
lws_b64_encode_string(hash, 20,
|
||||
wsi->u.hdr.initial_handshake_hash_base64,
|
||||
sizeof wsi->u.hdr.initial_handshake_hash_base64);
|
||||
sizeof(wsi->u.hdr.initial_handshake_hash_base64));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
|
|
@ -48,20 +48,20 @@ child_handler(int signum)
|
|||
|
||||
fd = open(lock_path, O_TRUNC | O_RDWR | O_CREAT, 0640);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "unable to create lock"
|
||||
" file %s, code=%d (%s)\n",
|
||||
fprintf(stderr,
|
||||
"unable to create lock file %s, code=%d (%s)\n",
|
||||
lock_path, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
len = sprintf(sz, "%u", pid_daemon);
|
||||
sent = write(fd, sz, len);
|
||||
if (sent != len)
|
||||
fprintf(stderr, "unable write pid to lock"
|
||||
" file %s, code=%d (%s)\n",
|
||||
lock_path, errno, strerror(errno));
|
||||
fprintf(stderr,
|
||||
"unable write pid to lock file %s, code=%d (%s)\n",
|
||||
lock_path, errno, strerror(errno));
|
||||
|
||||
close(fd);
|
||||
exit(!!(sent == len));
|
||||
close(fd);
|
||||
exit(!!(sent == len));
|
||||
|
||||
case SIGCHLD: /* daemonization failed */
|
||||
exit(1);
|
||||
|
@ -104,16 +104,19 @@ lws_daemonize(const char *_lock_path)
|
|||
|
||||
fd = open(_lock_path, O_RDONLY);
|
||||
if (fd > 0) {
|
||||
n = read(fd, buf, sizeof buf);
|
||||
n = read(fd, buf, sizeof(buf));
|
||||
close(fd);
|
||||
if (n) {
|
||||
n = atoi(buf);
|
||||
ret = kill(n, 0);
|
||||
if (ret >= 0) {
|
||||
fprintf(stderr, "Daemon already running from pid %d, aborting\n", n);
|
||||
fprintf(stderr,
|
||||
"Daemon already running from pid %d\n", n);
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr, "Removing stale lock file %s from dead pid %d\n", _lock_path, n);
|
||||
fprintf(stderr,
|
||||
"Removing stale lock file %s from dead pid %d\n",
|
||||
_lock_path, n);
|
||||
unlink(lock_path);
|
||||
}
|
||||
}
|
||||
|
@ -207,11 +210,11 @@ lws_daemonize(const char *_lock_path)
|
|||
act.sa_handler = lws_daemon_closing;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
|
||||
|
||||
sigaction(SIGTERM, &act, NULL);
|
||||
|
||||
/* return to continue what is now "the daemon" */
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,8 @@ int lws_extension_callback_deflate_frame(
|
|||
}
|
||||
conn->buf_pre_used = 0;
|
||||
conn->buf_pre_length = 0;
|
||||
conn->buf_in_length = sizeof conn->buf_in;;
|
||||
conn->buf_out_length = sizeof conn->buf_out;
|
||||
conn->buf_in_length = sizeof(conn->buf_in);
|
||||
conn->buf_out_length = sizeof(conn->buf_out);
|
||||
conn->compressed_out = 0;
|
||||
conn->buf_pre = NULL;
|
||||
conn->buf_in = (unsigned char *)
|
||||
|
@ -147,19 +147,21 @@ bail:
|
|||
|
||||
conn->zs_in.avail_in = total_payload + 4;
|
||||
|
||||
conn->zs_in.next_out = conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING;
|
||||
conn->zs_in.avail_out = conn->buf_in_length;
|
||||
conn->zs_in.next_out =
|
||||
conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING;
|
||||
conn->zs_in.avail_out = conn->buf_in_length;
|
||||
|
||||
while (1) {
|
||||
n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
|
||||
switch (n) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_STREAM_ERROR:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
while (1) {
|
||||
n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
|
||||
switch (n) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_STREAM_ERROR:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
/*
|
||||
* screwed.. close the connection... we will get a
|
||||
* destroy callback to take care of closing nicely
|
||||
* screwed.. close the connection...
|
||||
* we will get a destroy callback to take care
|
||||
* of closing nicely
|
||||
*/
|
||||
lwsl_err("zlib error inflate %d: %s\n",
|
||||
n, conn->zs_in.msg);
|
||||
|
@ -174,8 +176,7 @@ bail:
|
|||
|
||||
conn->buf_in_length *= 2;
|
||||
if (conn->buf_in_length > LWS_MAX_ZLIB_CONN_BUFFER) {
|
||||
lwsl_ext("zlib in buffer tried to exceed "
|
||||
"max allowed of %u\n",
|
||||
lwsl_ext("zlib in buffer hit limit %u\n",
|
||||
LWS_MAX_ZLIB_CONN_BUFFER);
|
||||
return -1;
|
||||
}
|
||||
|
@ -191,13 +192,14 @@ bail:
|
|||
"deflate-frame ext RX did realloc to %ld\n",
|
||||
conn->buf_in_length);
|
||||
conn->zs_in.next_out = conn->buf_in +
|
||||
LWS_SEND_BUFFER_PRE_PADDING + len_so_far;
|
||||
LWS_SEND_BUFFER_PRE_PADDING + len_so_far;
|
||||
conn->zs_in.avail_out =
|
||||
conn->buf_in_length - len_so_far;
|
||||
}
|
||||
conn->buf_in_length - len_so_far;
|
||||
}
|
||||
|
||||
/* rewrite the buffer pointers and length */
|
||||
eff_buf->token = (char *)(conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING);
|
||||
eff_buf->token =
|
||||
(char *)(conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING);
|
||||
eff_buf->token_len = (int)(conn->zs_in.next_out -
|
||||
(conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING));
|
||||
|
||||
|
@ -212,15 +214,17 @@ bail:
|
|||
conn->zs_out.next_in = (unsigned char *)eff_buf->token;
|
||||
conn->zs_out.avail_in = current_payload;
|
||||
|
||||
conn->zs_out.next_out = conn->buf_out + LWS_SEND_BUFFER_PRE_PADDING;
|
||||
conn->zs_out.next_out =
|
||||
conn->buf_out + LWS_SEND_BUFFER_PRE_PADDING;
|
||||
conn->zs_out.avail_out = conn->buf_out_length;
|
||||
|
||||
while (1) {
|
||||
n = deflate(&conn->zs_out, Z_SYNC_FLUSH);
|
||||
if (n == Z_STREAM_ERROR) {
|
||||
/*
|
||||
* screwed.. close the connection... we will get a
|
||||
* destroy callback to take care of closing nicely
|
||||
* screwed.. close the connection... we will
|
||||
* get a destroy callback to take care of
|
||||
* closing nicely
|
||||
*/
|
||||
lwsl_ext("zlib error deflate\n");
|
||||
|
||||
|
@ -235,9 +239,8 @@ bail:
|
|||
LWS_SEND_BUFFER_PRE_PADDING));
|
||||
conn->buf_out_length *= 2;
|
||||
if (conn->buf_out_length > LWS_MAX_ZLIB_CONN_BUFFER) {
|
||||
lwsl_ext("zlib out buffer tried to exceed "
|
||||
"max allowed of %u\n",
|
||||
LWS_MAX_ZLIB_CONN_BUFFER);
|
||||
lwsl_ext("zlib out hit limit %u\n",
|
||||
LWS_MAX_ZLIB_CONN_BUFFER);
|
||||
return -1;
|
||||
}
|
||||
conn->buf_out = (unsigned char *)realloc(
|
||||
|
|
|
@ -60,14 +60,11 @@ int lws_extension_callback_deflate_stream(
|
|||
* Notice, length may be 0 and pointer NULL
|
||||
* in the case we are flushing with nothing new coming in
|
||||
*/
|
||||
if (conn->remaining_in)
|
||||
{
|
||||
if (conn->remaining_in) {
|
||||
conn->zs_in.next_in = conn->buf_in;
|
||||
conn->zs_in.avail_in = conn->remaining_in;
|
||||
conn->remaining_in = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
conn->zs_in.next_in = (unsigned char *)eff_buf->token;
|
||||
conn->zs_in.avail_in = eff_buf->token_len;
|
||||
}
|
||||
|
@ -91,13 +88,14 @@ int lws_extension_callback_deflate_stream(
|
|||
/* rewrite the buffer pointers and length */
|
||||
|
||||
eff_buf->token = (char *)conn->buf_out;
|
||||
eff_buf->token_len = sizeof(conn->buf_out) - conn->zs_in.avail_out;
|
||||
eff_buf->token_len =
|
||||
sizeof(conn->buf_out) - conn->zs_in.avail_out;
|
||||
|
||||
/* copy avail data if not consumed */
|
||||
if (conn->zs_in.avail_in > 0)
|
||||
{
|
||||
if (conn->zs_in.avail_in > 0) {
|
||||
conn->remaining_in = conn->zs_in.avail_in;
|
||||
memcpy(conn->buf_in, conn->zs_in.next_in, conn->zs_in.avail_in);
|
||||
memcpy(conn->buf_in, conn->zs_in.next_in,
|
||||
conn->zs_in.avail_in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -144,7 +142,8 @@ int lws_extension_callback_deflate_stream(
|
|||
/* rewrite the buffer pointers and length */
|
||||
|
||||
eff_buf->token = (char *)conn->buf_out;
|
||||
eff_buf->token_len = sizeof(conn->buf_out) - conn->zs_out.avail_out;
|
||||
eff_buf->token_len =
|
||||
sizeof(conn->buf_out) - conn->zs_out.avail_out;
|
||||
|
||||
/*
|
||||
* if we filled the output buffer, signal that we likely have
|
||||
|
|
|
@ -8,18 +8,18 @@ struct libwebsocket_extension libwebsocket_internal_extensions[] = {
|
|||
{
|
||||
"deflate-stream",
|
||||
lws_extension_callback_deflate_stream,
|
||||
sizeof (struct lws_ext_deflate_stream_conn)
|
||||
sizeof(struct lws_ext_deflate_stream_conn)
|
||||
},
|
||||
#else
|
||||
{
|
||||
"x-webkit-deflate-frame",
|
||||
lws_extension_callback_deflate_frame,
|
||||
sizeof (struct lws_ext_deflate_frame_conn)
|
||||
sizeof(struct lws_ext_deflate_frame_conn)
|
||||
},
|
||||
{
|
||||
"deflate-frame",
|
||||
lws_extension_callback_deflate_frame,
|
||||
sizeof (struct lws_ext_deflate_frame_conn)
|
||||
sizeof(struct lws_ext_deflate_frame_conn)
|
||||
},
|
||||
#endif
|
||||
{ /* terminator */
|
||||
|
|
317
lib/getifaddrs.c
317
lib/getifaddrs.c
|
@ -1,25 +1,28 @@
|
|||
/* downloaded from http://ftp.uninett.no/pub/OpenBSD/src/kerberosV/src/lib/roken/getifaddrs.c */
|
||||
/*
|
||||
* downloaded from
|
||||
* http://ftp.uninett.no/pub/OpenBSD/src/kerberosV/src/lib/roken/getifaddrs.c
|
||||
*/
|
||||
#if !HAVE_GETIFADDRS
|
||||
/*
|
||||
* Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan
|
||||
* Copyright (c) 2000 - 2001 Kungliga Tekniska H<EFBFBD>gskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
|
@ -51,174 +54,174 @@
|
|||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#include "getifaddrs.h"
|
||||
|
||||
static int
|
||||
getifaddrs2(struct ifaddrs **ifap,
|
||||
getifaddrs2(struct ifaddrs **ifap,
|
||||
int af, int siocgifconf, int siocgifflags,
|
||||
size_t ifreq_sz)
|
||||
{
|
||||
int ret;
|
||||
int fd;
|
||||
size_t buf_size;
|
||||
char *buf;
|
||||
struct ifconf ifconf;
|
||||
char *p;
|
||||
size_t sz;
|
||||
struct sockaddr sa_zero;
|
||||
struct ifreq *ifr;
|
||||
int ret;
|
||||
int fd;
|
||||
size_t buf_size;
|
||||
char *buf;
|
||||
struct ifconf ifconf;
|
||||
char *p;
|
||||
size_t sz;
|
||||
struct sockaddr sa_zero;
|
||||
struct ifreq *ifr;
|
||||
|
||||
struct ifaddrs *start, **end = &start;
|
||||
struct ifaddrs *start, **end = &start;
|
||||
|
||||
buf = NULL;
|
||||
buf = NULL;
|
||||
|
||||
memset (&sa_zero, 0, sizeof(sa_zero));
|
||||
fd = socket(af, SOCK_DGRAM, 0);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
memset(&sa_zero, 0, sizeof(sa_zero));
|
||||
fd = socket(af, SOCK_DGRAM, 0);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
buf_size = 8192;
|
||||
for (;;) {
|
||||
buf = calloc(1, buf_size);
|
||||
if (buf == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto error_out;
|
||||
buf_size = 8192;
|
||||
for (;;) {
|
||||
buf = calloc(1, buf_size);
|
||||
if (buf == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto error_out;
|
||||
}
|
||||
ifconf.ifc_len = buf_size;
|
||||
ifconf.ifc_buf = buf;
|
||||
|
||||
/*
|
||||
* Solaris returns EINVAL when the buffer is too small.
|
||||
*/
|
||||
if (ioctl(fd, siocgifconf, &ifconf) < 0 && errno != EINVAL) {
|
||||
ret = errno;
|
||||
goto error_out;
|
||||
}
|
||||
/*
|
||||
* Can the difference between a full and a overfull buf
|
||||
* be determined?
|
||||
*/
|
||||
|
||||
if (ifconf.ifc_len < (int)buf_size)
|
||||
break;
|
||||
free(buf);
|
||||
buf_size *= 2;
|
||||
}
|
||||
ifconf.ifc_len = buf_size;
|
||||
ifconf.ifc_buf = buf;
|
||||
|
||||
/*
|
||||
* Solaris returns EINVAL when the buffer is too small.
|
||||
*/
|
||||
if (ioctl (fd, siocgifconf, &ifconf) < 0 && errno != EINVAL) {
|
||||
ret = errno;
|
||||
goto error_out;
|
||||
}
|
||||
/*
|
||||
* Can the difference between a full and a overfull buf
|
||||
* be determined?
|
||||
*/
|
||||
for (p = ifconf.ifc_buf; p < ifconf.ifc_buf + ifconf.ifc_len; p += sz) {
|
||||
struct ifreq ifreq;
|
||||
struct sockaddr *sa;
|
||||
size_t salen;
|
||||
|
||||
if (ifconf.ifc_len < (int)buf_size)
|
||||
break;
|
||||
free (buf);
|
||||
buf_size *= 2;
|
||||
}
|
||||
ifr = (struct ifreq *)p;
|
||||
sa = &ifr->ifr_addr;
|
||||
|
||||
for (p = ifconf.ifc_buf;
|
||||
p < ifconf.ifc_buf + ifconf.ifc_len;
|
||||
p += sz) {
|
||||
struct ifreq ifreq;
|
||||
struct sockaddr *sa;
|
||||
size_t salen;
|
||||
|
||||
ifr = (struct ifreq *)p;
|
||||
sa = &ifr->ifr_addr;
|
||||
|
||||
sz = ifreq_sz;
|
||||
salen = sizeof(struct sockaddr);
|
||||
sz = ifreq_sz;
|
||||
salen = sizeof(struct sockaddr);
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
|
||||
salen = sa->sa_len;
|
||||
sz = max(sz, sizeof(ifr->ifr_name) + sa->sa_len);
|
||||
salen = sa->sa_len;
|
||||
sz = max(sz, sizeof(ifr->ifr_name) + sa->sa_len);
|
||||
#endif
|
||||
#ifdef SA_LEN
|
||||
salen = SA_LEN(sa);
|
||||
sz = max(sz, sizeof(ifr->ifr_name) + SA_LEN(sa));
|
||||
salen = SA_LEN(sa);
|
||||
sz = max(sz, sizeof(ifr->ifr_name) + SA_LEN(sa));
|
||||
#endif
|
||||
memset (&ifreq, 0, sizeof(ifreq));
|
||||
memcpy (ifreq.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name));
|
||||
memset(&ifreq, 0, sizeof(ifreq));
|
||||
memcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name));
|
||||
|
||||
if (ioctl(fd, siocgifflags, &ifreq) < 0) {
|
||||
ret = errno;
|
||||
goto error_out;
|
||||
}
|
||||
if (ioctl(fd, siocgifflags, &ifreq) < 0) {
|
||||
ret = errno;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
*end = malloc(sizeof(**end));
|
||||
*end = malloc(sizeof(**end));
|
||||
|
||||
(*end)->ifa_next = NULL;
|
||||
(*end)->ifa_name = strdup(ifr->ifr_name);
|
||||
(*end)->ifa_flags = ifreq.ifr_flags;
|
||||
(*end)->ifa_addr = malloc(salen);
|
||||
memcpy((*end)->ifa_addr, sa, salen);
|
||||
(*end)->ifa_netmask = NULL;
|
||||
(*end)->ifa_next = NULL;
|
||||
(*end)->ifa_name = strdup(ifr->ifr_name);
|
||||
(*end)->ifa_flags = ifreq.ifr_flags;
|
||||
(*end)->ifa_addr = malloc(salen);
|
||||
memcpy((*end)->ifa_addr, sa, salen);
|
||||
(*end)->ifa_netmask = NULL;
|
||||
|
||||
#if 0
|
||||
/* fix these when we actually need them */
|
||||
if(ifreq.ifr_flags & IFF_BROADCAST) {
|
||||
(*end)->ifa_broadaddr = malloc(sizeof(ifr->ifr_broadaddr));
|
||||
memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr,
|
||||
sizeof(ifr->ifr_broadaddr));
|
||||
} else if(ifreq.ifr_flags & IFF_POINTOPOINT) {
|
||||
(*end)->ifa_dstaddr = malloc(sizeof(ifr->ifr_dstaddr));
|
||||
memcpy((*end)->ifa_dstaddr, &ifr->ifr_dstaddr,
|
||||
sizeof(ifr->ifr_dstaddr));
|
||||
} else
|
||||
(*end)->ifa_dstaddr = NULL;
|
||||
/* fix these when we actually need them */
|
||||
if (ifreq.ifr_flags & IFF_BROADCAST) {
|
||||
(*end)->ifa_broadaddr =
|
||||
malloc(sizeof(ifr->ifr_broadaddr));
|
||||
memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr,
|
||||
sizeof(ifr->ifr_broadaddr));
|
||||
} else if (ifreq.ifr_flags & IFF_POINTOPOINT) {
|
||||
(*end)->ifa_dstaddr = malloc(sizeof(ifr->ifr_dstaddr));
|
||||
memcpy((*end)->ifa_dstaddr, &ifr->ifr_dstaddr,
|
||||
sizeof(ifr->ifr_dstaddr));
|
||||
} else
|
||||
(*end)->ifa_dstaddr = NULL;
|
||||
#else
|
||||
(*end)->ifa_dstaddr = NULL;
|
||||
(*end)->ifa_dstaddr = NULL;
|
||||
#endif
|
||||
(*end)->ifa_data = NULL;
|
||||
|
||||
(*end)->ifa_data = NULL;
|
||||
end = &(*end)->ifa_next;
|
||||
|
||||
end = &(*end)->ifa_next;
|
||||
|
||||
}
|
||||
*ifap = start;
|
||||
close(fd);
|
||||
free(buf);
|
||||
return 0;
|
||||
error_out:
|
||||
close(fd);
|
||||
free(buf);
|
||||
errno = ret;
|
||||
return -1;
|
||||
}
|
||||
*ifap = start;
|
||||
close(fd);
|
||||
free(buf);
|
||||
return 0;
|
||||
|
||||
error_out:
|
||||
close(fd);
|
||||
free(buf);
|
||||
errno = ret;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
getifaddrs(struct ifaddrs **ifap)
|
||||
getifaddrs(struct ifaddrs **ifap)
|
||||
{
|
||||
int ret = -1;
|
||||
errno = ENXIO;
|
||||
int ret = -1;
|
||||
errno = ENXIO;
|
||||
#if defined(AF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)
|
||||
if (ret)
|
||||
ret = getifaddrs2 (ifap, AF_INET6, SIOCGIF6CONF, SIOCGIF6FLAGS,
|
||||
if (ret)
|
||||
ret = getifaddrs2(ifap, AF_INET6, SIOCGIF6CONF, SIOCGIF6FLAGS,
|
||||
sizeof(struct in6_ifreq));
|
||||
#endif
|
||||
#if defined(HAVE_IPV6) && defined(SIOCGIFCONF)
|
||||
if (ret)
|
||||
ret = getifaddrs2 (ifap, AF_INET6, SIOCGIFCONF, SIOCGIFFLAGS,
|
||||
if (ret)
|
||||
ret = getifaddrs2(ifap, AF_INET6, SIOCGIFCONF, SIOCGIFFLAGS,
|
||||
sizeof(struct ifreq));
|
||||
#endif
|
||||
#if defined(AF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)
|
||||
if (ret)
|
||||
ret = getifaddrs2 (ifap, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
|
||||
if (ret)
|
||||
ret = getifaddrs2(ifap, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
|
||||
sizeof(struct ifreq));
|
||||
#endif
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
freeifaddrs(struct ifaddrs *ifp)
|
||||
{
|
||||
struct ifaddrs *p, *q;
|
||||
|
||||
for(p = ifp; p; ) {
|
||||
free(p->ifa_name);
|
||||
if(p->ifa_addr)
|
||||
free(p->ifa_addr);
|
||||
if(p->ifa_dstaddr)
|
||||
free(p->ifa_dstaddr);
|
||||
if(p->ifa_netmask)
|
||||
free(p->ifa_netmask);
|
||||
if(p->ifa_data)
|
||||
free(p->ifa_data);
|
||||
q = p;
|
||||
p = p->ifa_next;
|
||||
free(q);
|
||||
}
|
||||
struct ifaddrs *p, *q;
|
||||
|
||||
for (p = ifp; p; ) {
|
||||
free(p->ifa_name);
|
||||
if (p->ifa_addr)
|
||||
free(p->ifa_addr);
|
||||
if (p->ifa_dstaddr)
|
||||
free(p->ifa_dstaddr);
|
||||
if (p->ifa_netmask)
|
||||
free(p->ifa_netmask);
|
||||
if (p->ifa_data)
|
||||
free(p->ifa_data);
|
||||
q = p;
|
||||
p = p->ifa_next;
|
||||
free(q);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
@ -226,46 +229,48 @@ freeifaddrs(struct ifaddrs *ifp)
|
|||
void
|
||||
print_addr(const char *s, struct sockaddr *sa)
|
||||
{
|
||||
int i;
|
||||
printf(" %s=%d/", s, sa->sa_family);
|
||||
int i;
|
||||
printf(" %s=%d/", s, sa->sa_family);
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
|
||||
for(i = 0; i < sa->sa_len - ((long)sa->sa_data - (long)&sa->sa_family); i++)
|
||||
printf("%02x", ((unsigned char*)sa->sa_data)[i]);
|
||||
for (i = 0;
|
||||
i < sa->sa_len - ((long)sa->sa_data - (long)&sa->sa_family); i++)
|
||||
printf("%02x", ((unsigned char *)sa->sa_data)[i]);
|
||||
#else
|
||||
for(i = 0; i < sizeof(sa->sa_data); i++)
|
||||
printf("%02x", ((unsigned char*)sa->sa_data)[i]);
|
||||
for (i = 0; i < sizeof(sa->sa_data); i++)
|
||||
printf("%02x", ((unsigned char *)sa->sa_data)[i]);
|
||||
#endif
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
print_ifaddrs(struct ifaddrs *x)
|
||||
{
|
||||
struct ifaddrs *p;
|
||||
|
||||
for(p = x; p; p = p->ifa_next) {
|
||||
printf("%s\n", p->ifa_name);
|
||||
printf(" flags=%x\n", p->ifa_flags);
|
||||
if(p->ifa_addr)
|
||||
print_addr("addr", p->ifa_addr);
|
||||
if(p->ifa_dstaddr)
|
||||
print_addr("dstaddr", p->ifa_dstaddr);
|
||||
if(p->ifa_netmask)
|
||||
print_addr("netmask", p->ifa_netmask);
|
||||
printf(" %p\n", p->ifa_data);
|
||||
}
|
||||
struct ifaddrs *p;
|
||||
|
||||
for (p = x; p; p = p->ifa_next) {
|
||||
printf("%s\n", p->ifa_name);
|
||||
printf(" flags=%x\n", p->ifa_flags);
|
||||
if (p->ifa_addr)
|
||||
print_addr("addr", p->ifa_addr);
|
||||
if (p->ifa_dstaddr)
|
||||
print_addr("dstaddr", p->ifa_dstaddr);
|
||||
if (p->ifa_netmask)
|
||||
print_addr("netmask", p->ifa_netmask);
|
||||
printf(" %p\n", p->ifa_data);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
struct ifaddrs *a = NULL, *b;
|
||||
getifaddrs2(&a, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS, sizeof(struct ifreq));
|
||||
print_ifaddrs(a);
|
||||
printf("---\n");
|
||||
getifaddrs(&b);
|
||||
print_ifaddrs(b);
|
||||
return 0;
|
||||
struct ifaddrs *a = NULL, *b;
|
||||
getifaddrs2(&a, AF_INET, SIOCGIFCONF,
|
||||
SIOCGIFFLAGS, sizeof(struct ifreq));
|
||||
print_ifaddrs(a);
|
||||
printf("---\n");
|
||||
getifaddrs(&b);
|
||||
print_ifaddrs(b);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -6,25 +6,25 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Copyright (c) 2000 Kungliga Tekniska Högskolan
|
||||
* Copyright (c) 2000 Kungliga Tekniska H<EFBFBD>gskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
|
@ -51,22 +51,22 @@ extern "C" {
|
|||
#undef ifa_dstaddr
|
||||
|
||||
struct ifaddrs {
|
||||
struct ifaddrs *ifa_next;
|
||||
char *ifa_name;
|
||||
unsigned int ifa_flags;
|
||||
struct sockaddr *ifa_addr;
|
||||
struct sockaddr *ifa_netmask;
|
||||
struct sockaddr *ifa_dstaddr;
|
||||
void *ifa_data;
|
||||
struct ifaddrs *ifa_next;
|
||||
char *ifa_name;
|
||||
unsigned int ifa_flags;
|
||||
struct sockaddr *ifa_addr;
|
||||
struct sockaddr *ifa_netmask;
|
||||
struct sockaddr *ifa_dstaddr;
|
||||
void *ifa_data;
|
||||
};
|
||||
|
||||
#ifndef ifa_broadaddr
|
||||
#define ifa_broadaddr ifa_dstaddr
|
||||
#endif
|
||||
|
||||
int getifaddrs(struct ifaddrs**);
|
||||
int getifaddrs(struct ifaddrs **);
|
||||
|
||||
void freeifaddrs(struct ifaddrs*);
|
||||
void freeifaddrs(struct ifaddrs *);
|
||||
|
||||
#endif /* __ifaddrs_h__ */
|
||||
|
||||
|
|
|
@ -53,13 +53,9 @@
|
|||
* machine that is completely independent of packet size.
|
||||
*/
|
||||
|
||||
#ifndef LWS_NO_SERVER
|
||||
extern int handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi);
|
||||
#endif
|
||||
|
||||
int
|
||||
libwebsocket_read(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
||||
struct libwebsocket *wsi, unsigned char *buf, size_t len)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
|
@ -73,14 +69,8 @@ libwebsocket_read(struct libwebsocket_context *context,
|
|||
case WSI_STATE_HTTP_HEADERS:
|
||||
|
||||
lwsl_parser("issuing %d bytes to parser\n", (int)len);
|
||||
#ifdef _DEBUG
|
||||
//fwrite(buf, 1, len, stderr);
|
||||
#endif
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
|
||||
// lwsl_info("mode=%d\n", wsi->mode);
|
||||
|
||||
switch (wsi->mode) {
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
|
||||
case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
|
||||
|
@ -89,7 +79,7 @@ libwebsocket_read(struct libwebsocket_context *context,
|
|||
case LWS_CONNMODE_WS_CLIENT:
|
||||
for (n = 0; n < len; n++)
|
||||
if (libwebsocket_client_rx_sm(wsi, *buf++)) {
|
||||
lwsl_info("libwebsocket_client_rx_sm failed\n");
|
||||
lwsl_info("client_rx_sm failed\n");
|
||||
goto bail;
|
||||
}
|
||||
return 0;
|
||||
|
@ -119,17 +109,17 @@ libwebsocket_read(struct libwebsocket_context *context,
|
|||
n = 0;
|
||||
if (wsi->protocol->callback)
|
||||
n = wsi->protocol->callback(context, wsi,
|
||||
LWS_CALLBACK_HTTP,
|
||||
wsi->user_space,
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI),
|
||||
lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI));
|
||||
LWS_CALLBACK_HTTP,
|
||||
wsi->user_space,
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI),
|
||||
lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI));
|
||||
|
||||
/* drop the header info */
|
||||
if (wsi->u.hdr.ah)
|
||||
free(wsi->u.hdr.ah);
|
||||
|
||||
if (n) {
|
||||
lwsl_info("LWS_CALLBACK_HTTP wanted to close\n");
|
||||
lwsl_info("LWS_CALLBACK_HTTP closing\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
|
@ -152,7 +142,8 @@ libwebsocket_read(struct libwebsocket_context *context,
|
|||
break;
|
||||
} else
|
||||
if (wsi->protocol->name && strcmp(
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL),
|
||||
lws_hdr_simple_ptr(wsi,
|
||||
WSI_TOKEN_PROTOCOL),
|
||||
wsi->protocol->name) == 0)
|
||||
break;
|
||||
|
||||
|
@ -162,14 +153,13 @@ libwebsocket_read(struct libwebsocket_context *context,
|
|||
/* we didn't find a protocol he wanted? */
|
||||
|
||||
if (wsi->protocol->callback == NULL) {
|
||||
if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL) == NULL) {
|
||||
lwsl_info("[no protocol] "
|
||||
"mapped to protocol 0 handler\n");
|
||||
if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL) ==
|
||||
NULL) {
|
||||
lwsl_info("no protocol -> prot 0 handler\n");
|
||||
wsi->protocol = &context->protocols[0];
|
||||
} else {
|
||||
lwsl_err("Requested protocol %s "
|
||||
"not supported\n",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL));
|
||||
lwsl_err("Req protocol %s not supported\n",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL));
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
@ -195,9 +185,9 @@ libwebsocket_read(struct libwebsocket_context *context,
|
|||
|
||||
switch (wsi->ietf_spec_revision) {
|
||||
case 13:
|
||||
lwsl_parser("libwebsocket_parse calling handshake_04\n");
|
||||
lwsl_parser("lws_parse calling handshake_04\n");
|
||||
if (handshake_0405(context, wsi)) {
|
||||
lwsl_info("handshake_0405 xor 05 has failed the connection\n");
|
||||
lwsl_info("hs0405 has failed the connection\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
|
@ -216,7 +206,7 @@ libwebsocket_read(struct libwebsocket_context *context,
|
|||
wsi->mode = LWS_CONNMODE_WS_SERVING;
|
||||
|
||||
/* union transition */
|
||||
memset(&wsi->u, 0, sizeof wsi->u);
|
||||
memset(&wsi->u, 0, sizeof(wsi->u));
|
||||
|
||||
/*
|
||||
* create the frame buffer for this connection according to the
|
||||
|
@ -246,7 +236,8 @@ libwebsocket_read(struct libwebsocket_context *context,
|
|||
switch (wsi->mode) {
|
||||
case LWS_CONNMODE_WS_CLIENT:
|
||||
for (n = 0; n < len; n++)
|
||||
if (libwebsocket_client_rx_sm(wsi, *buf++) < 0) {
|
||||
if (libwebsocket_client_rx_sm(
|
||||
wsi, *buf++) < 0) {
|
||||
lwsl_info("client rx has bailed\n");
|
||||
goto bail;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
|
|||
|
||||
static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH;
|
||||
|
||||
static const char *log_level_names[] = {
|
||||
static const char * const log_level_names[] = {
|
||||
"ERR",
|
||||
"WARN",
|
||||
"NOTICE",
|
||||
|
@ -71,6 +71,17 @@ static const char *log_level_names[] = {
|
|||
"LATENCY",
|
||||
};
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
extern int lws_client_socket_service(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct pollfd *pollfd);
|
||||
#endif
|
||||
#ifndef LWS_NO_SERVER
|
||||
extern int lws_server_socket_service(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct pollfd *pollfd);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* lws_get_library_version: get version and git hash library built from
|
||||
*
|
||||
|
@ -86,22 +97,25 @@ lws_get_library_version(void)
|
|||
}
|
||||
|
||||
int
|
||||
insert_wsi_socket_into_fds(struct libwebsocket_context *context, struct libwebsocket *wsi)
|
||||
insert_wsi_socket_into_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
if (context->fds_count >= context->max_fds) {
|
||||
lwsl_err("Reached limit of fds tracking (%d)\n", context->max_fds);
|
||||
lwsl_err("Too many fds (%d)\n", context->max_fds);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (wsi->sock > context->max_fds) {
|
||||
lwsl_err("Socket fd %d is beyond what we can index (%d)\n", wsi->sock, context->max_fds);
|
||||
lwsl_err("Socket fd %d is too high (%d)\n",
|
||||
wsi->sock, context->max_fds);
|
||||
return 1;
|
||||
}
|
||||
|
||||
assert(wsi);
|
||||
assert(wsi->sock);
|
||||
|
||||
lwsl_info("insert_wsi_socket_into_fds: wsi=%p, sock=%d, fds pos=%d\n", wsi, wsi->sock, context->fds_count);
|
||||
lwsl_info("insert_wsi_socket_into_fds: wsi=%p, sock=%d, fds pos=%d\n",
|
||||
wsi, wsi->sock, context->fds_count);
|
||||
|
||||
context->lws_lookup[wsi->sock] = wsi;
|
||||
wsi->position_in_fds_table = context->fds_count;
|
||||
|
@ -118,7 +132,8 @@ insert_wsi_socket_into_fds(struct libwebsocket_context *context, struct libwebso
|
|||
}
|
||||
|
||||
static int
|
||||
remove_wsi_socket_from_fds(struct libwebsocket_context *context, struct libwebsocket *wsi)
|
||||
remove_wsi_socket_from_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
int m;
|
||||
|
||||
|
@ -126,22 +141,29 @@ remove_wsi_socket_from_fds(struct libwebsocket_context *context, struct libwebso
|
|||
goto do_ext;
|
||||
|
||||
if (wsi->sock > context->max_fds) {
|
||||
lwsl_err("Socket fd %d is beyond what we can index (%d)\n", wsi->sock, context->max_fds);
|
||||
lwsl_err("Socket fd %d too high (%d)\n",
|
||||
wsi->sock, context->max_fds);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lwsl_info("remove_wsi_socket_from_fds: wsi=%p, sock=%d, fds pos=%d\n", wsi, wsi->sock, wsi->position_in_fds_table);
|
||||
lwsl_info("remove_wsi_socket_from_fds: wsi=%p, sock=%d, fds pos=%d\n",
|
||||
wsi, wsi->sock, wsi->position_in_fds_table);
|
||||
|
||||
m = wsi->position_in_fds_table; /* replace the contents for this */
|
||||
|
||||
/* have the last guy take up the vacant slot */
|
||||
context->fds[m] = context->fds[context->fds_count]; /* vacant fds slot filled with end one */
|
||||
/* end guy's fds_lookup entry remains unchanged (still same fd pointing to same wsi) */
|
||||
context->fds[m] = context->fds[context->fds_count];
|
||||
/*
|
||||
* end guy's fds_lookup entry remains unchanged
|
||||
* (still same fd pointing to same wsi)
|
||||
*/
|
||||
/* end guy's "position in fds table" changed */
|
||||
context->lws_lookup[context->fds[context->fds_count].fd]->position_in_fds_table = m;
|
||||
context->lws_lookup[context->fds[context->fds_count].fd]->
|
||||
position_in_fds_table = m;
|
||||
/* deletion guy's lws_lookup entry needs nuking */
|
||||
context->lws_lookup[wsi->sock] = NULL; /* no WSI for the socket of the wsi being removed*/
|
||||
wsi->position_in_fds_table = -1; /* removed wsi has no position any more */
|
||||
context->lws_lookup[wsi->sock] = NULL;
|
||||
/* removed wsi has no position any more */
|
||||
wsi->position_in_fds_table = -1;
|
||||
|
||||
do_ext:
|
||||
/* remove also from external POLL support via protocol 0 */
|
||||
|
@ -248,8 +270,8 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
|||
|
||||
if (eff_buf.token_len)
|
||||
if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
|
||||
eff_buf.token_len)) {
|
||||
lwsl_debug("close: sending final extension spill had problems\n");
|
||||
eff_buf.token_len)) {
|
||||
lwsl_debug("close: ext spill failed\n");
|
||||
goto just_kill_connection;
|
||||
}
|
||||
}
|
||||
|
@ -273,8 +295,9 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
|||
lwsl_debug("sending close indication...\n");
|
||||
|
||||
/* make valgrind happy */
|
||||
memset(buf, 0, sizeof buf);
|
||||
n = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING + 2],
|
||||
memset(buf, 0, sizeof(buf));
|
||||
n = libwebsocket_write(wsi,
|
||||
&buf[LWS_SEND_BUFFER_PRE_PADDING + 2],
|
||||
0, LWS_WRITE_CLOSE);
|
||||
if (!n) {
|
||||
/*
|
||||
|
@ -284,7 +307,10 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
|||
|
||||
wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
|
||||
|
||||
/* and we should wait for a reply for a bit out of politeness */
|
||||
/*
|
||||
* ...and we should wait for a reply for a bit
|
||||
* out of politeness
|
||||
*/
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_CLOSE_ACK, 1);
|
||||
|
@ -294,7 +320,7 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
|||
return;
|
||||
}
|
||||
|
||||
lwsl_info("close: sending the close packet failed, hanging up\n");
|
||||
lwsl_info("close: sending close packet failed, hanging up\n");
|
||||
|
||||
/* else, the send failed and we should just hang up */
|
||||
}
|
||||
|
@ -303,7 +329,7 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
|||
just_kill_connection:
|
||||
#endif
|
||||
|
||||
lwsl_debug("libwebsocket_close_and_free_session: just_kill_connection\n");
|
||||
lwsl_debug("close: just_kill_connection\n");
|
||||
|
||||
/*
|
||||
* we won't be servicing or receiving anything further from this guy
|
||||
|
@ -314,7 +340,9 @@ just_kill_connection:
|
|||
|
||||
wsi->state = WSI_STATE_DEAD_SOCKET;
|
||||
|
||||
if ((old_state == WSI_STATE_ESTABLISHED || wsi->mode == LWS_CONNMODE_WS_SERVING || wsi->mode == LWS_CONNMODE_WS_CLIENT) && wsi->u.ws.rx_user_buffer) {
|
||||
if ((old_state == WSI_STATE_ESTABLISHED ||
|
||||
wsi->mode == LWS_CONNMODE_WS_SERVING ||
|
||||
wsi->mode == LWS_CONNMODE_WS_CLIENT) && wsi->u.ws.rx_user_buffer) {
|
||||
free(wsi->u.ws.rx_user_buffer);
|
||||
wsi->u.ws.rx_user_buffer = NULL;
|
||||
}
|
||||
|
@ -329,7 +357,7 @@ just_kill_connection:
|
|||
wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
|
||||
wsi->user_space, NULL, 0);
|
||||
} else
|
||||
lwsl_debug("not calling back closed, old_state=%d\n", old_state);
|
||||
lwsl_debug("not calling back closed\n");
|
||||
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
/* deallocate any active extension contexts */
|
||||
|
@ -376,16 +404,19 @@ just_kill_connection:
|
|||
if (wsi->sock) {
|
||||
n = shutdown(wsi->sock, SHUT_RDWR);
|
||||
if (n)
|
||||
lwsl_debug("closing: shutdown returned %d\n", errno);
|
||||
lwsl_debug("closing: shutdown returned %d\n",
|
||||
errno);
|
||||
|
||||
n = compatible_close(wsi->sock);
|
||||
if (n)
|
||||
lwsl_debug("closing: close returned %d\n", errno);
|
||||
lwsl_debug("closing: close returned %d\n",
|
||||
errno);
|
||||
}
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
}
|
||||
#endif
|
||||
if (wsi->protocol && wsi->protocol->per_session_data_size && wsi->user_space) /* user code may own */
|
||||
if (wsi->protocol && wsi->protocol->per_session_data_size &&
|
||||
wsi->user_space) /* user code may own */
|
||||
free(wsi->user_space);
|
||||
|
||||
free(wsi);
|
||||
|
@ -404,7 +435,7 @@ libwebsockets_hangup_on_client(struct libwebsocket_context *context, int fd)
|
|||
struct libwebsocket *wsi = context->lws_lookup[fd];
|
||||
|
||||
if (wsi) {
|
||||
lwsl_info("closing connection at libwebsockets_hangup_on_client:\n");
|
||||
lwsl_info("close connection at hangup_on_client:\n");
|
||||
libwebsocket_close_and_free_session(context,
|
||||
wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
} else
|
||||
|
@ -442,7 +473,7 @@ libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
|
|||
int n;
|
||||
int ret = -1;
|
||||
#ifdef AF_LOCAL
|
||||
struct sockaddr_un *un;
|
||||
struct sockaddr_un *un;
|
||||
#endif
|
||||
|
||||
rip[0] = '\0';
|
||||
|
@ -450,13 +481,13 @@ libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
|
|||
|
||||
lws_latency_pre(context, wsi);
|
||||
|
||||
len = sizeof sin;
|
||||
len = sizeof(sin);
|
||||
if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
|
||||
perror("getpeername");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
host = gethostbyaddr((char *) &sin.sin_addr, sizeof sin.sin_addr,
|
||||
host = gethostbyaddr((char *) &sin.sin_addr, sizeof(sin.sin_addr),
|
||||
AF_INET);
|
||||
if (host == NULL) {
|
||||
perror("gethostbyaddr");
|
||||
|
@ -725,7 +756,8 @@ notify_action:
|
|||
n = LWS_CALLBACK_SERVER_WRITEABLE;
|
||||
|
||||
return user_callback_handle_rxflow(wsi->protocol->callback, context,
|
||||
wsi, (enum libwebsocket_callback_reasons) n, wsi->user_space, NULL, 0);
|
||||
wsi, (enum libwebsocket_callback_reasons) n,
|
||||
wsi->user_space, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -771,7 +803,8 @@ libwebsocket_service_timeout_check(struct libwebsocket_context *context,
|
|||
* happened.
|
||||
*
|
||||
* This function takes a pollfd that has POLLIN or POLLOUT activity and
|
||||
* services it according to the state of the associated struct libwebsocket.
|
||||
* services it according to the state of the associated
|
||||
* struct libwebsocket.
|
||||
*
|
||||
* The one call deals with all "service" that might happen on a socket
|
||||
* including listen accepts, http files as well as websocket protocol.
|
||||
|
@ -791,12 +824,6 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
|
|||
int more = 1;
|
||||
#endif
|
||||
struct lws_tokens eff_buf;
|
||||
#ifndef LWS_NO_CLIENT
|
||||
extern int lws_client_socket_service(struct libwebsocket_context *context, struct libwebsocket *wsi, struct pollfd *pollfd);
|
||||
#endif
|
||||
#ifndef LWS_NO_SERVER
|
||||
extern int lws_server_socket_service(struct libwebsocket_context *context, struct libwebsocket *wsi, struct pollfd *pollfd);
|
||||
#endif
|
||||
|
||||
if (context->listen_service_fd)
|
||||
listen_socket_fds_index = context->lws_lookup[
|
||||
|
@ -815,14 +842,16 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
|
|||
|
||||
#ifndef WIN32
|
||||
/* if our parent went down, don't linger around */
|
||||
if (context->started_with_parent && kill(context->started_with_parent, 0) < 0)
|
||||
if (context->started_with_parent &&
|
||||
kill(context->started_with_parent, 0) < 0)
|
||||
kill(getpid(), SIGTERM);
|
||||
#endif
|
||||
|
||||
/* global timeout check once per second */
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
struct libwebsocket *new_wsi = context->lws_lookup[context->fds[n].fd];
|
||||
struct libwebsocket *new_wsi =
|
||||
context->lws_lookup[context->fds[n].fd];
|
||||
if (!new_wsi)
|
||||
continue;
|
||||
libwebsocket_service_timeout_check(context,
|
||||
|
@ -846,23 +875,32 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
|
|||
* pending connection here, it causes us to check again next time.
|
||||
*/
|
||||
|
||||
if (context->listen_service_fd && pollfd != &context->fds[listen_socket_fds_index]) {
|
||||
if (context->listen_service_fd && pollfd !=
|
||||
&context->fds[listen_socket_fds_index]) {
|
||||
context->listen_service_count++;
|
||||
if (context->listen_service_extraseen ||
|
||||
context->listen_service_count == context->listen_service_modulo) {
|
||||
context->listen_service_count ==
|
||||
context->listen_service_modulo) {
|
||||
context->listen_service_count = 0;
|
||||
m = 1;
|
||||
if (context->listen_service_extraseen > 5)
|
||||
m = 2;
|
||||
while (m--) {
|
||||
/* even with extpoll, we prepared this internal fds for listen */
|
||||
n = poll(&context->fds[listen_socket_fds_index], 1, 0);
|
||||
if (n > 0) { /* there's a connection waiting for us */
|
||||
libwebsocket_service_fd(context, &context->fds[listen_socket_fds_index]);
|
||||
/*
|
||||
* even with extpoll, we prepared this
|
||||
* internal fds for listen
|
||||
*/
|
||||
n = poll(&context->fds[listen_socket_fds_index],
|
||||
1, 0);
|
||||
if (n > 0) { /* there's a conn waiting for us */
|
||||
libwebsocket_service_fd(context,
|
||||
&context->
|
||||
fds[listen_socket_fds_index]);
|
||||
context->listen_service_extraseen++;
|
||||
} else {
|
||||
if (context->listen_service_extraseen)
|
||||
context->listen_service_extraseen--;
|
||||
context->
|
||||
listen_service_extraseen--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -875,7 +913,8 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
|
|||
wsi = context->lws_lookup[pollfd->fd];
|
||||
if (wsi == NULL) {
|
||||
if (pollfd->fd > 11)
|
||||
lwsl_err("unexpected NULL wsi fd=%d fds_count=%d\n", pollfd->fd, context->fds_count);
|
||||
lwsl_err("unexpected NULL wsi fd=%d fds_count=%d\n",
|
||||
pollfd->fd, context->fds_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -926,17 +965,18 @@ read_pending:
|
|||
if (wsi->ssl) {
|
||||
eff_buf.token_len = SSL_read(wsi->ssl,
|
||||
context->service_buffer,
|
||||
sizeof context->service_buffer);
|
||||
sizeof(context->service_buffer));
|
||||
if (!eff_buf.token_len) {
|
||||
n = SSL_get_error(wsi->ssl, eff_buf.token_len);
|
||||
lwsl_err("SSL_read returned 0 with reason %s\n",
|
||||
ERR_error_string(n, (char *)context->service_buffer));
|
||||
ERR_error_string(n,
|
||||
(char *)context->service_buffer));
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
eff_buf.token_len = recv(pollfd->fd,
|
||||
context->service_buffer,
|
||||
sizeof context->service_buffer, 0);
|
||||
context->service_buffer,
|
||||
sizeof(context->service_buffer), 0);
|
||||
|
||||
if (eff_buf.token_len < 0) {
|
||||
lwsl_debug("Socket read returned %d\n",
|
||||
|
@ -947,7 +987,7 @@ read_pending:
|
|||
return 0;
|
||||
}
|
||||
if (!eff_buf.token_len) {
|
||||
lwsl_info("closing connection due to zero length read\n");
|
||||
lwsl_info("closing connection due to 0 length read\n");
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
|
@ -1047,7 +1087,8 @@ libwebsocket_context_destroy(struct libwebsocket_context *context)
|
|||
#endif
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
struct libwebsocket *wsi = context->lws_lookup[context->fds[n].fd];
|
||||
struct libwebsocket *wsi =
|
||||
context->lws_lookup[context->fds[n].fd];
|
||||
libwebsocket_close_and_free_session(context,
|
||||
wsi, LWS_CLOSE_STATUS_NOSTATUS /* no protocol close */);
|
||||
n--;
|
||||
|
@ -1063,7 +1104,9 @@ libwebsocket_context_destroy(struct libwebsocket_context *context)
|
|||
if (context->listen_port)
|
||||
m = LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT;
|
||||
while (ext && ext->callback) {
|
||||
ext->callback(context, ext, NULL, (enum libwebsocket_extension_callback_reasons)m, NULL, NULL, 0);
|
||||
ext->callback(context, ext, NULL,
|
||||
(enum libwebsocket_extension_callback_reasons)m,
|
||||
NULL, NULL, 0);
|
||||
ext++;
|
||||
}
|
||||
|
||||
|
@ -1110,7 +1153,7 @@ libwebsocket_context_destroy(struct libwebsocket_context *context)
|
|||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_context_user() - get the user data associated with the whole context
|
||||
* libwebsocket_context_user() - get the user data associated with the context
|
||||
* @context: Websocket context
|
||||
*
|
||||
* This returns the optional user allocation that can be attached to
|
||||
|
@ -1118,12 +1161,10 @@ libwebsocket_context_destroy(struct libwebsocket_context *context)
|
|||
* to let all sockets serviced in the same context share data without
|
||||
* using globals statics in the user code.
|
||||
*/
|
||||
|
||||
|
||||
LWS_EXTERN void *
|
||||
libwebsocket_context_user(struct libwebsocket_context *context)
|
||||
{
|
||||
return context->user_space;
|
||||
return context->user_space;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1158,7 +1199,6 @@ libwebsocket_context_user(struct libwebsocket_context *context)
|
|||
* nothing is pending, or as soon as it services whatever was pending.
|
||||
*/
|
||||
|
||||
|
||||
int
|
||||
libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
|
||||
{
|
||||
|
@ -1267,8 +1307,8 @@ libwebsocket_callback_on_writable(struct libwebsocket_context *context,
|
|||
return 1;
|
||||
#endif
|
||||
if (wsi->position_in_fds_table < 0) {
|
||||
lwsl_err("libwebsocket_callback_on_writable: "
|
||||
"failed to find socket %d\n", wsi->sock);
|
||||
lwsl_err("libwebsocket_callback_on_writable: failed to find socket %d\n",
|
||||
wsi->sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1349,7 +1389,8 @@ libwebsocket_get_socket_fd(struct libwebsocket *wsi)
|
|||
|
||||
#ifdef LWS_LATENCY
|
||||
void
|
||||
lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi, const char *action, int ret, int completed)
|
||||
lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi,
|
||||
const char *action, int ret, int completed)
|
||||
{
|
||||
struct timeval tv;
|
||||
unsigned long u;
|
||||
|
@ -1362,12 +1403,21 @@ lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi, cons
|
|||
if (action) {
|
||||
if (completed) {
|
||||
if (wsi->action_start == wsi->latency_start)
|
||||
sprintf(buf, "Completion first try lat %luus: %p: ret %d: %s\n", u - wsi->latency_start, (void *)wsi, ret, action);
|
||||
sprintf(buf,
|
||||
"Completion first try lat %luus: %p: ret %d: %s\n",
|
||||
u - wsi->latency_start,
|
||||
(void *)wsi, ret, action);
|
||||
else
|
||||
sprintf(buf, "Completion %luus: lat %luus: %p: ret %d: %s\n", u - wsi->action_start, u - wsi->latency_start, (void *)wsi, ret, action);
|
||||
sprintf(buf,
|
||||
"Completion %luus: lat %luus: %p: ret %d: %s\n",
|
||||
u - wsi->action_start,
|
||||
u - wsi->latency_start,
|
||||
(void *)wsi, ret, action);
|
||||
wsi->action_start = 0;
|
||||
} else
|
||||
sprintf(buf, "lat %luus: %p: ret %d: %s\n", u - wsi->latency_start, (void *)wsi, ret, action);
|
||||
sprintf(buf, "lat %luus: %p: ret %d: %s\n",
|
||||
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);
|
||||
|
@ -1399,13 +1449,14 @@ _libwebsocket_rx_flow_control(struct libwebsocket *wsi)
|
|||
|
||||
wsi->u.ws.rxflow_change_to &= ~2;
|
||||
|
||||
lwsl_info("rxflow: wsi %p change_to %d\n", wsi, wsi->u.ws.rxflow_change_to);
|
||||
lwsl_info("rxflow: wsi %p change_to %d\n",
|
||||
wsi, wsi->u.ws.rxflow_change_to);
|
||||
|
||||
/* if we're letting it come again, did we interrupt anything? */
|
||||
if ((wsi->u.ws.rxflow_change_to & 1) && wsi->u.ws.rxflow_buffer) {
|
||||
n = libwebsocket_interpret_incoming_packet(wsi, NULL, 0);
|
||||
if (n < 0) {
|
||||
lwsl_info("returning that we want to close connection at libwebsocket_rx_flow_control:\n");
|
||||
lwsl_info("libwebsocket_rx_flow_control: close req\n");
|
||||
return -1;
|
||||
}
|
||||
if (n)
|
||||
|
@ -1509,7 +1560,7 @@ OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
|
|||
#endif
|
||||
|
||||
int user_callback_handle_rxflow(callback_function callback_function,
|
||||
struct libwebsocket_context * context,
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len)
|
||||
|
@ -1575,17 +1626,18 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
#endif
|
||||
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
extern int get_daemonize_pid();
|
||||
int pid_daemon = get_daemonize_pid();
|
||||
#endif
|
||||
|
||||
lwsl_notice("Initial logging level %d\n", log_level);
|
||||
lwsl_notice("Library version: %s\n", library_version);
|
||||
lwsl_info(" LWS_MAX_HEADER_NAME_LENGTH: %u\n", LWS_MAX_HEADER_NAME_LENGTH);
|
||||
lwsl_info(" LWS_MAX_HEADER_NAME_LENGTH: %u\n",
|
||||
LWS_MAX_HEADER_NAME_LENGTH);
|
||||
lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
|
||||
lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE);
|
||||
lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n",
|
||||
LWS_MAX_EXTENSIONS_ACTIVE);
|
||||
#else
|
||||
lwsl_notice(" Configured without extension support\n");
|
||||
#endif
|
||||
|
@ -1627,7 +1679,8 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
}
|
||||
#endif
|
||||
|
||||
context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context));
|
||||
context = (struct libwebsocket_context *)
|
||||
malloc(sizeof(struct libwebsocket_context));
|
||||
if (!context) {
|
||||
lwsl_err("No memory for websocket context\n");
|
||||
return NULL;
|
||||
|
@ -1637,7 +1690,7 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
context->started_with_parent = pid_daemon;
|
||||
lwsl_notice(" Started with daemon pid %d\n", pid_daemon);
|
||||
#endif
|
||||
|
||||
|
||||
context->listen_service_extraseen = 0;
|
||||
context->protocols = info->protocols;
|
||||
context->listen_port = info->port;
|
||||
|
@ -1650,17 +1703,24 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
sizeof(struct libwebsocket_context),
|
||||
sizeof(struct pollfd) + sizeof(struct libwebsocket *),
|
||||
context->max_fds,
|
||||
sizeof(struct libwebsocket_context) + ((sizeof(struct pollfd) + sizeof(struct libwebsocket *)) * context->max_fds));
|
||||
sizeof(struct libwebsocket_context) +
|
||||
((sizeof(struct pollfd) + sizeof(struct libwebsocket *)) *
|
||||
context->max_fds));
|
||||
|
||||
context->fds = (struct pollfd *)malloc(sizeof(struct pollfd) * context->max_fds);
|
||||
context->fds = (struct pollfd *)malloc(sizeof(struct pollfd) *
|
||||
context->max_fds);
|
||||
if (context->fds == NULL) {
|
||||
lwsl_err("Unable to allocate fds array for %d connections\n", context->max_fds);
|
||||
lwsl_err("Unable to allocate fds array for %d connections\n",
|
||||
context->max_fds);
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
context->lws_lookup = (struct libwebsocket **)malloc(sizeof(struct libwebsocket *) * context->max_fds);
|
||||
context->lws_lookup = (struct libwebsocket **)
|
||||
malloc(sizeof(struct libwebsocket *) * context->max_fds);
|
||||
if (context->lws_lookup == NULL) {
|
||||
lwsl_err("Unable to allocate lws_lookup array for %d connections\n", context->max_fds);
|
||||
lwsl_err(
|
||||
"Unable to allocate lws_lookup array for %d connections\n",
|
||||
context->max_fds);
|
||||
free(context->fds);
|
||||
free(context);
|
||||
return NULL;
|
||||
|
@ -1700,31 +1760,39 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
|
||||
/* find canonical hostname */
|
||||
|
||||
context->service_buffer[(sizeof context->service_buffer) - 1] = '\0';
|
||||
context->service_buffer[
|
||||
sizeof(context->service_buffer) - 1] = '\0';
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_family = AF_INET;
|
||||
sa.sa_data[(sizeof sa.sa_data) - 1] = '\0';
|
||||
gethostname((char *)context->service_buffer, (sizeof context->service_buffer) - 1);
|
||||
sa.sa_data[sizeof(sa.sa_data) - 1] = '\0';
|
||||
gethostname((char *)context->service_buffer,
|
||||
sizeof(context->service_buffer) - 1);
|
||||
|
||||
n = 0;
|
||||
|
||||
if (strlen((char *)context->service_buffer) < sizeof(sa.sa_data) - 1) {
|
||||
if (strlen((char *)context->service_buffer) <
|
||||
sizeof(sa.sa_data) - 1) {
|
||||
strcpy(sa.sa_data, (char *)context->service_buffer);
|
||||
lwsl_debug("my host name is %s\n", sa.sa_data);
|
||||
n = getnameinfo(&sa, sizeof(sa), (char *)context->service_buffer,
|
||||
(sizeof context->service_buffer) - 1, NULL, 0, NI_NAMEREQD);
|
||||
n = getnameinfo(&sa, sizeof(sa),
|
||||
(char *)context->service_buffer,
|
||||
sizeof(context->service_buffer) - 1,
|
||||
NULL, 0, NI_NAMEREQD);
|
||||
}
|
||||
|
||||
if (!n) {
|
||||
strncpy(context->canonical_hostname, (char *)context->service_buffer,
|
||||
sizeof context->canonical_hostname - 1);
|
||||
strncpy(context->canonical_hostname,
|
||||
(char *)context->service_buffer,
|
||||
sizeof(context->canonical_hostname) - 1);
|
||||
context->canonical_hostname[
|
||||
sizeof context->canonical_hostname - 1] = '\0';
|
||||
sizeof(context->canonical_hostname) - 1] = '\0';
|
||||
} else
|
||||
strncpy(context->canonical_hostname, (char *)context->service_buffer,
|
||||
sizeof context->canonical_hostname - 1);
|
||||
strncpy(context->canonical_hostname,
|
||||
(char *)context->service_buffer,
|
||||
sizeof(context->canonical_hostname) - 1);
|
||||
|
||||
lwsl_notice(" canonical_hostname = %s\n", context->canonical_hostname);
|
||||
lwsl_notice(" canonical_hostname = %s\n",
|
||||
context->canonical_hostname);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1733,9 +1801,9 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
p = getenv("http_proxy");
|
||||
if (p) {
|
||||
strncpy(context->http_proxy_address, p,
|
||||
sizeof context->http_proxy_address - 1);
|
||||
sizeof(context->http_proxy_address) - 1);
|
||||
context->http_proxy_address[
|
||||
sizeof context->http_proxy_address - 1] = '\0';
|
||||
sizeof(context->http_proxy_address) - 1] = '\0';
|
||||
|
||||
p = strchr(context->http_proxy_address, ':');
|
||||
if (p == NULL) {
|
||||
|
@ -1772,11 +1840,13 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
lwsl_notice(" Not compiled for OpenSSl support!\n");
|
||||
goto bail;
|
||||
}
|
||||
lwsl_notice(" Compiled without SSL support, "
|
||||
"serving unencrypted\n");
|
||||
lwsl_notice(" Compiled without SSL support\n");
|
||||
#endif
|
||||
|
||||
lwsl_notice(" per-connection allocation: %u + %u headers (only during handshake) + frame buffer set by protocol\n", sizeof(struct libwebsocket), sizeof(struct allocated_headers));
|
||||
lwsl_notice(
|
||||
" per-conn mem: %u + %u headers + protocol rx buf\n",
|
||||
sizeof(struct libwebsocket),
|
||||
sizeof(struct allocated_headers));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1807,13 +1877,15 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
method = (SSL_METHOD *)SSLv23_server_method();
|
||||
if (!method) {
|
||||
lwsl_err("problem creating ssl method: %s\n",
|
||||
ERR_error_string(ERR_get_error(), (char *)context->service_buffer));
|
||||
ERR_error_string(ERR_get_error(),
|
||||
(char *)context->service_buffer));
|
||||
goto bail;
|
||||
}
|
||||
context->ssl_ctx = SSL_CTX_new(method); /* create context */
|
||||
if (!context->ssl_ctx) {
|
||||
lwsl_err("problem creating ssl context: %s\n",
|
||||
ERR_error_string(ERR_get_error(), (char *)context->service_buffer));
|
||||
ERR_error_string(ERR_get_error(),
|
||||
(char *)context->service_buffer));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
|
@ -1831,22 +1903,27 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
method = (SSL_METHOD *)SSLv23_client_method();
|
||||
if (!method) {
|
||||
lwsl_err("problem creating ssl method: %s\n",
|
||||
ERR_error_string(ERR_get_error(), (char *)context->service_buffer));
|
||||
ERR_error_string(ERR_get_error(),
|
||||
(char *)context->service_buffer));
|
||||
goto bail;
|
||||
}
|
||||
/* create context */
|
||||
context->ssl_client_ctx = SSL_CTX_new(method);
|
||||
if (!context->ssl_client_ctx) {
|
||||
lwsl_err("problem creating ssl context: %s\n",
|
||||
ERR_error_string(ERR_get_error(), (char *)context->service_buffer));
|
||||
ERR_error_string(ERR_get_error(),
|
||||
(char *)context->service_buffer));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
#ifdef SSL_OP_NO_COMPRESSION
|
||||
SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_NO_COMPRESSION);
|
||||
SSL_CTX_set_options(context->ssl_client_ctx,
|
||||
SSL_OP_NO_COMPRESSION);
|
||||
#endif
|
||||
SSL_CTX_set_options(context->ssl_client_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
SSL_CTX_set_cipher_list(context->ssl_client_ctx, CIPHERS_LIST_STRING);
|
||||
SSL_CTX_set_options(context->ssl_client_ctx,
|
||||
SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
SSL_CTX_set_cipher_list(context->ssl_client_ctx,
|
||||
CIPHERS_LIST_STRING);
|
||||
|
||||
/* openssl init for cert verification (for client sockets) */
|
||||
if (!info->ssl_ca_filepath) {
|
||||
|
@ -1854,10 +1931,10 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
context->ssl_client_ctx, NULL,
|
||||
LWS_OPENSSL_CLIENT_CERTS))
|
||||
lwsl_err(
|
||||
"Unable to load SSL Client certs from %s "
|
||||
"(set by --with-client-cert-dir= in configure) -- "
|
||||
" client ssl isn't going to work",
|
||||
LWS_OPENSSL_CLIENT_CERTS);
|
||||
"Unable to load SSL Client certs from %s "
|
||||
"(set by --with-client-cert-dir= "
|
||||
"in configure) -- client ssl isn't "
|
||||
"going to work", LWS_OPENSSL_CLIENT_CERTS);
|
||||
} else
|
||||
if (!SSL_CTX_load_verify_locations(
|
||||
context->ssl_client_ctx, info->ssl_ca_filepath,
|
||||
|
@ -1880,7 +1957,8 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
|
||||
/* as a server, are we requiring clients to identify themselves? */
|
||||
|
||||
if (info->options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
|
||||
if (info->options &
|
||||
LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
|
||||
|
||||
/* absolutely require the client cert */
|
||||
|
||||
|
@ -1908,7 +1986,8 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
if (n != 1) {
|
||||
lwsl_err("problem getting cert '%s': %s\n",
|
||||
info->ssl_cert_filepath,
|
||||
ERR_error_string(ERR_get_error(), (char *)context->service_buffer));
|
||||
ERR_error_string(ERR_get_error(),
|
||||
(char *)context->service_buffer));
|
||||
goto bail;
|
||||
}
|
||||
/* set the private key from KeyFile */
|
||||
|
@ -1916,8 +1995,9 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
info->ssl_private_key_filepath,
|
||||
SSL_FILETYPE_PEM) != 1) {
|
||||
lwsl_err("ssl problem getting key '%s': %s\n",
|
||||
info->ssl_private_key_filepath,
|
||||
ERR_error_string(ERR_get_error(), (char *)context->service_buffer));
|
||||
info->ssl_private_key_filepath,
|
||||
ERR_error_string(ERR_get_error(),
|
||||
(char *)context->service_buffer));
|
||||
goto bail;
|
||||
}
|
||||
/* verify private key */
|
||||
|
@ -1939,7 +2019,6 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
/* set up our external listening socket we serve on */
|
||||
|
||||
if (info->port) {
|
||||
extern int interface_to_sa(const char *ifname, struct sockaddr_in *addr, size_t addrlen);
|
||||
int sockfd;
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
@ -1949,10 +2028,13 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
}
|
||||
|
||||
#ifndef WIN32
|
||||
/* allow us to restart even if old sockets in TIME_WAIT
|
||||
* (REUSEADDR on Unix means, "don't hang on to this address after the
|
||||
* listener is closed." On Windows, though, it means "don't keep other
|
||||
* processes from binding to this address while we're using it) */
|
||||
/*
|
||||
* allow us to restart even if old sockets in TIME_WAIT
|
||||
* (REUSEADDR on Unix means, "don't hang on to this
|
||||
* address after the listener is closed." On Windows, though,
|
||||
* it means "don't keep other processes from binding to
|
||||
* this address while we're using it)
|
||||
*/
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const void *)&opt, sizeof(opt));
|
||||
#endif
|
||||
|
@ -1964,7 +2046,7 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
|
||||
#ifdef WIN32
|
||||
opt = 0;
|
||||
ioctlsocket(sockfd, FIONBIO, (unsigned long *)&opt );
|
||||
ioctlsocket(sockfd, FIONBIO, (unsigned long *)&opt);
|
||||
#else
|
||||
fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
||||
#endif
|
||||
|
@ -1987,13 +2069,14 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
goto bail;
|
||||
}
|
||||
|
||||
wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
|
||||
wsi = (struct libwebsocket *)malloc(
|
||||
sizeof(struct libwebsocket));
|
||||
if (wsi == NULL) {
|
||||
lwsl_err("Out of mem\n");
|
||||
close(sockfd);
|
||||
goto bail;
|
||||
}
|
||||
memset(wsi, 0, sizeof (struct libwebsocket));
|
||||
memset(wsi, 0, sizeof(struct libwebsocket));
|
||||
wsi->sock = sockfd;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
wsi->count_active_extensions = 0;
|
||||
|
@ -2057,7 +2140,7 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
m = LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT;
|
||||
if (info->port)
|
||||
m = LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT;
|
||||
|
||||
|
||||
if (info->extensions) {
|
||||
ext = info->extensions;
|
||||
while (ext->callback) {
|
||||
|
@ -2134,10 +2217,10 @@ static void lwsl_emit_stderr(int level, const char *line)
|
|||
for (n = 0; n < LLL_COUNT; n++)
|
||||
if (level == (1 << n)) {
|
||||
sprintf(buf, "[%ld:%04d] %s: ", tv.tv_sec,
|
||||
(int)(tv.tv_usec / 100), log_level_names[n]);
|
||||
(int)(tv.tv_usec / 100), log_level_names[n]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
fprintf(stderr, "%s%s", buf, line);
|
||||
}
|
||||
|
||||
|
@ -2178,8 +2261,8 @@ void _lws_log(int filter, const char *format, ...)
|
|||
return;
|
||||
|
||||
va_start(ap, format);
|
||||
vsnprintf(buf, (sizeof buf), format, ap);
|
||||
buf[(sizeof buf) - 1] = '\0';
|
||||
vsnprintf(buf, sizeof(buf), format, ap);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
va_end(ap);
|
||||
|
||||
lwsl_emit(filter, buf);
|
||||
|
@ -2196,7 +2279,8 @@ void _lws_log(int filter, const char *format, ...)
|
|||
* emission on stderr.
|
||||
*/
|
||||
|
||||
void lws_set_log_level(int level, void (*log_emit_function)(int level, const char *line))
|
||||
void lws_set_log_level(int level, void (*log_emit_function)(int level,
|
||||
const char *line))
|
||||
{
|
||||
log_level = level;
|
||||
if (log_emit_function)
|
||||
|
|
|
@ -360,8 +360,8 @@ enum lws_close_status {
|
|||
LWS_CLOSE_STATUS_POLICY_VIOLATION = 1008,
|
||||
LWS_CLOSE_STATUS_MESSAGE_TOO_LARGE = 1009,
|
||||
LWS_CLOSE_STATUS_EXTENSION_REQUIRED = 1010,
|
||||
LWS_CLOSE_STATUS_UNEXPECTED_CONDITION = 1011,
|
||||
LWS_CLOSE_STATUS_TLS_FAILURE = 1015,
|
||||
LWS_CLOSE_STATUS_UNEXPECTED_CONDITION = 1011,
|
||||
LWS_CLOSE_STATUS_TLS_FAILURE = 1015,
|
||||
};
|
||||
|
||||
struct libwebsocket;
|
||||
|
@ -395,12 +395,12 @@ struct libwebsocket_extension;
|
|||
* been unable to complete a handshake with the remote server
|
||||
*
|
||||
* LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH: this is the last chance for the
|
||||
* client user code to examine the http headers
|
||||
* and decide to reject the connection. If the
|
||||
* content in the headers is interesting to the
|
||||
* client (url, etc) it needs to copy it out at
|
||||
* this point since it will be destroyed before
|
||||
* the CLIENT_ESTABLISHED call
|
||||
* client user code to examine the http headers
|
||||
* and decide to reject the connection. If the
|
||||
* content in the headers is interesting to the
|
||||
* client (url, etc) it needs to copy it out at
|
||||
* this point since it will be destroyed before
|
||||
* the CLIENT_ESTABLISHED call
|
||||
*
|
||||
* LWS_CALLBACK_CLIENT_ESTABLISHED: after your client connection completed
|
||||
* a handshake with the remote server
|
||||
|
@ -455,22 +455,22 @@ struct libwebsocket_extension;
|
|||
* or not, based on the client IP. @user contains the connection
|
||||
* socket's descriptor. Return non-zero to terminate
|
||||
* the connection before sending or receiving anything.
|
||||
* Because this happens immediately after the network connection
|
||||
* Because this happens immediately after the network connection
|
||||
* from the client, there's no websocket protocol selected yet so
|
||||
* this callback is issued only to protocol 0.
|
||||
*
|
||||
* LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: called when the handshake has
|
||||
* been received and parsed from the client, but the response is
|
||||
* not sent yet. Return non-zero to disallow the connection.
|
||||
* LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: called when the handshake has
|
||||
* been received and parsed from the client, but the response is
|
||||
* not sent yet. Return non-zero to disallow the connection.
|
||||
* @user is a pointer to an array of struct lws_tokens, you can
|
||||
* use the header enums lws_token_indexes from libwebsockets.h
|
||||
* to check for and read the supported header presence and
|
||||
* content before deciding to allow the handshake to proceed or
|
||||
* to kill the connection.
|
||||
*
|
||||
* LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: if configured for
|
||||
* including OpenSSL support, this callback allows your user code
|
||||
* to perform extra SSL_CTX_load_verify_locations() or similar
|
||||
* LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: if configured for
|
||||
* including OpenSSL support, this callback allows your user code
|
||||
* to perform extra SSL_CTX_load_verify_locations() or similar
|
||||
* calls to direct OpenSSL where to find certificates the client
|
||||
* can use to confirm the remote server identity. @user is the
|
||||
* OpenSSL SSL_CTX*
|
||||
|
@ -510,8 +510,8 @@ struct libwebsocket_extension;
|
|||
*
|
||||
* char **p = (char **)in;
|
||||
*
|
||||
* if (len < 100)
|
||||
* return 1;
|
||||
* if (len < 100)
|
||||
* return 1;
|
||||
*
|
||||
* *p += sprintf(*p, "Cookie: a=b\x0d\x0a");
|
||||
*
|
||||
|
@ -521,10 +521,10 @@ struct libwebsocket_extension;
|
|||
* the CRLF on the line you added. Obviously this callback is
|
||||
* optional, if you don't handle it everything is fine.
|
||||
*
|
||||
* Notice the callback is coming to protocols[0] all the time,
|
||||
* Notice the callback is coming to protocols[0] all the time,
|
||||
* because there is no specific protocol handshook yet.
|
||||
*
|
||||
* LWS_CALLBACK_CONFIRM_EXTENSION_OKAY: When the server handshake code
|
||||
* LWS_CALLBACK_CONFIRM_EXTENSION_OKAY: When the server handshake code
|
||||
* sees that it does support a requested extension, before
|
||||
* accepting the extension by additing to the list sent back to
|
||||
* the client it gives this callback just to check that it's okay
|
||||
|
@ -553,45 +553,45 @@ struct libwebsocket_extension;
|
|||
* deallocate everything that was allocated by the protocol.
|
||||
*
|
||||
* The next four reasons are optional and only need taking care of if you
|
||||
* will be integrating libwebsockets sockets into an external polling
|
||||
* array.
|
||||
*
|
||||
* LWS_CALLBACK_ADD_POLL_FD: libwebsocket deals with its poll() loop
|
||||
* internally, but in the case you are integrating with another
|
||||
* server you will need to have libwebsocket sockets share a
|
||||
* polling array with the other server. This and the other
|
||||
* POLL_FD related callbacks let you put your specialized
|
||||
* poll array interface code in the callback for protocol 0, the
|
||||
* first protocol you support, usually the HTTP protocol in the
|
||||
* serving case. This callback happens when a socket needs to be
|
||||
* will be integrating libwebsockets sockets into an external polling
|
||||
* array.
|
||||
*
|
||||
* LWS_CALLBACK_ADD_POLL_FD: libwebsocket deals with its poll() loop
|
||||
* internally, but in the case you are integrating with another
|
||||
* server you will need to have libwebsocket sockets share a
|
||||
* polling array with the other server. This and the other
|
||||
* POLL_FD related callbacks let you put your specialized
|
||||
* poll array interface code in the callback for protocol 0, the
|
||||
* first protocol you support, usually the HTTP protocol in the
|
||||
* serving case. This callback happens when a socket needs to be
|
||||
* added to the polling loop: @user contains the fd, and
|
||||
* @len is the events bitmap (like, POLLIN). If you are using the
|
||||
* @len is the events bitmap (like, POLLIN). If you are using the
|
||||
* internal polling loop (the "service" callback), you can just
|
||||
* ignore these callbacks.
|
||||
* ignore these callbacks.
|
||||
*
|
||||
* LWS_CALLBACK_DEL_POLL_FD: This callback happens when a socket descriptor
|
||||
* needs to be removed from an external polling array. @user is
|
||||
* the socket desricptor. If you are using the internal polling
|
||||
* loop, you can just ignore it.
|
||||
* LWS_CALLBACK_DEL_POLL_FD: This callback happens when a socket descriptor
|
||||
* needs to be removed from an external polling array. @user is
|
||||
* the socket desricptor. If you are using the internal polling
|
||||
* loop, you can just ignore it.
|
||||
*
|
||||
* LWS_CALLBACK_SET_MODE_POLL_FD: This callback happens when libwebsockets
|
||||
* wants to modify the events for the socket descriptor in @user.
|
||||
* LWS_CALLBACK_SET_MODE_POLL_FD: This callback happens when libwebsockets
|
||||
* wants to modify the events for the socket descriptor in @user.
|
||||
* The handler should OR @len on to the events member of the pollfd
|
||||
* struct for this socket descriptor. If you are using the
|
||||
* struct for this socket descriptor. If you are using the
|
||||
* internal polling loop, you can just ignore it.
|
||||
*
|
||||
* LWS_CALLBACK_CLEAR_MODE_POLL_FD: This callback occurs when libwebsockets
|
||||
* wants to modify the events for the socket descriptor in @user.
|
||||
* wants to modify the events for the socket descriptor in @user.
|
||||
* The handler should AND ~@len on to the events member of the
|
||||
* pollfd struct for this socket descriptor. If you are using the
|
||||
* pollfd struct for this socket descriptor. If you are using the
|
||||
* internal polling loop, you can just ignore it.
|
||||
*/
|
||||
LWS_EXTERN int callback(struct libwebsocket_context * context,
|
||||
LWS_EXTERN int callback(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len);
|
||||
|
||||
typedef int (callback_function)(struct libwebsocket_context * context,
|
||||
typedef int (callback_function)(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len);
|
||||
|
@ -622,7 +622,7 @@ typedef int (callback_function)(struct libwebsocket_context * context,
|
|||
* extension a chance to initialize its connection context found
|
||||
* in @user.
|
||||
*
|
||||
* LWS_EXT_CALLBACK_CLIENT_CONSTRUCT: same as LWS_EXT_CALLBACK_CONSTRUCT
|
||||
* LWS_EXT_CALLBACK_CLIENT_CONSTRUCT: same as LWS_EXT_CALLBACK_CONSTRUCT
|
||||
* but called when client is instantiating this extension. Some
|
||||
* extensions will work the same on client and server side and then
|
||||
* you can just merge handlers for both CONSTRUCTS.
|
||||
|
@ -655,17 +655,17 @@ typedef int (callback_function)(struct libwebsocket_context * context,
|
|||
* buffer safely, it should copy the data into its own buffer and
|
||||
* set the lws_tokens token pointer to it.
|
||||
*/
|
||||
LWS_EXTERN int extension_callback(struct libwebsocket_context * context,
|
||||
LWS_EXTERN int extension_callback(struct libwebsocket_context *context,
|
||||
struct libwebsocket_extension *ext,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons reason, void *user,
|
||||
void *in, size_t len);
|
||||
enum libwebsocket_extension_callback_reasons reason,
|
||||
void *user, void *in, size_t len);
|
||||
|
||||
typedef int (extension_callback_function)(struct libwebsocket_context * context,
|
||||
typedef int (extension_callback_function)(struct libwebsocket_context *context,
|
||||
struct libwebsocket_extension *ext,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons reason, void *user,
|
||||
void *in, size_t len);
|
||||
enum libwebsocket_extension_callback_reasons reason,
|
||||
void *user, void *in, size_t len);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -681,13 +681,13 @@ typedef int (extension_callback_function)(struct libwebsocket_context * context,
|
|||
* freed on connection takedown. A pointer to this per-connection
|
||||
* allocation is passed into the callback in the 'user' parameter
|
||||
* @rx_buffer_size: if you want atomic frames delivered to the callback, you
|
||||
* should set this to the size of the biggest legal frame that
|
||||
* you support. If the frame size is exceeded, there is no
|
||||
* error, but the buffer will spill to the user callback when
|
||||
* full, which you can detect by using
|
||||
* libwebsockets_remaining_packet_payload(). Notice that you
|
||||
* just talk about frame size here, the LWS_SEND_BUFFER_PRE_PADDING
|
||||
* and post-padding are automatically also allocated on top.
|
||||
* should set this to the size of the biggest legal frame that
|
||||
* you support. If the frame size is exceeded, there is no
|
||||
* error, but the buffer will spill to the user callback when
|
||||
* full, which you can detect by using
|
||||
* libwebsockets_remaining_packet_payload(). Notice that you
|
||||
* just talk about frame size here, the LWS_SEND_BUFFER_PRE_PADDING
|
||||
* and post-padding are automatically also allocated on top.
|
||||
* @owning_server: the server init call fills in this opaque pointer when
|
||||
* registering this protocol with the server.
|
||||
* @protocol_index: which protocol we are starting from zero
|
||||
|
@ -718,19 +718,19 @@ struct libwebsocket_protocols {
|
|||
*
|
||||
* @name: Formal extension name, eg, "deflate-stream"
|
||||
* @callback: Service callback
|
||||
* @per_session_data_size: Libwebsockets will auto-malloc this much
|
||||
* memory for the use of the extension, a pointer
|
||||
* @per_session_data_size: Libwebsockets will auto-malloc this much
|
||||
* memory for the use of the extension, a pointer
|
||||
* to it comes in the @user callback parameter
|
||||
* @per_context_private_data: Optional storage for this extension that
|
||||
* is per-context, so it can track stuff across
|
||||
* all sessions, etc, if it wants
|
||||
* is per-context, so it can track stuff across
|
||||
* all sessions, etc, if it wants
|
||||
*/
|
||||
|
||||
struct libwebsocket_extension {
|
||||
const char *name;
|
||||
extension_callback_function *callback;
|
||||
size_t per_session_data_size;
|
||||
void * per_context_private_data;
|
||||
void *per_context_private_data;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -759,7 +759,7 @@ struct libwebsocket_extension {
|
|||
* @uid: user id to change to after setting listen socket, or -1.
|
||||
* @options: 0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
|
||||
* @user: optional user pointer that can be recovered via the context
|
||||
* pointer using libwebsocket_context_user
|
||||
* pointer using libwebsocket_context_user
|
||||
* @ka_time: 0 for no keepalive, otherwise apply this keepalive timeout to
|
||||
* all libwebsocket sockets, client or server
|
||||
* @ka_probes: if ka_time was nonzero, after the timeout expires how many
|
||||
|
@ -788,7 +788,8 @@ struct lws_context_creation_info {
|
|||
};
|
||||
|
||||
LWS_EXTERN
|
||||
void lws_set_log_level(int level, void (*log_emit_function)(int level, const char *line));
|
||||
void lws_set_log_level(int level,
|
||||
void (*log_emit_function)(int level, const char *line));
|
||||
|
||||
LWS_EXTERN void
|
||||
lwsl_emit_syslog(int level, const char *line);
|
||||
|
@ -954,7 +955,8 @@ extern int
|
|||
lws_hdr_total_length(struct libwebsocket *wsi, enum lws_token_indexes h);
|
||||
|
||||
extern int
|
||||
lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len, enum lws_token_indexes h);
|
||||
lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len,
|
||||
enum lws_token_indexes h);
|
||||
|
||||
/*
|
||||
* Note: this is not normally needed as a user api. It's provided in case it is
|
||||
|
|
50
lib/output.c
50
lib/output.c
|
@ -33,7 +33,7 @@ libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi)
|
|||
/* fetch the per-frame nonce */
|
||||
|
||||
n = libwebsockets_get_random(wsi->protocol->owning_server,
|
||||
wsi->u.ws.frame_masking_nonce_04, 4);
|
||||
wsi->u.ws.frame_masking_nonce_04, 4);
|
||||
if (n != 4) {
|
||||
lwsl_parser("Unable to read from random device %s %d\n",
|
||||
SYSTEM_RANDOM_FILEPATH, n);
|
||||
|
@ -147,7 +147,7 @@ int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len)
|
|||
n = send(wsi->sock, buf, len, MSG_NOSIGNAL);
|
||||
lws_latency(context, wsi, "send lws_issue_raw", n, n == len);
|
||||
if (n != len) {
|
||||
lwsl_debug("ERROR writing len %d to socket %d\n", len, n);
|
||||
lwsl_debug("ERROR writing len %d to skt %d\n", len, n);
|
||||
return -1;
|
||||
}
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
|
@ -372,8 +372,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
|
|||
n = LWS_WS_OPCODE_07__PONG;
|
||||
break;
|
||||
default:
|
||||
lwsl_warn("libwebsocket_write: unknown write "
|
||||
"opcode / protocol\n");
|
||||
lwsl_warn("lws_write: unknown write opc / protocol\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -423,8 +422,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
|
|||
if (wsi->mode == LWS_CONNMODE_WS_CLIENT) {
|
||||
|
||||
if (libwebsocket_0405_frame_mask_generate(wsi)) {
|
||||
lwsl_err("libwebsocket_write: "
|
||||
"frame mask generation failed\n");
|
||||
lwsl_err("lws_write: frame mask generation failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -432,7 +430,9 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
|
|||
* in v7, just mask the payload
|
||||
*/
|
||||
for (n = 4; n < (int)len + 4; n++)
|
||||
dropmask[n] = dropmask[n] ^ wsi->u.ws.frame_masking_nonce_04[(wsi->u.ws.frame_mask_index++) & 3];
|
||||
dropmask[n] = dropmask[n] ^
|
||||
wsi->u.ws.frame_masking_nonce_04[
|
||||
(wsi->u.ws.frame_mask_index++) & 3];
|
||||
|
||||
if (dropmask)
|
||||
/* copy the frame nonce into place */
|
||||
|
@ -449,7 +449,7 @@ send_raw:
|
|||
|
||||
switch (protocol) {
|
||||
case LWS_WRITE_CLOSE:
|
||||
// lwsl_hexdump(&buf[-pre], len + post);
|
||||
/* lwsl_hexdump(&buf[-pre], len + post); */
|
||||
case LWS_WRITE_HTTP:
|
||||
case LWS_WRITE_PONG:
|
||||
case LWS_WRITE_PING:
|
||||
|
@ -479,28 +479,33 @@ send_raw:
|
|||
return lws_issue_raw_ext_access(wsi, buf - pre, len + pre + post);
|
||||
}
|
||||
|
||||
int libwebsockets_serve_http_file_fragment(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
int libwebsockets_serve_http_file_fragment(
|
||||
struct libwebsocket_context *context, struct libwebsocket *wsi)
|
||||
{
|
||||
int ret = 0;
|
||||
int n;
|
||||
|
||||
while (!lws_send_pipe_choked(wsi)) {
|
||||
n = read(wsi->u.http.fd, context->service_buffer, sizeof(context->service_buffer));
|
||||
n = read(wsi->u.http.fd, context->service_buffer,
|
||||
sizeof(context->service_buffer));
|
||||
if (n > 0) {
|
||||
libwebsocket_write(wsi, context->service_buffer, n, LWS_WRITE_HTTP);
|
||||
libwebsocket_write(wsi, context->service_buffer, n,
|
||||
LWS_WRITE_HTTP);
|
||||
wsi->u.http.filepos += n;
|
||||
}
|
||||
|
||||
if (n < 0)
|
||||
return 1; /* caller will close */
|
||||
|
||||
if (n < sizeof(context->service_buffer) || wsi->u.http.filepos == wsi->u.http.filelen) {
|
||||
if (n < sizeof(context->service_buffer) ||
|
||||
wsi->u.http.filepos == wsi->u.http.filelen) {
|
||||
wsi->state = WSI_STATE_HTTP;
|
||||
|
||||
if (wsi->protocol->callback)
|
||||
ret = user_callback_handle_rxflow(wsi->protocol->callback, context, wsi, LWS_CALLBACK_HTTP_FILE_COMPLETION, wsi->user_space,
|
||||
NULL, 0);
|
||||
ret = user_callback_handle_rxflow(
|
||||
wsi->protocol->callback, context, wsi,
|
||||
LWS_CALLBACK_HTTP_FILE_COMPLETION,
|
||||
wsi->user_space, NULL, 0);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -543,9 +548,8 @@ int libwebsockets_serve_http_file(struct libwebsocket_context *context,
|
|||
);
|
||||
|
||||
if (wsi->u.http.fd < 1) {
|
||||
p += sprintf((char *)p, "HTTP/1.0 400 Bad\x0d\x0a"
|
||||
"Server: libwebsockets\x0d\x0a"
|
||||
"\x0d\x0a"
|
||||
p += sprintf((char *)p,
|
||||
"HTTP/1.0 400 Bad\x0d\x0aServer: libwebsockets\x0d\x0a\x0d\x0a"
|
||||
);
|
||||
wsi->u.http.fd = 0;
|
||||
libwebsocket_write(wsi, context->service_buffer,
|
||||
|
@ -556,11 +560,11 @@ int libwebsockets_serve_http_file(struct libwebsocket_context *context,
|
|||
|
||||
fstat(wsi->u.http.fd, &stat_buf);
|
||||
wsi->u.http.filelen = stat_buf.st_size;
|
||||
p += sprintf((char *)p, "HTTP/1.0 200 OK\x0d\x0a"
|
||||
"Server: libwebsockets\x0d\x0a"
|
||||
"Content-Type: %s\x0d\x0a"
|
||||
"Content-Length: %u\x0d\x0a"
|
||||
"\x0d\x0a", content_type,
|
||||
p += sprintf((char *)p,
|
||||
"HTTP/1.0 200 OK\x0d\x0aServer: libwebsockets\x0d\x0aContent-Type: %s\x0d\x0a",
|
||||
content_type);
|
||||
p += sprintf((char *)p,
|
||||
"Content-Length: %u\x0d\x0a\x0d\x0a",
|
||||
(unsigned int)stat_buf.st_size);
|
||||
|
||||
ret = libwebsocket_write(wsi, context->service_buffer,
|
||||
|
|
684
lib/parsers.c
684
lib/parsers.c
|
@ -27,273 +27,273 @@
|
|||
|
||||
|
||||
unsigned char lextable[] = {
|
||||
/* pos 0: state 0 */
|
||||
0x47 /* 'G' */, 0x07 /* to pos 14 state 1 */,
|
||||
0x48 /* 'H' */, 0x0A /* to pos 22 state 5 */,
|
||||
0x43 /* 'C' */, 0x0F /* to pos 34 state 10 */,
|
||||
0x53 /* 'S' */, 0x19 /* to pos 56 state 21 */,
|
||||
0x55 /* 'U' */, 0x3F /* to pos 134 state 51 */,
|
||||
0x4F /* 'O' */, 0x46 /* to pos 150 state 59 */,
|
||||
0x8D /* '.' */, 0x52 /* to pos 176 state 72 */,
|
||||
/* pos 14: state 1 */
|
||||
0xC5 /* 'E' */, 0x01 /* to pos 16 state 2 */,
|
||||
/* pos 16: state 2 */
|
||||
0xD4 /* 'T' */, 0x01 /* to pos 18 state 3 */,
|
||||
/* pos 18: state 3 */
|
||||
0xA0 /* ' ' */, 0x01 /* to pos 20 state 4 */,
|
||||
/* pos 20: state 4 */
|
||||
0x80, 0x00 /* terminal marker */,
|
||||
/* pos 22: state 5 */
|
||||
0x6F /* 'o' */, 0x02 /* to pos 26 state 6 */,
|
||||
0xD4 /* 'T' */, 0x76 /* to pos 260 state 114 */,
|
||||
/* pos 26: state 6 */
|
||||
0xF3 /* 's' */, 0x01 /* to pos 28 state 7 */,
|
||||
/* pos 28: state 7 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 30 state 8 */,
|
||||
/* pos 30: state 8 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 32 state 9 */,
|
||||
/* pos 32: state 9 */
|
||||
0x81, 0x00 /* terminal marker */,
|
||||
/* pos 34: state 10 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 36 state 11 */,
|
||||
/* pos 36: state 11 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 38 state 12 */,
|
||||
/* pos 38: state 12 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 40 state 13 */,
|
||||
/* pos 40: state 13 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 42 state 14 */,
|
||||
/* pos 42: state 14 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 44 state 15 */,
|
||||
/* pos 44: state 15 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 46 state 16 */,
|
||||
/* pos 46: state 16 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 48 state 17 */,
|
||||
/* pos 48: state 17 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 50 state 18 */,
|
||||
/* pos 50: state 18 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 52 state 19 */,
|
||||
/* pos 52: state 19 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 54 state 20 */,
|
||||
/* pos 54: state 20 */
|
||||
0x82, 0x00 /* terminal marker */,
|
||||
/* pos 56: state 21 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 58 state 22 */,
|
||||
/* pos 58: state 22 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 60 state 23 */,
|
||||
/* pos 60: state 23 */
|
||||
0xAD /* '-' */, 0x01 /* to pos 62 state 24 */,
|
||||
/* pos 62: state 24 */
|
||||
0xD7 /* 'W' */, 0x01 /* to pos 64 state 25 */,
|
||||
/* pos 64: state 25 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 66 state 26 */,
|
||||
/* pos 66: state 26 */
|
||||
0xE2 /* 'b' */, 0x01 /* to pos 68 state 27 */,
|
||||
/* pos 68: state 27 */
|
||||
0xD3 /* 'S' */, 0x01 /* to pos 70 state 28 */,
|
||||
/* pos 70: state 28 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 72 state 29 */,
|
||||
/* pos 72: state 29 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 74 state 30 */,
|
||||
/* pos 74: state 30 */
|
||||
0xEB /* 'k' */, 0x01 /* to pos 76 state 31 */,
|
||||
/* pos 76: state 31 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 78 state 32 */,
|
||||
/* pos 78: state 32 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 80 state 33 */,
|
||||
/* pos 80: state 33 */
|
||||
0xAD /* '-' */, 0x01 /* to pos 82 state 34 */,
|
||||
/* pos 82: state 34 */
|
||||
0x4B /* 'K' */, 0x08 /* to pos 98 state 35 */,
|
||||
0x50 /* 'P' */, 0x10 /* to pos 116 state 42 */,
|
||||
0x44 /* 'D' */, 0x27 /* to pos 164 state 66 */,
|
||||
0x56 /* 'V' */, 0x2F /* to pos 182 state 75 */,
|
||||
0x4F /* 'O' */, 0x36 /* to pos 198 state 83 */,
|
||||
0x45 /* 'E' */, 0x3C /* to pos 212 state 90 */,
|
||||
0x41 /* 'A' */, 0x46 /* to pos 234 state 101 */,
|
||||
0xCE /* 'N' */, 0x4C /* to pos 248 state 108 */,
|
||||
/* pos 98: state 35 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 100 state 36 */,
|
||||
/* pos 100: state 36 */
|
||||
0xF9 /* 'y' */, 0x01 /* to pos 102 state 37 */,
|
||||
/* pos 102: state 37 */
|
||||
0x31 /* '1' */, 0x03 /* to pos 108 state 38 */,
|
||||
0x32 /* '2' */, 0x04 /* to pos 112 state 40 */,
|
||||
0xBA /* ':' */, 0x25 /* to pos 180 state 74 */,
|
||||
/* pos 108: state 38 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 110 state 39 */,
|
||||
/* pos 110: state 39 */
|
||||
0x83, 0x00 /* terminal marker */,
|
||||
/* pos 112: state 40 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 114 state 41 */,
|
||||
/* pos 114: state 41 */
|
||||
0x84, 0x00 /* terminal marker */,
|
||||
/* pos 116: state 42 */
|
||||
0xF2 /* 'r' */, 0x01 /* to pos 118 state 43 */,
|
||||
/* pos 118: state 43 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 120 state 44 */,
|
||||
/* pos 120: state 44 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 122 state 45 */,
|
||||
/* pos 122: state 45 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 124 state 46 */,
|
||||
/* pos 124: state 46 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 126 state 47 */,
|
||||
/* pos 126: state 47 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 128 state 48 */,
|
||||
/* pos 128: state 48 */
|
||||
0xEC /* 'l' */, 0x01 /* to pos 130 state 49 */,
|
||||
/* pos 130: state 49 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 132 state 50 */,
|
||||
/* pos 132: state 50 */
|
||||
0x85, 0x00 /* terminal marker */,
|
||||
/* pos 134: state 51 */
|
||||
0xF0 /* 'p' */, 0x01 /* to pos 136 state 52 */,
|
||||
/* pos 136: state 52 */
|
||||
0xE7 /* 'g' */, 0x01 /* to pos 138 state 53 */,
|
||||
/* pos 138: state 53 */
|
||||
0xF2 /* 'r' */, 0x01 /* to pos 140 state 54 */,
|
||||
/* pos 140: state 54 */
|
||||
0xE1 /* 'a' */, 0x01 /* to pos 142 state 55 */,
|
||||
/* pos 142: state 55 */
|
||||
0xE4 /* 'd' */, 0x01 /* to pos 144 state 56 */,
|
||||
/* pos 144: state 56 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 146 state 57 */,
|
||||
/* pos 146: state 57 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 148 state 58 */,
|
||||
/* pos 148: state 58 */
|
||||
0x86, 0x00 /* terminal marker */,
|
||||
/* pos 150: state 59 */
|
||||
0xF2 /* 'r' */, 0x01 /* to pos 152 state 60 */,
|
||||
/* pos 152: state 60 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 154 state 61 */,
|
||||
/* pos 154: state 61 */
|
||||
0xE7 /* 'g' */, 0x01 /* to pos 156 state 62 */,
|
||||
/* pos 156: state 62 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 158 state 63 */,
|
||||
/* pos 158: state 63 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 160 state 64 */,
|
||||
/* pos 160: state 64 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 162 state 65 */,
|
||||
/* pos 162: state 65 */
|
||||
0x87, 0x00 /* terminal marker */,
|
||||
/* pos 164: state 66 */
|
||||
0xF2 /* 'r' */, 0x01 /* to pos 166 state 67 */,
|
||||
/* pos 166: state 67 */
|
||||
0xE1 /* 'a' */, 0x01 /* to pos 168 state 68 */,
|
||||
/* pos 168: state 68 */
|
||||
0xE6 /* 'f' */, 0x01 /* to pos 170 state 69 */,
|
||||
/* pos 170: state 69 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 172 state 70 */,
|
||||
/* pos 172: state 70 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 174 state 71 */,
|
||||
/* pos 174: state 71 */
|
||||
0x88, 0x00 /* terminal marker */,
|
||||
/* pos 176: state 72 */
|
||||
0x8A /* '.' */, 0x01 /* to pos 178 state 73 */,
|
||||
/* pos 178: state 73 */
|
||||
0x89, 0x00 /* terminal marker */,
|
||||
/* pos 180: state 74 */
|
||||
0x8A, 0x00 /* terminal marker */,
|
||||
/* pos 182: state 75 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 184 state 76 */,
|
||||
/* pos 184: state 76 */
|
||||
0xF2 /* 'r' */, 0x01 /* to pos 186 state 77 */,
|
||||
/* pos 186: state 77 */
|
||||
0xF3 /* 's' */, 0x01 /* to pos 188 state 78 */,
|
||||
/* pos 188: state 78 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 190 state 79 */,
|
||||
/* pos 190: state 79 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 192 state 80 */,
|
||||
/* pos 192: state 80 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 194 state 81 */,
|
||||
/* pos 194: state 81 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 196 state 82 */,
|
||||
/* pos 196: state 82 */
|
||||
0x8B, 0x00 /* terminal marker */,
|
||||
/* pos 198: state 83 */
|
||||
0xF2 /* 'r' */, 0x01 /* to pos 200 state 84 */,
|
||||
/* pos 200: state 84 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 202 state 85 */,
|
||||
/* pos 202: state 85 */
|
||||
0xE7 /* 'g' */, 0x01 /* to pos 204 state 86 */,
|
||||
/* pos 204: state 86 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 206 state 87 */,
|
||||
/* pos 206: state 87 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 208 state 88 */,
|
||||
/* pos 208: state 88 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 210 state 89 */,
|
||||
/* pos 210: state 89 */
|
||||
0x8C, 0x00 /* terminal marker */,
|
||||
/* pos 212: state 90 */
|
||||
0xF8 /* 'x' */, 0x01 /* to pos 214 state 91 */,
|
||||
/* pos 214: state 91 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 216 state 92 */,
|
||||
/* pos 216: state 92 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 218 state 93 */,
|
||||
/* pos 218: state 93 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 220 state 94 */,
|
||||
/* pos 220: state 94 */
|
||||
0xF3 /* 's' */, 0x01 /* to pos 222 state 95 */,
|
||||
/* pos 222: state 95 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 224 state 96 */,
|
||||
/* pos 224: state 96 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 226 state 97 */,
|
||||
/* pos 226: state 97 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 228 state 98 */,
|
||||
/* pos 228: state 98 */
|
||||
0xF3 /* 's' */, 0x01 /* to pos 230 state 99 */,
|
||||
/* pos 230: state 99 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 232 state 100 */,
|
||||
/* pos 232: state 100 */
|
||||
0x8D, 0x00 /* terminal marker */,
|
||||
/* pos 234: state 101 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 236 state 102 */,
|
||||
/* pos 236: state 102 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 238 state 103 */,
|
||||
/* pos 238: state 103 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 240 state 104 */,
|
||||
/* pos 240: state 104 */
|
||||
0xF0 /* 'p' */, 0x01 /* to pos 242 state 105 */,
|
||||
/* pos 242: state 105 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 244 state 106 */,
|
||||
/* pos 244: state 106 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 246 state 107 */,
|
||||
/* pos 246: state 107 */
|
||||
0x8E, 0x00 /* terminal marker */,
|
||||
/* pos 248: state 108 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 250 state 109 */,
|
||||
/* pos 250: state 109 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 252 state 110 */,
|
||||
/* pos 252: state 110 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 254 state 111 */,
|
||||
/* pos 254: state 111 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 256 state 112 */,
|
||||
/* pos 256: state 112 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 258 state 113 */,
|
||||
/* pos 258: state 113 */
|
||||
0x8F, 0x00 /* terminal marker */,
|
||||
/* pos 260: state 114 */
|
||||
0xD4 /* 'T' */, 0x01 /* to pos 262 state 115 */,
|
||||
/* pos 262: state 115 */
|
||||
0xD0 /* 'P' */, 0x01 /* to pos 264 state 116 */,
|
||||
/* pos 264: state 116 */
|
||||
0xAF /* '/' */, 0x01 /* to pos 266 state 117 */,
|
||||
/* pos 266: state 117 */
|
||||
0xB1 /* '1' */, 0x01 /* to pos 268 state 118 */,
|
||||
/* pos 268: state 118 */
|
||||
0xAE /* '.' */, 0x01 /* to pos 270 state 119 */,
|
||||
/* pos 270: state 119 */
|
||||
0xB1 /* '1' */, 0x01 /* to pos 272 state 120 */,
|
||||
/* pos 272: state 120 */
|
||||
0xA0 /* ' ' */, 0x01 /* to pos 274 state 121 */,
|
||||
/* pos 274: state 121 */
|
||||
0x90, 0x00 /* terminal marker */,
|
||||
/* total size 276 bytes */
|
||||
/* pos 0: state 0 */
|
||||
0x47 /* 'G' */, 0x07 /* to pos 14 state 1 */,
|
||||
0x48 /* 'H' */, 0x0A /* to pos 22 state 5 */,
|
||||
0x43 /* 'C' */, 0x0F /* to pos 34 state 10 */,
|
||||
0x53 /* 'S' */, 0x19 /* to pos 56 state 21 */,
|
||||
0x55 /* 'U' */, 0x3F /* to pos 134 state 51 */,
|
||||
0x4F /* 'O' */, 0x46 /* to pos 150 state 59 */,
|
||||
0x8D /* '.' */, 0x52 /* to pos 176 state 72 */,
|
||||
/* pos 14: state 1 */
|
||||
0xC5 /* 'E' */, 0x01 /* to pos 16 state 2 */,
|
||||
/* pos 16: state 2 */
|
||||
0xD4 /* 'T' */, 0x01 /* to pos 18 state 3 */,
|
||||
/* pos 18: state 3 */
|
||||
0xA0 /* ' ' */, 0x01 /* to pos 20 state 4 */,
|
||||
/* pos 20: state 4 */
|
||||
0x80, 0x00 /* terminal marker */,
|
||||
/* pos 22: state 5 */
|
||||
0x6F /* 'o' */, 0x02 /* to pos 26 state 6 */,
|
||||
0xD4 /* 'T' */, 0x76 /* to pos 260 state 114 */,
|
||||
/* pos 26: state 6 */
|
||||
0xF3 /* 's' */, 0x01 /* to pos 28 state 7 */,
|
||||
/* pos 28: state 7 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 30 state 8 */,
|
||||
/* pos 30: state 8 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 32 state 9 */,
|
||||
/* pos 32: state 9 */
|
||||
0x81, 0x00 /* terminal marker */,
|
||||
/* pos 34: state 10 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 36 state 11 */,
|
||||
/* pos 36: state 11 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 38 state 12 */,
|
||||
/* pos 38: state 12 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 40 state 13 */,
|
||||
/* pos 40: state 13 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 42 state 14 */,
|
||||
/* pos 42: state 14 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 44 state 15 */,
|
||||
/* pos 44: state 15 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 46 state 16 */,
|
||||
/* pos 46: state 16 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 48 state 17 */,
|
||||
/* pos 48: state 17 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 50 state 18 */,
|
||||
/* pos 50: state 18 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 52 state 19 */,
|
||||
/* pos 52: state 19 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 54 state 20 */,
|
||||
/* pos 54: state 20 */
|
||||
0x82, 0x00 /* terminal marker */,
|
||||
/* pos 56: state 21 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 58 state 22 */,
|
||||
/* pos 58: state 22 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 60 state 23 */,
|
||||
/* pos 60: state 23 */
|
||||
0xAD /* '-' */, 0x01 /* to pos 62 state 24 */,
|
||||
/* pos 62: state 24 */
|
||||
0xD7 /* 'W' */, 0x01 /* to pos 64 state 25 */,
|
||||
/* pos 64: state 25 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 66 state 26 */,
|
||||
/* pos 66: state 26 */
|
||||
0xE2 /* 'b' */, 0x01 /* to pos 68 state 27 */,
|
||||
/* pos 68: state 27 */
|
||||
0xD3 /* 'S' */, 0x01 /* to pos 70 state 28 */,
|
||||
/* pos 70: state 28 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 72 state 29 */,
|
||||
/* pos 72: state 29 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 74 state 30 */,
|
||||
/* pos 74: state 30 */
|
||||
0xEB /* 'k' */, 0x01 /* to pos 76 state 31 */,
|
||||
/* pos 76: state 31 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 78 state 32 */,
|
||||
/* pos 78: state 32 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 80 state 33 */,
|
||||
/* pos 80: state 33 */
|
||||
0xAD /* '-' */, 0x01 /* to pos 82 state 34 */,
|
||||
/* pos 82: state 34 */
|
||||
0x4B /* 'K' */, 0x08 /* to pos 98 state 35 */,
|
||||
0x50 /* 'P' */, 0x10 /* to pos 116 state 42 */,
|
||||
0x44 /* 'D' */, 0x27 /* to pos 164 state 66 */,
|
||||
0x56 /* 'V' */, 0x2F /* to pos 182 state 75 */,
|
||||
0x4F /* 'O' */, 0x36 /* to pos 198 state 83 */,
|
||||
0x45 /* 'E' */, 0x3C /* to pos 212 state 90 */,
|
||||
0x41 /* 'A' */, 0x46 /* to pos 234 state 101 */,
|
||||
0xCE /* 'N' */, 0x4C /* to pos 248 state 108 */,
|
||||
/* pos 98: state 35 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 100 state 36 */,
|
||||
/* pos 100: state 36 */
|
||||
0xF9 /* 'y' */, 0x01 /* to pos 102 state 37 */,
|
||||
/* pos 102: state 37 */
|
||||
0x31 /* '1' */, 0x03 /* to pos 108 state 38 */,
|
||||
0x32 /* '2' */, 0x04 /* to pos 112 state 40 */,
|
||||
0xBA /* ':' */, 0x25 /* to pos 180 state 74 */,
|
||||
/* pos 108: state 38 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 110 state 39 */,
|
||||
/* pos 110: state 39 */
|
||||
0x83, 0x00 /* terminal marker */,
|
||||
/* pos 112: state 40 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 114 state 41 */,
|
||||
/* pos 114: state 41 */
|
||||
0x84, 0x00 /* terminal marker */,
|
||||
/* pos 116: state 42 */
|
||||
0xF2 /* 'r' */, 0x01 /* to pos 118 state 43 */,
|
||||
/* pos 118: state 43 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 120 state 44 */,
|
||||
/* pos 120: state 44 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 122 state 45 */,
|
||||
/* pos 122: state 45 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 124 state 46 */,
|
||||
/* pos 124: state 46 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 126 state 47 */,
|
||||
/* pos 126: state 47 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 128 state 48 */,
|
||||
/* pos 128: state 48 */
|
||||
0xEC /* 'l' */, 0x01 /* to pos 130 state 49 */,
|
||||
/* pos 130: state 49 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 132 state 50 */,
|
||||
/* pos 132: state 50 */
|
||||
0x85, 0x00 /* terminal marker */,
|
||||
/* pos 134: state 51 */
|
||||
0xF0 /* 'p' */, 0x01 /* to pos 136 state 52 */,
|
||||
/* pos 136: state 52 */
|
||||
0xE7 /* 'g' */, 0x01 /* to pos 138 state 53 */,
|
||||
/* pos 138: state 53 */
|
||||
0xF2 /* 'r' */, 0x01 /* to pos 140 state 54 */,
|
||||
/* pos 140: state 54 */
|
||||
0xE1 /* 'a' */, 0x01 /* to pos 142 state 55 */,
|
||||
/* pos 142: state 55 */
|
||||
0xE4 /* 'd' */, 0x01 /* to pos 144 state 56 */,
|
||||
/* pos 144: state 56 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 146 state 57 */,
|
||||
/* pos 146: state 57 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 148 state 58 */,
|
||||
/* pos 148: state 58 */
|
||||
0x86, 0x00 /* terminal marker */,
|
||||
/* pos 150: state 59 */
|
||||
0xF2 /* 'r' */, 0x01 /* to pos 152 state 60 */,
|
||||
/* pos 152: state 60 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 154 state 61 */,
|
||||
/* pos 154: state 61 */
|
||||
0xE7 /* 'g' */, 0x01 /* to pos 156 state 62 */,
|
||||
/* pos 156: state 62 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 158 state 63 */,
|
||||
/* pos 158: state 63 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 160 state 64 */,
|
||||
/* pos 160: state 64 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 162 state 65 */,
|
||||
/* pos 162: state 65 */
|
||||
0x87, 0x00 /* terminal marker */,
|
||||
/* pos 164: state 66 */
|
||||
0xF2 /* 'r' */, 0x01 /* to pos 166 state 67 */,
|
||||
/* pos 166: state 67 */
|
||||
0xE1 /* 'a' */, 0x01 /* to pos 168 state 68 */,
|
||||
/* pos 168: state 68 */
|
||||
0xE6 /* 'f' */, 0x01 /* to pos 170 state 69 */,
|
||||
/* pos 170: state 69 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 172 state 70 */,
|
||||
/* pos 172: state 70 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 174 state 71 */,
|
||||
/* pos 174: state 71 */
|
||||
0x88, 0x00 /* terminal marker */,
|
||||
/* pos 176: state 72 */
|
||||
0x8A /* '.' */, 0x01 /* to pos 178 state 73 */,
|
||||
/* pos 178: state 73 */
|
||||
0x89, 0x00 /* terminal marker */,
|
||||
/* pos 180: state 74 */
|
||||
0x8A, 0x00 /* terminal marker */,
|
||||
/* pos 182: state 75 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 184 state 76 */,
|
||||
/* pos 184: state 76 */
|
||||
0xF2 /* 'r' */, 0x01 /* to pos 186 state 77 */,
|
||||
/* pos 186: state 77 */
|
||||
0xF3 /* 's' */, 0x01 /* to pos 188 state 78 */,
|
||||
/* pos 188: state 78 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 190 state 79 */,
|
||||
/* pos 190: state 79 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 192 state 80 */,
|
||||
/* pos 192: state 80 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 194 state 81 */,
|
||||
/* pos 194: state 81 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 196 state 82 */,
|
||||
/* pos 196: state 82 */
|
||||
0x8B, 0x00 /* terminal marker */,
|
||||
/* pos 198: state 83 */
|
||||
0xF2 /* 'r' */, 0x01 /* to pos 200 state 84 */,
|
||||
/* pos 200: state 84 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 202 state 85 */,
|
||||
/* pos 202: state 85 */
|
||||
0xE7 /* 'g' */, 0x01 /* to pos 204 state 86 */,
|
||||
/* pos 204: state 86 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 206 state 87 */,
|
||||
/* pos 206: state 87 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 208 state 88 */,
|
||||
/* pos 208: state 88 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 210 state 89 */,
|
||||
/* pos 210: state 89 */
|
||||
0x8C, 0x00 /* terminal marker */,
|
||||
/* pos 212: state 90 */
|
||||
0xF8 /* 'x' */, 0x01 /* to pos 214 state 91 */,
|
||||
/* pos 214: state 91 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 216 state 92 */,
|
||||
/* pos 216: state 92 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 218 state 93 */,
|
||||
/* pos 218: state 93 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 220 state 94 */,
|
||||
/* pos 220: state 94 */
|
||||
0xF3 /* 's' */, 0x01 /* to pos 222 state 95 */,
|
||||
/* pos 222: state 95 */
|
||||
0xE9 /* 'i' */, 0x01 /* to pos 224 state 96 */,
|
||||
/* pos 224: state 96 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 226 state 97 */,
|
||||
/* pos 226: state 97 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 228 state 98 */,
|
||||
/* pos 228: state 98 */
|
||||
0xF3 /* 's' */, 0x01 /* to pos 230 state 99 */,
|
||||
/* pos 230: state 99 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 232 state 100 */,
|
||||
/* pos 232: state 100 */
|
||||
0x8D, 0x00 /* terminal marker */,
|
||||
/* pos 234: state 101 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 236 state 102 */,
|
||||
/* pos 236: state 102 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 238 state 103 */,
|
||||
/* pos 238: state 103 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 240 state 104 */,
|
||||
/* pos 240: state 104 */
|
||||
0xF0 /* 'p' */, 0x01 /* to pos 242 state 105 */,
|
||||
/* pos 242: state 105 */
|
||||
0xF4 /* 't' */, 0x01 /* to pos 244 state 106 */,
|
||||
/* pos 244: state 106 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 246 state 107 */,
|
||||
/* pos 246: state 107 */
|
||||
0x8E, 0x00 /* terminal marker */,
|
||||
/* pos 248: state 108 */
|
||||
0xEF /* 'o' */, 0x01 /* to pos 250 state 109 */,
|
||||
/* pos 250: state 109 */
|
||||
0xEE /* 'n' */, 0x01 /* to pos 252 state 110 */,
|
||||
/* pos 252: state 110 */
|
||||
0xE3 /* 'c' */, 0x01 /* to pos 254 state 111 */,
|
||||
/* pos 254: state 111 */
|
||||
0xE5 /* 'e' */, 0x01 /* to pos 256 state 112 */,
|
||||
/* pos 256: state 112 */
|
||||
0xBA /* ':' */, 0x01 /* to pos 258 state 113 */,
|
||||
/* pos 258: state 113 */
|
||||
0x8F, 0x00 /* terminal marker */,
|
||||
/* pos 260: state 114 */
|
||||
0xD4 /* 'T' */, 0x01 /* to pos 262 state 115 */,
|
||||
/* pos 262: state 115 */
|
||||
0xD0 /* 'P' */, 0x01 /* to pos 264 state 116 */,
|
||||
/* pos 264: state 116 */
|
||||
0xAF /* '/' */, 0x01 /* to pos 266 state 117 */,
|
||||
/* pos 266: state 117 */
|
||||
0xB1 /* '1' */, 0x01 /* to pos 268 state 118 */,
|
||||
/* pos 268: state 118 */
|
||||
0xAE /* '.' */, 0x01 /* to pos 270 state 119 */,
|
||||
/* pos 270: state 119 */
|
||||
0xB1 /* '1' */, 0x01 /* to pos 272 state 120 */,
|
||||
/* pos 272: state 120 */
|
||||
0xA0 /* ' ' */, 0x01 /* to pos 274 state 121 */,
|
||||
/* pos 274: state 121 */
|
||||
0x90, 0x00 /* terminal marker */,
|
||||
/* total size 276 bytes */
|
||||
};
|
||||
|
||||
int lextable_decode(int pos, char c)
|
||||
{
|
||||
while (pos >= 0) {
|
||||
if (lextable[pos + 1] == 0) // terminal marker
|
||||
if (lextable[pos + 1] == 0) /* terminal marker */
|
||||
return pos;
|
||||
|
||||
if ((lextable[pos] & 0x7f) == c)
|
||||
|
@ -309,12 +309,12 @@ int lextable_decode(int pos, char c)
|
|||
|
||||
int lws_allocate_header_table(struct libwebsocket *wsi)
|
||||
{
|
||||
wsi->u.hdr.ah = malloc(sizeof *wsi->u.hdr.ah);
|
||||
wsi->u.hdr.ah = malloc(sizeof(*wsi->u.hdr.ah));
|
||||
if (wsi->u.hdr.ah == NULL) {
|
||||
lwsl_err("Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
memset(wsi->u.hdr.ah->frag_index, 0, sizeof wsi->u.hdr.ah->frag_index);
|
||||
memset(wsi->u.hdr.ah->frag_index, 0, sizeof(wsi->u.hdr.ah->frag_index));
|
||||
wsi->u.hdr.ah->next_frag_index = 0;
|
||||
wsi->u.hdr.ah->pos = 0;
|
||||
|
||||
|
@ -338,7 +338,8 @@ int lws_hdr_total_length(struct libwebsocket *wsi, enum lws_token_indexes h)
|
|||
return len;
|
||||
}
|
||||
|
||||
int lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len, enum lws_token_indexes h)
|
||||
int lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len,
|
||||
enum lws_token_indexes h)
|
||||
{
|
||||
int toklen = lws_hdr_total_length(wsi, h);
|
||||
int n;
|
||||
|
@ -351,7 +352,8 @@ int lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len, enum lws_token_i
|
|||
return 0;
|
||||
|
||||
do {
|
||||
strcpy(dest, &wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset]);
|
||||
strcpy(dest,
|
||||
&wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset]);
|
||||
dest += wsi->u.hdr.ah->frags[n].len;
|
||||
n = wsi->u.hdr.ah->frags[n].next_frag_index;
|
||||
} while (n);
|
||||
|
@ -359,7 +361,7 @@ int lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len, enum lws_token_i
|
|||
return toklen;
|
||||
}
|
||||
|
||||
char * lws_hdr_simple_ptr(struct libwebsocket *wsi, enum lws_token_indexes h)
|
||||
char *lws_hdr_simple_ptr(struct libwebsocket *wsi, enum lws_token_indexes h)
|
||||
{
|
||||
int n;
|
||||
|
||||
|
@ -370,28 +372,33 @@ char * lws_hdr_simple_ptr(struct libwebsocket *wsi, enum lws_token_indexes h)
|
|||
return &wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset];
|
||||
}
|
||||
|
||||
int lws_hdr_simple_create(struct libwebsocket *wsi, enum lws_token_indexes h, const char *s)
|
||||
int lws_hdr_simple_create(struct libwebsocket *wsi,
|
||||
enum lws_token_indexes h, const char *s)
|
||||
{
|
||||
wsi->u.hdr.ah->next_frag_index++;
|
||||
if (wsi->u.hdr.ah->next_frag_index == sizeof(wsi->u.hdr.ah->frags) / sizeof(wsi->u.hdr.ah->frags[0])) {
|
||||
lwsl_warn("More header fragments than we can deal with, dropping\n");
|
||||
if (wsi->u.hdr.ah->next_frag_index ==
|
||||
sizeof(wsi->u.hdr.ah->frags) / sizeof(wsi->u.hdr.ah->frags[0])) {
|
||||
lwsl_warn("More hdr frags than we can deal with, dropping\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsi->u.hdr.ah->frag_index[h] = wsi->u.hdr.ah->next_frag_index;
|
||||
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].offset = wsi->u.hdr.ah->pos;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].offset =
|
||||
wsi->u.hdr.ah->pos;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len = 0;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].next_frag_index = 0;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].next_frag_index =
|
||||
0;
|
||||
|
||||
do {
|
||||
if (wsi->u.hdr.ah->pos == sizeof wsi->u.hdr.ah->data) {
|
||||
if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
|
||||
lwsl_err("Ran out of header data space\n");
|
||||
return -1;
|
||||
}
|
||||
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = *s;
|
||||
if (*s)
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len++;
|
||||
wsi->u.hdr.ah->frags[
|
||||
wsi->u.hdr.ah->next_frag_index].len++;
|
||||
} while (*s++);
|
||||
|
||||
return 0;
|
||||
|
@ -420,11 +427,12 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
|||
case WSI_TOKEN_EXTENSIONS:
|
||||
case WSI_TOKEN_HTTP:
|
||||
|
||||
lwsl_parser("WSI_TOKEN_(%d) '%c'\n", wsi->u.hdr.parser_state, c);
|
||||
lwsl_parser("WSI_TOK_(%d) '%c'\n", wsi->u.hdr.parser_state, c);
|
||||
|
||||
/* collect into malloc'd buffers */
|
||||
/* optional initial space swallow */
|
||||
if (!wsi->u.hdr.ah->frags[wsi->u.hdr.ah->frag_index[wsi->u.hdr.parser_state]].len && c == ' ')
|
||||
if (!wsi->u.hdr.ah->frags[wsi->u.hdr.ah->frag_index[
|
||||
wsi->u.hdr.parser_state]].len && c == ' ')
|
||||
break;
|
||||
|
||||
/* special case space terminator for get-uri */
|
||||
|
@ -434,19 +442,21 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
|||
}
|
||||
|
||||
/* bail at EOL */
|
||||
if (wsi->u.hdr.parser_state != WSI_TOKEN_CHALLENGE && c == '\x0d') {
|
||||
if (wsi->u.hdr.parser_state != WSI_TOKEN_CHALLENGE &&
|
||||
c == '\x0d') {
|
||||
c = '\0';
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
|
||||
lwsl_parser("*\n");
|
||||
}
|
||||
|
||||
if (wsi->u.hdr.ah->pos == sizeof wsi->u.hdr.ah->data) {
|
||||
if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
|
||||
lwsl_warn("excessive header content\n");
|
||||
return -1;
|
||||
}
|
||||
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = c;
|
||||
if (c)
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len++;
|
||||
wsi->u.hdr.ah->frags[
|
||||
wsi->u.hdr.ah->next_frag_index].len++;
|
||||
|
||||
/* per-protocol end of headers management */
|
||||
|
||||
|
@ -458,7 +468,8 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
|||
case WSI_TOKEN_NAME_PART:
|
||||
lwsl_parser("WSI_TOKEN_NAME_PART '%c'\n", c);
|
||||
|
||||
if (wsi->u.hdr.name_buffer_pos == sizeof(wsi->u.hdr.name_buffer) - 1) {
|
||||
if (wsi->u.hdr.name_buffer_pos ==
|
||||
sizeof(wsi->u.hdr.name_buffer) - 1) {
|
||||
/* name bigger than we can handle, skip until next */
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
|
||||
break;
|
||||
|
@ -466,18 +477,23 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
|||
wsi->u.hdr.name_buffer[wsi->u.hdr.name_buffer_pos++] = c;
|
||||
wsi->u.hdr.name_buffer[wsi->u.hdr.name_buffer_pos] = '\0';
|
||||
|
||||
wsi->u.hdr.lextable_pos = lextable_decode(wsi->u.hdr.lextable_pos, c);
|
||||
wsi->u.hdr.lextable_pos =
|
||||
lextable_decode(wsi->u.hdr.lextable_pos, c);
|
||||
|
||||
if (wsi->u.hdr.lextable_pos < 0) {
|
||||
/* this is not a header we know about */
|
||||
if (wsi->u.hdr.ah->frag_index[WSI_TOKEN_GET_URI]) {
|
||||
/* altready had the method, no idea what this crap is, ignore */
|
||||
/*
|
||||
* altready had the method, no idea what
|
||||
* this crap is, ignore
|
||||
*/
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
|
||||
break;
|
||||
}
|
||||
/* hm it's an unknown http method in fact */
|
||||
if (c == ' ') {
|
||||
lwsl_info("Unknown method %s\n", wsi->u.hdr.name_buffer);
|
||||
lwsl_info("Unknown method %s\n",
|
||||
wsi->u.hdr.name_buffer);
|
||||
/* treat it as GET */
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_GET_URI;
|
||||
goto start_fragment;
|
||||
|
@ -509,14 +525,18 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
|||
|
||||
start_fragment:
|
||||
wsi->u.hdr.ah->next_frag_index++;
|
||||
if (wsi->u.hdr.ah->next_frag_index == sizeof(wsi->u.hdr.ah->frags) / sizeof(wsi->u.hdr.ah->frags[0])) {
|
||||
lwsl_warn("More header fragments than we can deal with, dropping\n");
|
||||
if (wsi->u.hdr.ah->next_frag_index ==
|
||||
sizeof(wsi->u.hdr.ah->frags) /
|
||||
sizeof(wsi->u.hdr.ah->frags[0])) {
|
||||
lwsl_warn("More hdr frags than we can deal with\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].offset = wsi->u.hdr.ah->pos;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].offset =
|
||||
wsi->u.hdr.ah->pos;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len = 0;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].next_frag_index = 0;
|
||||
wsi->u.hdr.ah->frags[
|
||||
wsi->u.hdr.ah->next_frag_index].next_frag_index = 0;
|
||||
|
||||
n = wsi->u.hdr.ah->frag_index[wsi->u.hdr.parser_state];
|
||||
if (!n) { /* first fragment */
|
||||
|
@ -528,13 +548,14 @@ start_fragment:
|
|||
wsi->u.hdr.ah->frags[n].next_frag_index =
|
||||
wsi->u.hdr.ah->next_frag_index;
|
||||
|
||||
if (wsi->u.hdr.ah->pos == sizeof wsi->u.hdr.ah->data) {
|
||||
if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
|
||||
lwsl_warn("excessive header content\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = ' ';
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len++;
|
||||
wsi->u.hdr.ah->frags[
|
||||
wsi->u.hdr.ah->next_frag_index].len++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -570,14 +591,11 @@ start_fragment:
|
|||
set_parsing_complete:
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_VERSION)) {
|
||||
// lwsl_info("Missing Version Header\n");
|
||||
// return 1;
|
||||
} else
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION))
|
||||
wsi->ietf_spec_revision =
|
||||
atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION));
|
||||
|
||||
lwsl_parser("v%02d headers completed\n", wsi->ietf_spec_revision);
|
||||
lwsl_parser("v%02d hdrs completed\n", wsi->ietf_spec_revision);
|
||||
}
|
||||
wsi->u.hdr.parser_state = WSI_PARSING_COMPLETE;
|
||||
|
||||
|
@ -627,8 +645,8 @@ libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
|||
goto handle_first;
|
||||
|
||||
default:
|
||||
lwsl_warn("libwebsocket_rx_sm doesn't know "
|
||||
"about spec version %d\n", wsi->ietf_spec_revision);
|
||||
lwsl_warn("lws_rx_sm: unknown spec version %d\n",
|
||||
wsi->ietf_spec_revision);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -715,7 +733,8 @@ handle_first:
|
|||
switch (wsi->u.ws.opcode) {
|
||||
case LWS_WS_OPCODE_07__TEXT_FRAME:
|
||||
case LWS_WS_OPCODE_07__BINARY_FRAME:
|
||||
wsi->u.ws.frame_is_binary = wsi->u.ws.opcode == LWS_WS_OPCODE_07__BINARY_FRAME;
|
||||
wsi->u.ws.frame_is_binary =
|
||||
wsi->u.ws.opcode == LWS_WS_OPCODE_07__BINARY_FRAME;
|
||||
break;
|
||||
}
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
|
||||
|
@ -869,13 +888,15 @@ handle_first:
|
|||
else
|
||||
wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
|
||||
(wsi->u.ws.rx_user_buffer_head++)] =
|
||||
c ^ wsi->u.ws.frame_masking_nonce_04[(wsi->u.ws.frame_mask_index++) & 3];
|
||||
c ^ wsi->u.ws.frame_masking_nonce_04[
|
||||
(wsi->u.ws.frame_mask_index++) & 3];
|
||||
|
||||
if (--wsi->u.ws.rx_packet_length == 0) {
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
if (wsi->u.ws.rx_user_buffer_head != wsi->protocol->rx_buffer_size)
|
||||
if (wsi->u.ws.rx_user_buffer_head !=
|
||||
wsi->protocol->rx_buffer_size)
|
||||
break;
|
||||
spill:
|
||||
/*
|
||||
|
@ -899,8 +920,10 @@ spill:
|
|||
lwsl_parser("server sees client close packet\n");
|
||||
/* parrot the close packet payload back */
|
||||
n = libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head, LWS_WRITE_CLOSE);
|
||||
&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head,
|
||||
LWS_WRITE_CLOSE);
|
||||
if (n)
|
||||
lwsl_info("write of close ack failed %d\n", n);
|
||||
wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
|
||||
|
@ -908,11 +931,15 @@ spill:
|
|||
return -1;
|
||||
|
||||
case LWS_WS_OPCODE_07__PING:
|
||||
lwsl_info("received %d byte ping, sending pong\n", wsi->u.ws.rx_user_buffer_head);
|
||||
lwsl_hexdump(&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], wsi->u.ws.rx_user_buffer_head);
|
||||
lwsl_info("received %d byte ping, sending pong\n",
|
||||
wsi->u.ws.rx_user_buffer_head);
|
||||
lwsl_hexdump(&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head);
|
||||
/* parrot the ping packet payload back as a pong */
|
||||
n = libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], wsi->u.ws.rx_user_buffer_head, LWS_WRITE_PONG);
|
||||
&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head, LWS_WRITE_PONG);
|
||||
/* ... then just drop it */
|
||||
wsi->u.ws.rx_user_buffer_head = 0;
|
||||
return 0;
|
||||
|
@ -929,7 +956,8 @@ spill:
|
|||
|
||||
default:
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
lwsl_parser("passing opcode %x up to exts\n", wsi->u.ws.opcode);
|
||||
lwsl_parser("passing opc %x up to exts\n",
|
||||
wsi->u.ws.opcode);
|
||||
|
||||
/*
|
||||
* It's something special we can't understand here.
|
||||
|
@ -955,8 +983,8 @@ spill:
|
|||
|
||||
if (!handled)
|
||||
#endif
|
||||
lwsl_ext("Unhandled extended opcode "
|
||||
"0x%x - ignoring frame\n", wsi->u.ws.opcode);
|
||||
lwsl_ext("ext opc opcode 0x%x unknown\n",
|
||||
wsi->u.ws.opcode);
|
||||
|
||||
wsi->u.ws.rx_user_buffer_head = 0;
|
||||
return 0;
|
||||
|
@ -981,8 +1009,8 @@ spill:
|
|||
&eff_buf, 0);
|
||||
if (m < 0) {
|
||||
lwsl_ext(
|
||||
"Extension '%s' failed to handle payload!\n",
|
||||
wsi->active_extensions[n]->name);
|
||||
"Extension '%s' failed to handle payload!\n",
|
||||
wsi->active_extensions[n]->name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -991,12 +1019,13 @@ spill:
|
|||
eff_buf.token[eff_buf.token_len] = '\0';
|
||||
|
||||
if (wsi->protocol->callback)
|
||||
ret = user_callback_handle_rxflow(wsi->protocol->callback,
|
||||
wsi->protocol->owning_server,
|
||||
wsi, LWS_CALLBACK_RECEIVE,
|
||||
wsi->user_space,
|
||||
eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
ret = user_callback_handle_rxflow(
|
||||
wsi->protocol->callback,
|
||||
wsi->protocol->owning_server,
|
||||
wsi, LWS_CALLBACK_RECEIVE,
|
||||
wsi->user_space,
|
||||
eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
else
|
||||
lwsl_err("No callback on payload spill!\n");
|
||||
}
|
||||
|
@ -1009,8 +1038,7 @@ spill:
|
|||
|
||||
illegal_ctl_length:
|
||||
|
||||
lwsl_warn("Control frame asking for "
|
||||
"extended length is illegal\n");
|
||||
lwsl_warn("Control frame with xtended length is illegal\n");
|
||||
/* kill the connection */
|
||||
return -1;
|
||||
}
|
||||
|
@ -1030,13 +1058,14 @@ int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
|
|||
#endif
|
||||
|
||||
if (buf && wsi->u.ws.rxflow_buffer)
|
||||
lwsl_err("!!!! libwebsocket_interpret_incoming_packet: was pending rxflow, data loss\n");
|
||||
lwsl_err("!!!! pending rxflow data loss\n");
|
||||
|
||||
/* let the rx protocol state machine have as much as it needs */
|
||||
|
||||
n = 0;
|
||||
if (!buf) {
|
||||
lwsl_info("dumping stored rxflow buffer len %d pos=%d\n", wsi->u.ws.rxflow_len, wsi->u.ws.rxflow_pos);
|
||||
lwsl_info("dumping stored rxflow buffer len %d pos=%d\n",
|
||||
wsi->u.ws.rxflow_len, wsi->u.ws.rxflow_pos);
|
||||
buf = wsi->u.ws.rxflow_buffer;
|
||||
n = wsi->u.ws.rxflow_pos;
|
||||
len = wsi->u.ws.rxflow_len;
|
||||
|
@ -1045,17 +1074,22 @@ int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
|
|||
}
|
||||
|
||||
while (n < len) {
|
||||
if (!(context->fds[wsi->position_in_fds_table].events & POLLIN)) {
|
||||
if (!(context->fds[wsi->position_in_fds_table].events &
|
||||
POLLIN)) {
|
||||
/* his RX is flowcontrolled */
|
||||
if (!wsi->u.ws.rxflow_buffer) { /* a new rxflow in effect, buffer it and warn caller */
|
||||
lwsl_info("new rxflow input buffer len %d\n", len - n);
|
||||
wsi->u.ws.rxflow_buffer = (unsigned char *)malloc(len - n);
|
||||
if (!wsi->u.ws.rxflow_buffer) {
|
||||
/* a new rxflow, buffer it and warn caller */
|
||||
lwsl_info("new rxflow input buffer len %d\n",
|
||||
len - n);
|
||||
wsi->u.ws.rxflow_buffer =
|
||||
(unsigned char *)malloc(len - n);
|
||||
wsi->u.ws.rxflow_len = len - n;
|
||||
wsi->u.ws.rxflow_pos = 0;
|
||||
memcpy(wsi->u.ws.rxflow_buffer, buf + n, len - n);
|
||||
memcpy(wsi->u.ws.rxflow_buffer,
|
||||
buf + n, len - n);
|
||||
} else {
|
||||
lwsl_info("re-using rxflow input buffer\n");
|
||||
/* rxflow while we were spilling previous rxflow buffer */
|
||||
/* rxflow while we were spilling prev rxflow */
|
||||
wsi->u.ws.rxflow_pos = n;
|
||||
}
|
||||
return 1;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
// System introspection configs.
|
||||
/* System introspection configs */
|
||||
#ifdef CMAKE_BUILD
|
||||
#include "lws_config.h"
|
||||
#else
|
||||
|
@ -43,9 +43,9 @@
|
|||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
#ifdef __MINGW64__
|
||||
#ifdef __MINGW64__
|
||||
#else
|
||||
#ifdef __MINGW32__
|
||||
#ifdef __MINGW32__
|
||||
#elif _MSC_VER > 1000 || defined(_WIN32)
|
||||
#else
|
||||
#include <netdb.h>
|
||||
|
@ -59,9 +59,9 @@
|
|||
#define LWS_NO_DAEMONIZE
|
||||
|
||||
#define compatible_close(fd) closesocket(fd);
|
||||
#ifdef __MINGW64__
|
||||
#else
|
||||
#ifdef __MINGW32__
|
||||
#ifdef __MINGW64__
|
||||
#else
|
||||
#ifdef __MINGW32__
|
||||
#else
|
||||
#include <time.h >
|
||||
#endif
|
||||
|
@ -278,7 +278,7 @@ struct libwebsocket_context {
|
|||
#ifndef LWS_NO_EXTENSIONS
|
||||
struct libwebsocket_extension *extensions;
|
||||
#endif
|
||||
void *user_space;
|
||||
void *user_space;
|
||||
};
|
||||
|
||||
|
||||
|
@ -396,16 +396,21 @@ struct libwebsocket {
|
|||
SSL *ssl;
|
||||
BIO *client_bio;
|
||||
unsigned int use_ssl:2;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef LWS_LATENCY
|
||||
static inline void lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi, const char *action, int ret, int completion) { while (0); }
|
||||
static inline void lws_latency_pre(struct libwebsocket_context *context, struct libwebsocket *wsi) { while (0); }
|
||||
static inline void lws_latency(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, const char *action,
|
||||
int ret, int completion) { while (0); }
|
||||
static inline void lws_latency_pre(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi) { while (0); }
|
||||
#else
|
||||
#define lws_latency_pre(_context, _wsi) lws_latency(_context, _wsi, NULL, 0, 0)
|
||||
extern void
|
||||
lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi, const char *action, int ret, int completion);
|
||||
lws_latency(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, const char *action,
|
||||
int ret, int completion);
|
||||
#endif
|
||||
|
||||
extern int
|
||||
|
@ -425,7 +430,8 @@ extern struct libwebsocket *
|
|||
wsi_from_fd(struct libwebsocket_context *context, int fd);
|
||||
|
||||
extern int
|
||||
insert_wsi_socket_into_fds(struct libwebsocket_context *context, struct libwebsocket *wsi);
|
||||
insert_wsi_socket_into_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
|
||||
extern void
|
||||
libwebsocket_set_timeout(struct libwebsocket *wsi,
|
||||
|
@ -480,7 +486,8 @@ extern int
|
|||
_libwebsocket_rx_flow_control(struct libwebsocket *wsi);
|
||||
|
||||
extern int
|
||||
user_callback_handle_rxflow(callback_function, struct libwebsocket_context * context,
|
||||
user_callback_handle_rxflow(callback_function,
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len);
|
||||
|
@ -495,11 +502,28 @@ extern char *
|
|||
lws_hdr_simple_ptr(struct libwebsocket *wsi, enum lws_token_indexes h);
|
||||
|
||||
extern int
|
||||
lws_hdr_simple_create(struct libwebsocket *wsi, enum lws_token_indexes h, const char *s);
|
||||
lws_hdr_simple_create(struct libwebsocket *wsi,
|
||||
enum lws_token_indexes h, const char *s);
|
||||
|
||||
#ifndef LWS_NO_SERVER
|
||||
extern int handshake_0405(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
#endif
|
||||
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
extern int get_daemonize_pid();
|
||||
#endif
|
||||
|
||||
extern int interface_to_sa(const char *ifname,
|
||||
struct sockaddr_in *addr, size_t addrlen);
|
||||
|
||||
#ifndef LWS_OPENSSL_SUPPORT
|
||||
|
||||
unsigned char *
|
||||
SHA1(const unsigned char *d, size_t n, unsigned char *md);
|
||||
|
||||
#else
|
||||
|
||||
extern int openssl_websocket_private_data_index;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -50,14 +50,14 @@ handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi)
|
|||
goto bail;
|
||||
}
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_KEY) >= MAX_WEBSOCKET_04_KEY_LEN) {
|
||||
lwsl_warn("Client sent handshake key longer "
|
||||
"than max supported %d\n", MAX_WEBSOCKET_04_KEY_LEN);
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_KEY) >=
|
||||
MAX_WEBSOCKET_04_KEY_LEN) {
|
||||
lwsl_warn("Client key too long %d\n", MAX_WEBSOCKET_04_KEY_LEN);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
n = snprintf((char *)context->service_buffer,
|
||||
sizeof context->service_buffer,
|
||||
sizeof(context->service_buffer),
|
||||
"%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_KEY));
|
||||
|
||||
|
@ -65,7 +65,7 @@ handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi)
|
|||
|
||||
accept_len = lws_b64_encode_string((char *)hash, 20,
|
||||
(char *)context->service_buffer,
|
||||
sizeof context->service_buffer);
|
||||
sizeof(context->service_buffer));
|
||||
if (accept_len < 0) {
|
||||
lwsl_warn("Base64 encoded hash too long\n");
|
||||
goto bail;
|
||||
|
@ -110,7 +110,9 @@ handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi)
|
|||
* and go through them
|
||||
*/
|
||||
|
||||
if (lws_hdr_copy(wsi, (char *)context->service_buffer, sizeof context->service_buffer, WSI_TOKEN_EXTENSIONS) < 0)
|
||||
if (lws_hdr_copy(wsi, (char *)context->service_buffer,
|
||||
sizeof(context->service_buffer),
|
||||
WSI_TOKEN_EXTENSIONS) < 0)
|
||||
goto bail;
|
||||
|
||||
c = (char *)context->service_buffer;
|
||||
|
@ -187,7 +189,7 @@ handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi)
|
|||
wsi->count_active_extensions] =
|
||||
malloc(ext->per_session_data_size);
|
||||
if (wsi->active_extensions_user[
|
||||
wsi->count_active_extensions] == NULL) {
|
||||
wsi->count_active_extensions] == NULL) {
|
||||
lwsl_err("Out of mem\n");
|
||||
free(response);
|
||||
goto bail;
|
||||
|
@ -208,7 +210,7 @@ handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi)
|
|||
wsi->count_active_extensions], NULL, 0);
|
||||
|
||||
wsi->count_active_extensions++;
|
||||
lwsl_parser("wsi->count_active_extensions <- %d\n",
|
||||
lwsl_parser("count_active_extensions <- %d\n",
|
||||
wsi->count_active_extensions);
|
||||
|
||||
ext++;
|
||||
|
@ -225,12 +227,13 @@ handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi)
|
|||
#ifndef LWS_NO_EXTENSIONS
|
||||
if (!lws_any_extension_handled(context, wsi,
|
||||
LWS_EXT_CALLBACK_HANDSHAKE_REPLY_TX,
|
||||
response, p - response))
|
||||
#endif
|
||||
response, p - response)) {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
/* okay send the handshake response accepting the connection */
|
||||
|
||||
lwsl_parser("issuing response packet %d len\n", (int)(p - response));
|
||||
lwsl_parser("issuing resp pkt %d len\n", (int)(p - response));
|
||||
#ifdef DEBUG
|
||||
fwrite(response, 1, p - response, stderr);
|
||||
#endif
|
||||
|
|
60
lib/server.c
60
lib/server.c
|
@ -37,7 +37,6 @@
|
|||
#endif
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
extern int openssl_websocket_private_data_index;
|
||||
|
||||
static void
|
||||
libwebsockets_decode_ssl_error(void)
|
||||
|
@ -150,26 +149,32 @@ int lws_server_socket_service(struct libwebsocket_context *context,
|
|||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
if (wsi->ssl)
|
||||
len = SSL_read(wsi->ssl, context->service_buffer, sizeof context->service_buffer);
|
||||
len = SSL_read(wsi->ssl,
|
||||
context->service_buffer,
|
||||
sizeof(context->service_buffer));
|
||||
else
|
||||
#endif
|
||||
len = recv(pollfd->fd, context->service_buffer, sizeof context->service_buffer, 0);
|
||||
len = recv(pollfd->fd,
|
||||
context->service_buffer,
|
||||
sizeof(context->service_buffer), 0);
|
||||
|
||||
if (len < 0) {
|
||||
lwsl_debug("Socket read returned %d\n", len);
|
||||
if (errno != EINTR && errno != EAGAIN)
|
||||
libwebsocket_close_and_free_session(context,
|
||||
wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
libwebsocket_close_and_free_session(
|
||||
context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
}
|
||||
if (!len) {
|
||||
lwsl_info("lws_server_socket_service: closing on zero length read\n");
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
lwsl_info("lws_server_sktt_srv: read 0 len\n");
|
||||
libwebsocket_close_and_free_session(
|
||||
context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = libwebsocket_read(context, wsi, context->service_buffer, len);
|
||||
n = libwebsocket_read(context, wsi,
|
||||
context->service_buffer, len);
|
||||
if (n < 0)
|
||||
/* we closed wsi */
|
||||
return 0;
|
||||
|
@ -182,15 +187,14 @@ int lws_server_socket_service(struct libwebsocket_context *context,
|
|||
|
||||
/* one shot */
|
||||
pollfd->events &= ~POLLOUT;
|
||||
|
||||
|
||||
if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE)
|
||||
break;
|
||||
|
||||
if (libwebsockets_serve_http_file_fragment(context, wsi)) { /* nonzero for completion or error */
|
||||
lwsl_info("lws_server_socket_service: libwebsockets_serve_http_file_fragment says to close\n");
|
||||
/* nonzero for completion or error */
|
||||
if (libwebsockets_serve_http_file_fragment(context, wsi))
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CONNMODE_SERVER_LISTENER:
|
||||
|
@ -206,7 +210,9 @@ int lws_server_socket_service(struct libwebsocket_context *context,
|
|||
lws_latency_pre(context, wsi);
|
||||
accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
|
||||
&clilen);
|
||||
lws_latency(context, wsi, "unencrypted accept LWS_CONNMODE_SERVER_LISTENER", accept_fd, accept_fd >= 0);
|
||||
lws_latency(context, wsi,
|
||||
"unencrypted accept LWS_CONNMODE_SERVER_LISTENER",
|
||||
accept_fd, accept_fd >= 0);
|
||||
if (accept_fd < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
lwsl_debug("accept asks to try again\n");
|
||||
|
@ -284,7 +290,7 @@ int lws_server_socket_service(struct libwebsocket_context *context,
|
|||
lwsl_notice("NULL rbio\n");
|
||||
#endif
|
||||
|
||||
/*
|
||||
/*
|
||||
* we are not accepted yet, but we need to enter ourselves
|
||||
* as a live connection. That way we can retry when more
|
||||
* pieces come if we're not sorted yet
|
||||
|
@ -297,7 +303,7 @@ int lws_server_socket_service(struct libwebsocket_context *context,
|
|||
libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
lwsl_info("inserted SSL acceipt into fds, trying actual SSL_accept\n");
|
||||
lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");
|
||||
|
||||
/* fallthru */
|
||||
|
||||
|
@ -312,14 +318,17 @@ int lws_server_socket_service(struct libwebsocket_context *context,
|
|||
|
||||
lws_latency_pre(context, wsi);
|
||||
n = SSL_accept(wsi->ssl);
|
||||
lws_latency(context, wsi, "SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
|
||||
lws_latency(context, wsi,
|
||||
"SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
|
||||
|
||||
if (n != 1) {
|
||||
m = SSL_get_error(wsi->ssl, n);
|
||||
lwsl_debug("SSL_accept failed %d / %s\n", m, ERR_error_string(m, NULL));
|
||||
lwsl_debug("SSL_accept failed %d / %s\n",
|
||||
m, ERR_error_string(m, NULL));
|
||||
|
||||
if (m == SSL_ERROR_WANT_READ) {
|
||||
context->fds[wsi->position_in_fds_table].events |= POLLIN;
|
||||
context->fds[
|
||||
wsi->position_in_fds_table].events |= POLLIN;
|
||||
|
||||
/* external POLL support via protocol 0 */
|
||||
context->protocols[0].callback(context, wsi,
|
||||
|
@ -329,7 +338,8 @@ int lws_server_socket_service(struct libwebsocket_context *context,
|
|||
break;
|
||||
}
|
||||
if (m == SSL_ERROR_WANT_WRITE) {
|
||||
context->fds[wsi->position_in_fds_table].events |= POLLOUT;
|
||||
context->fds[
|
||||
wsi->position_in_fds_table].events |= POLLOUT;
|
||||
|
||||
/* external POLL support via protocol 0 */
|
||||
context->protocols[0].callback(context, wsi,
|
||||
|
@ -340,7 +350,8 @@ int lws_server_socket_service(struct libwebsocket_context *context,
|
|||
lwsl_debug("SSL_accept failed skt %u: %s\n",
|
||||
pollfd->fd,
|
||||
ERR_error_string(m, NULL));
|
||||
libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -350,10 +361,9 @@ int lws_server_socket_service(struct libwebsocket_context *context,
|
|||
|
||||
wsi->mode = LWS_CONNMODE_HTTP_SERVING;
|
||||
|
||||
lwsl_debug("accepted new SSL conn "
|
||||
"port %u on fd=%d SSL ver %s\n",
|
||||
ntohs(cli_addr.sin_port),
|
||||
SSL_get_version(wsi->ssl));
|
||||
lwsl_debug(
|
||||
"accepted new SSL conn port %u on fd=%d SSL ver %s\n",
|
||||
ntohs(cli_addr.sin_port), SSL_get_version(wsi->ssl));
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -166,7 +166,8 @@ happened.
|
|||
<h3>Description</h3>
|
||||
<blockquote>
|
||||
This function takes a pollfd that has POLLIN or POLLOUT activity and
|
||||
services it according to the state of the associated struct libwebsocket.
|
||||
services it according to the state of the associated
|
||||
struct libwebsocket.
|
||||
<p>
|
||||
The one call deals with all "service" that might happen on a socket
|
||||
including listen accepts, http files as well as websocket protocol.
|
||||
|
@ -188,7 +189,7 @@ context. After calling this, any further use of the context is
|
|||
undefined.
|
||||
</blockquote>
|
||||
<hr>
|
||||
<h2>libwebsocket_context_user - get the user data associated with the whole context</h2>
|
||||
<h2>libwebsocket_context_user - get the user data associated with the context</h2>
|
||||
<i>LWS_EXTERN void *</i>
|
||||
<b>libwebsocket_context_user</b>
|
||||
(<i>struct libwebsocket_context *</i> <b>context</b>)
|
||||
|
@ -398,7 +399,7 @@ this is how you can get a pointer to the active protocol if needed.
|
|||
<i>void</i>
|
||||
<b>lws_set_log_level</b>
|
||||
(<i>int</i> <b>level</b>,
|
||||
<i>void (*</i><b>log_emit_function</b>) <i>(int level, const char *line)</i>)
|
||||
<i>void (*</i><b>log_emit_function</b>) <i>(int level, const char *line)</i>)
|
||||
<h3>Arguments</h3>
|
||||
<dl>
|
||||
<dt><b>level</b>
|
||||
|
|
Loading…
Add table
Reference in a new issue