mirror of
https://libwebsockets.org/repo/libwebsockets
synced 2025-05-03 23:49:53 +00:00
Compare commits
57 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e7fbdac391 | ||
![]() |
bd57dbc241 | ||
![]() |
df9f518e97 | ||
![]() |
5d1947474e | ||
![]() |
7333fcc9cd | ||
![]() |
ff0e0f3c35 | ||
![]() |
b81b24d10e | ||
![]() |
5a34404b1a | ||
![]() |
fce734f279 | ||
![]() |
e5506ade69 | ||
![]() |
c6e9792188 | ||
![]() |
dc65edd519 | ||
![]() |
12e52ae293 | ||
![]() |
c4b1e34a50 | ||
![]() |
a71a62f51b | ||
![]() |
5102a5c8d6 | ||
![]() |
8ad16af9a3 | ||
![]() |
0ee1984c5c | ||
![]() |
dcf9dcaf2a | ||
![]() |
a544db3020 | ||
![]() |
a1ee5a2c50 | ||
![]() |
e24114fed9 | ||
![]() |
0981808868 | ||
![]() |
bad1866c8a | ||
![]() |
d1722af79b | ||
![]() |
f7aeadeb0e | ||
![]() |
8fc7596fec | ||
![]() |
2ca5d8605b | ||
![]() |
b05e95ec87 | ||
![]() |
82c97d4022 | ||
![]() |
86819f05af | ||
![]() |
51c47daea3 | ||
![]() |
3976131e35 | ||
![]() |
57a0c16aeb | ||
![]() |
154bf55441 | ||
![]() |
8c8a2a5be3 | ||
![]() |
7467274d4d | ||
![]() |
b462ccd7dd | ||
![]() |
ca375a4cab | ||
![]() |
c571d22dba | ||
![]() |
c90a77f124 | ||
![]() |
bd8f69e438 | ||
![]() |
eac4489237 | ||
![]() |
0a132164c2 | ||
![]() |
6901c32a9d | ||
![]() |
130a446b90 | ||
![]() |
893ff81a8d | ||
![]() |
0fd97f652a | ||
![]() |
50375030a3 | ||
![]() |
cd3869e8b9 | ||
![]() |
ab683ca6a6 | ||
![]() |
881a0ac34a | ||
![]() |
be473054bd | ||
![]() |
bfa67ecf0c | ||
![]() |
0c1a090273 | ||
![]() |
f8eac4e83b | ||
![]() |
eba1e4aa7f |
59 changed files with 741 additions and 469 deletions
CMakeLists-implied-options.txt
READMEs
contrib
include
lib
core-net
core
event-libs
misc
plat
freertos
optee
unix
windows
roles
h2
http
netlink
raw-skt
ws
tls
minimal-examples
api-tests
http-client/minimal-http-client-certinfo
http-server/minimal-http-server-eventlib-custom
plugins/acme-client
test-apps
win32port/zlib
|
@ -368,6 +368,12 @@ if (LWS_WITHOUT_SERVER)
|
|||
set(LWS_WITH_SERVER)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_SERVER)
|
||||
else()
|
||||
set(LWS_WITH_CGI 0)
|
||||
set(LWS_ROLE_CGI 0)
|
||||
endif()
|
||||
|
||||
# using any abstract protocol enables LWS_WITH_ABSTRACT
|
||||
|
||||
#if (LWS_WITH_SMTP)
|
||||
|
|
|
@ -353,7 +353,7 @@ https://www.wolfssl.com/wolfSSL/Products-wolfssl.html
|
|||
It contains a OpenSSL compatibility layer which makes it possible to pretty
|
||||
much link to it instead of OpenSSL, giving a much smaller footprint.
|
||||
|
||||
**NOTE**: wolfssl needs to be compiled using the `--enable-opensslextra` flag for
|
||||
**NOTE**: wolfssl needs to be compiled using the `--enable-libwebsockets` flag for
|
||||
this to work.
|
||||
|
||||
@section wolf1 Compiling libwebsockets with wolfSSL
|
||||
|
|
|
@ -30,33 +30,44 @@ scheduler from your own code; it uses it to spread out connection
|
|||
attempts so they are staggered in time. You must create an
|
||||
`lws_sorted_usec_list_t` object somewhere, eg, in you own existing object.
|
||||
|
||||
```
|
||||
```c
|
||||
static lws_sorted_usec_list_t sul_stagger;
|
||||
```
|
||||
|
||||
Create your own callback for the event... the argument points to the sul object
|
||||
used when the callback was scheduled. You can use pointer arithmetic to translate
|
||||
that to your own struct when the `lws_sorted_usec_list_t` was a member of the
|
||||
same struct.
|
||||
that to your own struct (when the `lws_sorted_usec_list_t` was a member of the
|
||||
some struct) by using `lws_container_of(sul, container_struct_type, field_name)`.
|
||||
|
||||
```c
|
||||
typedef struct my_connection_data {
|
||||
...
|
||||
lws_sorted_usec_list_t sul_stagger;
|
||||
...
|
||||
} my_connection_data_t;
|
||||
|
||||
```
|
||||
static void
|
||||
stagger_cb(lws_sorted_usec_list_t *sul)
|
||||
{
|
||||
...
|
||||
my_connection_data_t* my_data = lws_container_of(sul, my_connection_data_t, sul_stagger);
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
**Important note**: make sure, that `lws_sorted_usec_list_t` data initiallized by
|
||||
zeros (`memset(&sul_stagger, 0, sizeof(lws_sorted_usec_list_t)`). This struct
|
||||
contains pointers, so them must initially pointing to `NULL`!
|
||||
|
||||
When you want to schedule the callback, use `lws_sul_schedule()`... this will call
|
||||
it 10ms in the future
|
||||
|
||||
```
|
||||
```c
|
||||
lws_sul_schedule(context, 0, &sul_stagger, stagger_cb, 10 * LWS_US_PER_MS);
|
||||
```
|
||||
|
||||
In the case you destroy your object and need to cancel the scheduled callback, use
|
||||
|
||||
```
|
||||
```c
|
||||
lws_sul_schedule(context, 0, &sul_stagger, NULL, LWS_SET_TIMER_USEC_CANCEL);
|
||||
```
|
||||
|
||||
|
|
|
@ -43,8 +43,10 @@ valid session object.
|
|||
### Difference from Session Tickets
|
||||
|
||||
TLS also supports sessions as bearer tokens, but these are generally considered
|
||||
as degrading security. Lws doesn't support Session Tickets, just reuse by
|
||||
Session IDs.
|
||||
as degrading security. Lws doesn't do anything special for Session Tickets, but
|
||||
it's possible your TLS library will support them by default, as is reportedly the
|
||||
case with mbedtls 2.28.1. Either way, it's expected Session IDs should work with
|
||||
lws if enabled and your tls library supports them.
|
||||
|
||||
## Support in lws
|
||||
|
||||
|
|
|
@ -24,13 +24,13 @@ CMAKE_OPTIONS += -DLWS_WITH_SSL=ON
|
|||
CMAKE_OPTIONS += -DLWS_WITHOUT_TESTAPPS=$(if $(CONFIG_PACKAGE_libwebsockets-examples),"OFF","ON")
|
||||
|
||||
# for wolfssl, define these in addition to LWS_OPENSSL_SUPPORT and
|
||||
# edit package/libs/wolfssl/Makefile to include --enable-opensslextra
|
||||
# edit package/libs/wolfssl/Makefile to include --enable-libwebsockets
|
||||
# CMAKE_OPTIONS += -DLWS_WITH_WOLFSSL=ON
|
||||
# CMAKE_OPTIONS += -DLWS_WOLFSSL_LIBRARIES=$(STAGING_DIR)/usr/lib/libwolfssl.so
|
||||
# CMAKE_OPTIONS += -DLWS_WOLFSSL_INCLUDE_DIRS=$(STAGING_DIR)/usr/include
|
||||
|
||||
# for cyassl, define these in addition to LWS_OPENSSL_SUPPORT and
|
||||
# edit package/libs/wolfssl/Makefile to include --enable-opensslextra
|
||||
# edit package/libs/wolfssl/Makefile to include --enable-libwebsockets
|
||||
# CMAKE_OPTIONS += -DLWS_WITH_CYASSL=ON
|
||||
# CMAKE_OPTIONS += -DLWS_CYASSL_LIBRARIES=$(STAGING_DIR)/usr/lib/libcyassl.so
|
||||
# CMAKE_OPTIONS += -DLWS_CYASSL_INCLUDE_DIRS=$(STAGING_DIR)/usr/include
|
||||
|
|
|
@ -88,8 +88,8 @@ typedef unsigned long long lws_intptr_t;
|
|||
#define O_RDONLY _O_RDONLY
|
||||
#endif
|
||||
|
||||
typedef int uid_t;
|
||||
typedef int gid_t;
|
||||
typedef unsigned int uid_t;
|
||||
typedef unsigned int gid_t;
|
||||
typedef unsigned short sa_family_t;
|
||||
#if !defined(LWS_HAVE_SUSECONDS_T)
|
||||
typedef unsigned int useconds_t;
|
||||
|
@ -132,7 +132,7 @@ typedef int suseconds_t;
|
|||
#define LWS_O_CREAT _O_CREAT
|
||||
#define LWS_O_TRUNC _O_TRUNC
|
||||
|
||||
#ifndef __func__
|
||||
#if (__STDC_VERSION__ < 199901L) && !defined(__func__)
|
||||
#define __func__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ struct lws_genaes_ctx {
|
|||
char underway;
|
||||
};
|
||||
|
||||
/** lws_genaes_create() - Create RSA public decrypt context
|
||||
/** lws_genaes_create() - Create genaes AES context
|
||||
*
|
||||
* \param ctx: your struct lws_genaes_ctx
|
||||
* \param op: LWS_GAESO_ENC or LWS_GAESO_DEC
|
||||
|
@ -98,7 +98,7 @@ struct lws_genaes_ctx {
|
|||
* \param padding: 0 = no padding, 1 = padding
|
||||
* \param engine: if openssl engine used, pass the pointer here
|
||||
*
|
||||
* Creates an RSA context with a public key associated with it, formed from
|
||||
* Creates an AES context with a key associated with it, formed from
|
||||
* the key elements in \p el.
|
||||
*
|
||||
* Returns 0 for OK or nonzero for error.
|
||||
|
|
|
@ -184,7 +184,7 @@ lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi,
|
|||
*
|
||||
* Built-in callback implementing RFC7692 permessage-deflate
|
||||
*/
|
||||
LWS_EXTERN int
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_extension_callback_pm_deflate(struct lws_context *context,
|
||||
const struct lws_extension *ext,
|
||||
struct lws *wsi,
|
||||
|
|
|
@ -217,7 +217,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads,
|
|||
*/
|
||||
|
||||
lwsi_set_state(wsi, LRS_UNCONNECTED);
|
||||
lws_sul_schedule(wsi->a.context, 0, &wsi->sul_connect_timeout,
|
||||
lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->sul_connect_timeout,
|
||||
lws_client_dns_retry_timeout,
|
||||
LWS_USEC_PER_SEC);
|
||||
return wsi;
|
||||
|
@ -601,7 +601,7 @@ ads_known:
|
|||
* uses wsi->sul_connect_timeout just for this purpose
|
||||
*/
|
||||
|
||||
lws_sul_schedule(wsi->a.context, 0, &wsi->sul_connect_timeout,
|
||||
lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->sul_connect_timeout,
|
||||
lws_client_conn_wait_timeout,
|
||||
wsi->a.context->timeout_secs *
|
||||
LWS_USEC_PER_SEC);
|
||||
|
@ -728,6 +728,7 @@ try_next_dns_result:
|
|||
lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
|
||||
|
||||
failed1:
|
||||
lws_sul_cancel(&wsi->sul_connect_timeout);
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect3");
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -279,7 +279,7 @@ send_hs:
|
|||
pfd.revents = LWS_POLLOUT;
|
||||
|
||||
lwsl_wsi_info(wsi, "going to service fd");
|
||||
n = lws_service_fd(wsi->a.context, &pfd);
|
||||
n = lws_service_fd_tsi(wsi->a.context, &pfd, wsi->tsi);
|
||||
if (n < 0) {
|
||||
cce = "first service failed";
|
||||
goto failed;
|
||||
|
@ -318,7 +318,7 @@ provoke_service:
|
|||
pfd.events = LWS_POLLIN;
|
||||
pfd.revents = LWS_POLLIN;
|
||||
|
||||
n = lws_service_fd(wsi->a.context, &pfd);
|
||||
n = lws_service_fd_tsi(wsi->a.context, &pfd, wsi->tsi);
|
||||
if (n < 0) {
|
||||
cce = "first service failed";
|
||||
goto failed;
|
||||
|
|
|
@ -881,9 +881,19 @@ __lws_close_free_wsi_final(struct lws *wsi)
|
|||
if (!wsi->shadow &&
|
||||
lws_socket_is_valid(wsi->desc.sockfd) && !lws_ssl_close(wsi)) {
|
||||
lwsl_wsi_debug(wsi, "fd %d", wsi->desc.sockfd);
|
||||
n = compatible_close(wsi->desc.sockfd);
|
||||
if (n)
|
||||
lwsl_wsi_debug(wsi, "closing: close ret %d", LWS_ERRNO);
|
||||
|
||||
/*
|
||||
* if this is the pt pipe, skip the actual close,
|
||||
* go through the motions though so we will reach 0 open wsi
|
||||
* on the pt, and trigger the pt destroy to close the pipe fds
|
||||
*/
|
||||
if (!lws_plat_pipe_is_fd_assocated(wsi->a.context, wsi->tsi,
|
||||
wsi->desc.sockfd)) {
|
||||
n = compatible_close(wsi->desc.sockfd);
|
||||
if (n)
|
||||
lwsl_wsi_debug(wsi, "closing: close ret %d",
|
||||
LWS_ERRNO);
|
||||
}
|
||||
|
||||
__remove_wsi_socket_from_fds(wsi);
|
||||
if (lws_socket_is_valid(wsi->desc.sockfd))
|
||||
|
|
|
@ -1326,6 +1326,8 @@ int
|
|||
lws_plat_pipe_signal(struct lws_context *ctx, int tsi);
|
||||
void
|
||||
lws_plat_pipe_close(struct lws *wsi);
|
||||
int
|
||||
lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd);
|
||||
|
||||
void
|
||||
lws_addrinfo_clean(struct lws *wsi);
|
||||
|
|
|
@ -1305,7 +1305,7 @@ lws_mux_mark_immortal(struct lws *wsi)
|
|||
&& !wsi->client_mux_substream
|
||||
#endif
|
||||
) {
|
||||
lwsl_wsi_err(wsi, "not mux substream");
|
||||
// lwsl_wsi_err(wsi, "not mux substream");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -386,9 +386,6 @@ lws_create_context(const struct lws_context_creation_info *info)
|
|||
#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT)
|
||||
struct lws_cache_creation_info ci;
|
||||
#endif
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
char mbedtls_version[32];
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
struct rlimit rt;
|
||||
|
@ -545,6 +542,11 @@ lws_create_context(const struct lws_context_creation_info *info)
|
|||
fatal_exit_defer = !!info->foreign_loops;
|
||||
us_wait_resolution = 0;
|
||||
}
|
||||
#else
|
||||
if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBUV)) {
|
||||
lwsl_cx_err(context, "Application wants libuv, but lws not built with it");
|
||||
goto bail;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_LIBEVENT)
|
||||
|
@ -553,6 +555,11 @@ lws_create_context(const struct lws_context_creation_info *info)
|
|||
plev = &evlib_event;
|
||||
us_wait_resolution = 0;
|
||||
}
|
||||
#else
|
||||
if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEVENT)) {
|
||||
lwsl_cx_err(context, "Application wants libevent, but lws not built with it");
|
||||
goto bail;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_GLIB)
|
||||
|
@ -561,6 +568,11 @@ lws_create_context(const struct lws_context_creation_info *info)
|
|||
plev = &evlib_glib;
|
||||
us_wait_resolution = 0;
|
||||
}
|
||||
#else
|
||||
if (lws_check_opt(info->options, LWS_SERVER_OPTION_GLIB)) {
|
||||
lwsl_cx_err(context, "Application wants glib, but lws not built with it");
|
||||
goto bail;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_LIBEV)
|
||||
|
@ -569,6 +581,11 @@ lws_create_context(const struct lws_context_creation_info *info)
|
|||
plev = &evlib_ev;
|
||||
us_wait_resolution = 0;
|
||||
}
|
||||
#else
|
||||
if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEV)) {
|
||||
lwsl_cx_err(context, "Application wants libev, but lws not built with it");
|
||||
goto bail;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_SDEVENT)
|
||||
|
@ -577,6 +594,11 @@ lws_create_context(const struct lws_context_creation_info *info)
|
|||
plev = &evlib_sd;
|
||||
us_wait_resolution = 0;
|
||||
}
|
||||
#else
|
||||
if (lws_check_opt(info->options, LWS_SERVER_OPTION_SDEVENT)) {
|
||||
lwsl_cx_err(context, "Application wants sdevent, but lws not built with it");
|
||||
goto bail;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_ULOOP)
|
||||
|
@ -585,6 +607,11 @@ lws_create_context(const struct lws_context_creation_info *info)
|
|||
plev = &evlib_uloop;
|
||||
us_wait_resolution = 0;
|
||||
}
|
||||
#else
|
||||
if (lws_check_opt(info->options, LWS_SERVER_OPTION_ULOOP)) {
|
||||
lwsl_cx_err(context, "Application wants uloop, but lws not built with it");
|
||||
goto bail;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* with event libs */
|
||||
|
@ -788,11 +815,16 @@ lws_create_context(const struct lws_context_creation_info *info)
|
|||
#endif /* network */
|
||||
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
mbedtls_version_get_string(mbedtls_version);
|
||||
#endif
|
||||
{
|
||||
char mbedtls_version[32];
|
||||
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
lwsl_cx_notice(context, "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s);
|
||||
#if defined(MBEDTLS_VERSION_C)
|
||||
mbedtls_version_get_string(mbedtls_version);
|
||||
#else
|
||||
lws_snprintf(mbedtls_version, sizeof(mbedtls_version), "%s", MBEDTLS_VERSION_STRING);
|
||||
#endif
|
||||
lwsl_cx_notice(context, "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s);
|
||||
}
|
||||
#else
|
||||
lwsl_cx_notice(context, "LWS: %s, %s%s", library_version, opts_str, s);
|
||||
#endif
|
||||
|
|
|
@ -29,11 +29,11 @@ typedef struct lws_map_hashtable {
|
|||
lws_dll2_owner_t ho;
|
||||
} lws_map_hashtable_t;
|
||||
|
||||
typedef struct lws_map {
|
||||
struct lws_map {
|
||||
lws_map_info_t info;
|
||||
|
||||
/* array of info.modulo x lws_map_hashtable_t overallocated */
|
||||
} lws_map_t;
|
||||
};
|
||||
|
||||
typedef struct lws_map_item {
|
||||
lws_dll2_t list; /* owned by hashtable */
|
||||
|
@ -88,7 +88,10 @@ lws_map_hash_from_key_default(const lws_map_key_t key, size_t kl)
|
|||
const uint8_t *u = (const uint8_t *)key;
|
||||
|
||||
while (kl--)
|
||||
h = ((((h << 7) | (h >> 25)) + 0xa1b2c3d4) ^ (*u++)) ^ h;
|
||||
h = ((
|
||||
(((h & 0x1fffffff /* coverity */ ) << 7) |
|
||||
(h >> 25)) +
|
||||
0xa1b2c3d4) ^ (*u++)) ^ h;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
|
|
@ -94,6 +94,7 @@ lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
|
|||
struct lws_context_per_thread *pt;
|
||||
struct lws_pollfd eventfd;
|
||||
struct lws *wsi;
|
||||
int tsi = 0;
|
||||
|
||||
if (revents & EV_ERROR)
|
||||
return;
|
||||
|
@ -112,10 +113,12 @@ lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
|
|||
}
|
||||
|
||||
wsi = wsi_from_fd(context, watcher->fd);
|
||||
pt = &context->pt[(int)wsi->tsi];
|
||||
if (wsi)
|
||||
tsi = (int)wsi->tsi;
|
||||
pt = &context->pt[tsi];
|
||||
ptpr = pt_to_priv_ev(pt);
|
||||
|
||||
lws_service_fd_tsi(context, &eventfd, (int)wsi->tsi);
|
||||
lws_service_fd_tsi(context, &eventfd, tsi);
|
||||
|
||||
ev_idle_start(ptpr->io_loop, &ptpr->idle);
|
||||
}
|
||||
|
@ -136,6 +139,7 @@ lws_ev_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents)
|
|||
static int
|
||||
elops_listen_init_ev(struct lws_dll2 *d, void *user)
|
||||
{
|
||||
#if defined(LWS_WITH_SERVER)
|
||||
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
|
||||
struct lws_context *context = (struct lws_context *)user;
|
||||
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
||||
|
@ -150,6 +154,7 @@ elops_listen_init_ev(struct lws_dll2 *d, void *user)
|
|||
ev_io_init(&vh_to_priv_ev(vh)->w_accept.watcher,
|
||||
lws_accept_cb, wsi->desc.sockfd, EV_READ);
|
||||
ev_io_start(ptpr->io_loop, &vh_to_priv_ev(vh)->w_accept.watcher);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -240,6 +245,7 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
|
|||
static int
|
||||
elops_listen_destroy_ev(struct lws_dll2 *d, void *user)
|
||||
{
|
||||
#if defined(LWS_WITH_SERVER)
|
||||
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
|
||||
struct lws_context *context = (struct lws_context *)user;
|
||||
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
||||
|
@ -247,7 +253,7 @@ elops_listen_destroy_ev(struct lws_dll2 *d, void *user)
|
|||
struct lws_vhost *vh = wsi->a.vhost;
|
||||
|
||||
ev_io_stop(ptpr->io_loop, &vh_to_priv_ev(vh)->w_accept.watcher);
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -413,6 +419,14 @@ elops_destroy_wsi_ev(struct lws *wsi)
|
|||
ev_io_stop(ptpr->io_loop, &w->w_write.watcher);
|
||||
}
|
||||
|
||||
static int
|
||||
elops_wsi_logical_close_ev(struct lws *wsi)
|
||||
{
|
||||
elops_destroy_wsi_ev(wsi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct lws_event_loop_ops event_loop_ops_ev = {
|
||||
/* name */ "libev",
|
||||
/* init_context */ elops_init_context_ev,
|
||||
|
@ -420,7 +434,7 @@ static const struct lws_event_loop_ops event_loop_ops_ev = {
|
|||
/* destroy_context2 */ elops_destroy_context2_ev,
|
||||
/* init_vhost_listen_wsi */ elops_init_vhost_listen_wsi_ev,
|
||||
/* init_pt */ elops_init_pt_ev,
|
||||
/* wsi_logical_close */ NULL,
|
||||
/* wsi_logical_close */ elops_wsi_logical_close_ev,
|
||||
/* check_client_connect_ok */ NULL,
|
||||
/* close_handle_manually */ NULL,
|
||||
/* accept */ elops_accept_ev,
|
||||
|
|
|
@ -176,6 +176,7 @@ lws_event_sigint_cb(evutil_socket_t sock_fd, short revents, void *ctx)
|
|||
static int
|
||||
elops_listen_init_event(struct lws_dll2 *d, void *user)
|
||||
{
|
||||
#if defined(LWS_WITH_SERVER)
|
||||
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
|
||||
struct lws_context *context = (struct lws_context *)user;
|
||||
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
||||
|
@ -188,6 +189,7 @@ elops_listen_init_event(struct lws_dll2 *d, void *user)
|
|||
(EV_READ | EV_PERSIST), lws_event_cb, w_read);
|
||||
event_add(w_read->watcher, NULL);
|
||||
w_read->set = 1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -334,6 +336,7 @@ elops_run_pt_event(struct lws_context *context, int tsi)
|
|||
static int
|
||||
elops_listen_destroy_event(struct lws_dll2 *d, void *user)
|
||||
{
|
||||
#if defined(LWS_WITH_SERVER)
|
||||
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
|
||||
struct lws_wsi_eventlibs_libevent *w = wsi_to_priv_event(wsi);
|
||||
|
||||
|
@ -341,6 +344,7 @@ elops_listen_destroy_event(struct lws_dll2 *d, void *user)
|
|||
w->w_read.watcher = NULL;
|
||||
event_free(w->w_write.watcher);
|
||||
w->w_write.watcher = NULL;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -698,10 +698,12 @@ elops_destroy_pt_uv(struct lws_context *context, int tsi)
|
|||
static int
|
||||
elops_listen_init_uv(struct lws_dll2 *d, void *user)
|
||||
{
|
||||
#if defined(LWS_WITH_SERVER)
|
||||
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
|
||||
|
||||
if (elops_init_vhost_listen_wsi_uv(wsi) == -1)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -234,10 +234,12 @@ init_vhost_listen_wsi_sd(struct lws *wsi)
|
|||
static int
|
||||
elops_listen_init_sdevent(struct lws_dll2 *d, void *user)
|
||||
{
|
||||
#if defined(LWS_WITH_SERVER)
|
||||
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
|
||||
|
||||
if (init_vhost_listen_wsi_sd(wsi) == -1)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -368,9 +370,11 @@ run_pt_sd(struct lws_context *context, int tsi)
|
|||
static int
|
||||
elops_listen_destroy_sdevent(struct lws_dll2 *d, void *user)
|
||||
{
|
||||
#if defined(LWS_WITH_SERVER)
|
||||
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
|
||||
|
||||
wsi_logical_close_sd(wsi);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -135,6 +135,7 @@ lws_uloop_cb(struct uloop_fd *ufd, unsigned int revents)
|
|||
static int
|
||||
elops_listen_init_uloop(struct lws_dll2 *d, void *user)
|
||||
{
|
||||
#if defined(LWS_WITH_SERVER)
|
||||
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
|
||||
struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi);
|
||||
|
||||
|
@ -143,6 +144,7 @@ elops_listen_init_uloop(struct lws_dll2 *d, void *user)
|
|||
wu->fd.cb = lws_uloop_cb;
|
||||
uloop_fd_add(&wu->fd, ULOOP_READ);
|
||||
wu->actual_events = ULOOP_READ;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -217,10 +219,12 @@ elops_run_pt_uloop(struct lws_context *context, int tsi)
|
|||
static int
|
||||
elops_listen_destroy_uloop(struct lws_dll2 *d, void *user)
|
||||
{
|
||||
#if defined(LWS_WITH_SERVER)
|
||||
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
|
||||
struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi);
|
||||
|
||||
uloop_fd_delete(&wu->fd);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -163,7 +163,11 @@ nscookiejar_iterate(lws_cache_nscookiejar_t *cache, int fd,
|
|||
lwsl_debug("%s: n %d, m %d\n", __func__, n, m);
|
||||
|
||||
read:
|
||||
n1 = (int)read(fd, temp + n, sizeof(temp) - (size_t)n);
|
||||
if ((size_t)n >= sizeof(temp) - 1)
|
||||
/* there's no space left in temp */
|
||||
n1 = 0;
|
||||
else
|
||||
n1 = (int)read(fd, temp + n, sizeof(temp) - (size_t)n);
|
||||
|
||||
lwsl_debug("%s: n1 %d\n", __func__, n1);
|
||||
|
||||
|
@ -171,12 +175,18 @@ read:
|
|||
eof = 1;
|
||||
if (m == n)
|
||||
continue;
|
||||
} else
|
||||
} else {
|
||||
n += n1;
|
||||
|
||||
if ((size_t)n > sizeof(temp)) { /* coverity */
|
||||
ret = -1;
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
while (m < n) {
|
||||
|
||||
m++;
|
||||
m++; /* m can == n nw then */
|
||||
|
||||
if (temp[m - 1] != '\n')
|
||||
continue;
|
||||
|
@ -197,6 +207,13 @@ read:
|
|||
* cb can classify it even if it can't get all the
|
||||
* value part in one go
|
||||
*/
|
||||
|
||||
/* coverity: we will blow up if m > n */
|
||||
if (m > n) {
|
||||
ret = -1;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
memmove(temp, temp + m, (size_t)(n - m));
|
||||
n -= m;
|
||||
m = 0;
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicefsme, and/or
|
||||
* sell copies of the Software, and to permit persofsm to whom the Software is
|
||||
* furnished to do so, subject to the following conditiofsm:
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portiofsm of the Software.
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
|
|
|
@ -985,7 +985,7 @@ format_scan(const char *fmt)
|
|||
}
|
||||
|
||||
if (numeric) {
|
||||
if (*fmt >= '0' && *fmt <= '9')
|
||||
while (*fmt >= '0' && *fmt <= '9')
|
||||
fmt++;
|
||||
numeric = 0;
|
||||
if (*fmt != '(')
|
||||
|
@ -1119,6 +1119,7 @@ pop:
|
|||
|
||||
return count[0];
|
||||
|
||||
case '-':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
|
|
|
@ -580,7 +580,8 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
|
|||
}
|
||||
|
||||
ctx->buf[ctx->npos] = '\0';
|
||||
if (ctx->f & LEJP_SEEN_POINT) {
|
||||
if (ctx->f & (LEJP_SEEN_POINT | LEJP_SEEN_EXP)) {
|
||||
/* 0.001 or 1E-3 are both floats, take 1E3 as float too */
|
||||
if (ctx->pst[ctx->pst_sp].callback(ctx,
|
||||
LEJPCB_VAL_NUM_FLOAT))
|
||||
goto reject_callback;
|
||||
|
|
|
@ -124,3 +124,11 @@ lws_plat_pipe_close(struct lws *wsi)
|
|||
|
||||
fd[0] = fd[1] = -1;
|
||||
}
|
||||
|
||||
int
|
||||
lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &cx->pt[tsi];
|
||||
|
||||
return fd == pt->dummy_pipe_fds[0] || fd == pt->dummy_pipe_fds[1];
|
||||
}
|
||||
|
|
|
@ -49,6 +49,12 @@ lws_plat_pipe_close(struct lws *wsi)
|
|||
{
|
||||
}
|
||||
|
||||
int
|
||||
lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lws_send_pipe_choked(struct lws *wsi)
|
||||
{
|
||||
|
|
|
@ -83,7 +83,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
|
|||
const char *vpath, lws_fop_flags_t *flags)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
int ret = lws_open(filename, (*flags) & LWS_FOP_FLAGS_MASK, 0664);
|
||||
int ret = lws_open(filename, (int)((*flags) & LWS_FOP_FLAGS_MASK), 0664);
|
||||
lws_fop_fd_t fop_fd;
|
||||
|
||||
if (ret < 0)
|
||||
|
|
|
@ -240,4 +240,9 @@ lws_plat_context_late_destroy(struct lws_context *context)
|
|||
lwsl_err("ZERO RANDOM FD\n");
|
||||
if (context->fd_random != LWS_INVALID_FILE)
|
||||
close(context->fd_random);
|
||||
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
mbedtls_entropy_free(&context->mec);
|
||||
mbedtls_ctr_drbg_free(&context->mcdc);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -84,10 +84,20 @@ lws_plat_pipe_close(struct lws *wsi)
|
|||
{
|
||||
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
|
||||
|
||||
if (pt->dummy_pipe_fds[0] && pt->dummy_pipe_fds[0] != -1)
|
||||
if (pt->dummy_pipe_fds[0] && pt->dummy_pipe_fds[0] != -1) {
|
||||
close(pt->dummy_pipe_fds[0]);
|
||||
if (pt->dummy_pipe_fds[1] && pt->dummy_pipe_fds[1] != -1)
|
||||
pt->dummy_pipe_fds[0] = -1;
|
||||
}
|
||||
if (pt->dummy_pipe_fds[1] && pt->dummy_pipe_fds[1] != -1) {
|
||||
close(pt->dummy_pipe_fds[1]);
|
||||
|
||||
pt->dummy_pipe_fds[0] = pt->dummy_pipe_fds[1] = -1;
|
||||
pt->dummy_pipe_fds[1] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &cx->pt[tsi];
|
||||
|
||||
return fd == pt->dummy_pipe_fds[0] || fd == pt->dummy_pipe_fds[1];
|
||||
}
|
||||
|
|
|
@ -191,21 +191,23 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt)
|
|||
}
|
||||
|
||||
static const int ip_opt_lws_flags[] = {
|
||||
LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT,
|
||||
LCCSCF_IP_HIGH_RELIABILITY
|
||||
#if !defined(__OpenBSD__)
|
||||
LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT
|
||||
#if !defined(__OpenBSD__) && !defined(__sun) && !defined(__QNX__)
|
||||
, LCCSCF_IP_HIGH_RELIABILITY
|
||||
, LCCSCF_IP_LOW_COST
|
||||
#endif
|
||||
}, ip_opt_val[] = {
|
||||
IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_RELIABILITY
|
||||
IPTOS_LOWDELAY, IPTOS_THROUGHPUT
|
||||
#if !defined(__OpenBSD__) && !defined(__sun) && !defined(__QNX__)
|
||||
, IPTOS_RELIABILITY
|
||||
, IPTOS_MINCOST
|
||||
#endif
|
||||
};
|
||||
#if !defined(LWS_WITH_NO_LOGS)
|
||||
static const char *ip_opt_names[] = {
|
||||
"LOWDELAY", "THROUGHPUT", "RELIABILITY"
|
||||
#if !defined(__OpenBSD__) && !defined(__sun)
|
||||
"LOWDELAY", "THROUGHPUT"
|
||||
#if !defined(__OpenBSD__) && !defined(__sun) && !defined(__QNX__)
|
||||
, "RELIABILITY"
|
||||
, "MINCOST"
|
||||
#endif
|
||||
};
|
||||
|
@ -255,7 +257,10 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
|
|||
}
|
||||
#endif
|
||||
|
||||
for (n = 0; n < 4; n++) {
|
||||
|
||||
#if !defined(__NuttX__)
|
||||
/* array size differs by platform */
|
||||
for (n = 0; n < (int)LWS_ARRAY_SIZE(ip_opt_lws_flags); n++) {
|
||||
if (!(lws_flags & ip_opt_lws_flags[n]))
|
||||
continue;
|
||||
|
||||
|
@ -272,6 +277,7 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
|
|||
lwsl_notice("%s: set ip flag %s\n", __func__,
|
||||
ip_opt_names[n]);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -435,7 +441,7 @@ lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, size_t canned_len,
|
|||
p[3] = (uint8_t)(n);
|
||||
|
||||
while (p16 < (uint16_t *)(p + 20))
|
||||
ucs += ntohs(*p16++);
|
||||
ucs = ucs + (uint32_t)(ntohs((uint16_t)(*p16++)));
|
||||
|
||||
ucs += ucs >> 16;
|
||||
ucs ^= 0xffff;
|
||||
|
@ -447,7 +453,7 @@ lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, size_t canned_len,
|
|||
|
||||
memset(&sll, 0, sizeof(sll));
|
||||
sll.sll_family = AF_PACKET;
|
||||
sll.sll_protocol = htons(0x800);
|
||||
sll.sll_protocol = (uint32_t)(htons((uint16_t)0x800));
|
||||
sll.sll_halen = 6;
|
||||
sll.sll_ifindex = (int)if_nametoindex(iface);
|
||||
memset(sll.sll_addr, 0xff, 6);
|
||||
|
|
|
@ -549,8 +549,10 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i)
|
|||
int naml = lws_ptr_diff(p, i->env_array[m]);
|
||||
char enam[32];
|
||||
|
||||
lws_strnncpy(enam, i->env_array[m], naml, sizeof(enam));
|
||||
setenv(enam, p, 1);
|
||||
if (p) {
|
||||
lws_strnncpy(enam, i->env_array[m], naml, sizeof(enam));
|
||||
setenv(enam, p + 1, 1);
|
||||
}
|
||||
m++;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -49,7 +49,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
|
|||
ret = CreateFileW(buf, GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (ret == NULL)
|
||||
if (ret == INVALID_HANDLE_VALUE)
|
||||
goto bail;
|
||||
|
||||
fop_fd = malloc(sizeof(*fop_fd));
|
||||
|
|
|
@ -125,3 +125,11 @@ lws_plat_pipe_close(struct lws *wsi)
|
|||
|
||||
pt->dummy_pipe_fds[0] = pt->dummy_pipe_fds[1] = LWS_SOCK_INVALID;
|
||||
}
|
||||
|
||||
int
|
||||
lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &cx->pt[tsi];
|
||||
|
||||
return fd == pt->dummy_pipe_fds[0] || fd == pt->dummy_pipe_fds[1];
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
|
|||
struct lws_context_per_thread *pt;
|
||||
struct lws_pollfd *pfd;
|
||||
lws_usec_t timeout_us;
|
||||
int64_t timeout_ms64 = (int64_t)timeout_ms;
|
||||
struct lws *wsi;
|
||||
unsigned int i;
|
||||
int n;
|
||||
|
@ -85,12 +86,12 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
|
|||
pt->service_tid_detected = 1;
|
||||
}
|
||||
|
||||
if (timeout_ms < 0)
|
||||
timeout_ms = 0;
|
||||
if (timeout_ms64 < 0)
|
||||
timeout_ms64 = 0;
|
||||
else
|
||||
/* force a default timeout of 23 days */
|
||||
timeout_ms = 2000000000;
|
||||
timeout_us = ((lws_usec_t)timeout_ms) * LWS_US_PER_MS;
|
||||
timeout_ms64 = 2000000000;
|
||||
timeout_us = ((lws_usec_t)timeout_ms64) * LWS_US_PER_MS;
|
||||
|
||||
if (context->event_loop_ops->run_pt)
|
||||
context->event_loop_ops->run_pt(context, tsi);
|
||||
|
@ -176,6 +177,11 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
|
|||
// lwsl_notice("%s: idx %d, revents 0x%x\n", __func__, n, pt->fds[n].revents);
|
||||
lws_service_fd_tsi(context, &pt->fds[n], tsi);
|
||||
}
|
||||
|
||||
if (pt->destroy_self) {
|
||||
lws_context_destroy(pt->context);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -81,10 +81,7 @@ lws_plat_set_nonblocking(lws_sockfd_type fd)
|
|||
int result = !!ioctlsocket(fd, FIONBIO, &optl);
|
||||
#if (_LWS_ENABLED_LOGS & LLL_ERR)
|
||||
if (result)
|
||||
{
|
||||
int error = LWS_ERRNO;
|
||||
lwsl_err("ioctlsocket FIONBIO 1 failed with error %d\n", error);
|
||||
}
|
||||
lwsl_err("ioctlsocket FIONBIO 1 failed with error %d\n", LWS_ERRNO);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
@ -108,8 +105,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
|
|||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(const char *)&optval, optlen) < 0) {
|
||||
#if (_LWS_ENABLED_LOGS & LLL_ERR)
|
||||
int error = LWS_ERRNO;
|
||||
lwsl_err("setsockopt SO_KEEPALIVE 1 failed with error %d\n", error);
|
||||
lwsl_err("setsockopt SO_KEEPALIVE 1 failed with error %d\n", LWS_ERRNO);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
@ -121,8 +117,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
|
|||
if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
|
||||
NULL, 0, &dwBytesRet, NULL, NULL)) {
|
||||
#if (_LWS_ENABLED_LOGS & LLL_ERR)
|
||||
int error = LWS_ERRNO;
|
||||
lwsl_err("WSAIoctl SIO_KEEPALIVE_VALS 1 %lu %lu failed with error %d\n", alive.keepalivetime, alive.keepaliveinterval, error);
|
||||
lwsl_err("WSAIoctl SIO_KEEPALIVE_VALS 1 %lu %lu failed with error %d\n", alive.keepalivetime, alive.keepaliveinterval, LWS_ERRNO);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
@ -134,8 +129,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
|
|||
tcp_proto = getprotobyname("TCP");
|
||||
if (!tcp_proto) {
|
||||
#if (_LWS_ENABLED_LOGS & LLL_WARN)
|
||||
int error = LWS_ERRNO;
|
||||
lwsl_warn("getprotobyname(\"TCP\") failed with error, falling back to 6 %d\n", error);
|
||||
lwsl_warn("getprotobyname(\"TCP\") failed with error, falling back to 6 %d\n", LWS_ERRNO);
|
||||
#endif
|
||||
protonbr = 6; /* IPPROTO_TCP */
|
||||
} else
|
||||
|
@ -146,8 +140,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
|
|||
|
||||
if (setsockopt(fd, protonbr, TCP_NODELAY, (const char *)&optval, optlen) ) {
|
||||
#if (_LWS_ENABLED_LOGS & LLL_WARN)
|
||||
int error = LWS_ERRNO;
|
||||
lwsl_warn("setsockopt TCP_NODELAY 1 failed with error %d\n", error);
|
||||
lwsl_warn("setsockopt TCP_NODELAY 1 failed with error %d\n", LWS_ERRNO);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -2322,12 +2322,14 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t _inlen,
|
|||
(unsigned int)h2n->count,
|
||||
(unsigned int)h2n->length);
|
||||
|
||||
in += (unsigned int)n - 1;
|
||||
h2n->inside += (unsigned int)n;
|
||||
h2n->count += (unsigned int)n - 1;
|
||||
if (n) {
|
||||
in += (unsigned int)n - 1;
|
||||
h2n->inside += (unsigned int)n;
|
||||
h2n->count += (unsigned int)n - 1;
|
||||
|
||||
h2n->swsi->txc.peer_tx_cr_est -= n;
|
||||
wsi->txc.peer_tx_cr_est -= n;
|
||||
h2n->swsi->txc.peer_tx_cr_est -= n;
|
||||
wsi->txc.peer_tx_cr_est -= n;
|
||||
}
|
||||
|
||||
do_windows:
|
||||
|
||||
|
|
|
@ -227,11 +227,13 @@ read:
|
|||
// lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2 &&
|
||||
lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS))) {
|
||||
|
||||
int scr_ret;
|
||||
|
||||
ebuf.token = pt->serv_buf;
|
||||
ebuf.len = lws_ssl_capable_read(wsi,
|
||||
scr_ret = lws_ssl_capable_read(wsi,
|
||||
ebuf.token,
|
||||
wsi->a.context->pt_serv_buf_size);
|
||||
switch (ebuf.len) {
|
||||
switch (scr_ret) {
|
||||
case 0:
|
||||
lwsl_info("%s: zero length read\n", __func__);
|
||||
return LWS_HPI_RET_PLEASE_CLOSE_ME;
|
||||
|
@ -243,6 +245,19 @@ read:
|
|||
return LWS_HPI_RET_PLEASE_CLOSE_ME;
|
||||
}
|
||||
|
||||
/*
|
||||
* coverity is confused: it knows lws_ssl_capable_read may
|
||||
* return < 0 and assigning that to ebuf.len is bad, but it
|
||||
* doesn't understand this check below on scr_ret < 0
|
||||
* removes that possibility
|
||||
*/
|
||||
|
||||
ebuf.len = scr_ret;
|
||||
if (ebuf.len < 0) /* ie, not usable data */ {
|
||||
lwsl_info("%s: other error\n", __func__);
|
||||
return LWS_HPI_RET_PLEASE_CLOSE_ME;
|
||||
}
|
||||
|
||||
// lwsl_notice("%s: Actual RX %d\n", __func__, ebuf.len);
|
||||
// if (ebuf.len > 0)
|
||||
// lwsl_hexdump_notice(ebuf.token, ebuf.len);
|
||||
|
@ -313,7 +328,8 @@ drain:
|
|||
lws_dll2_remove(&wsi->dll_buflist);
|
||||
}
|
||||
} else
|
||||
if (n && n < ebuf.len && ebuf.len > 0) {
|
||||
/* cov: both n and ebuf.len are int */
|
||||
if (n > 0 && n < ebuf.len && ebuf.len > 0) {
|
||||
// lwsl_notice("%s: h2 append seg %d\n", __func__, ebuf.len - n);
|
||||
m = lws_buflist_append_segment(&wsi->buflist,
|
||||
ebuf.token + n,
|
||||
|
|
|
@ -1255,6 +1255,8 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt)
|
|||
// if (!wsi->client_pipeline)
|
||||
// conn1 = "close, ";
|
||||
p = lws_generate_client_ws_handshake(wsi, p, conn1);
|
||||
if (!p)
|
||||
return NULL;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
|
|
@ -160,11 +160,13 @@ lws_cookie_rm_sws(const char **buf_p, size_t *len_p)
|
|||
|
||||
buf = *buf_p;
|
||||
len = *len_p;
|
||||
|
||||
while (buf[0] == ' ' && len > 0) {
|
||||
buf++;
|
||||
len--;
|
||||
}
|
||||
while (buf[len - 1] == ' ' && len > 0)
|
||||
|
||||
while (len && buf[len - 1] == ' ')
|
||||
len--;
|
||||
|
||||
*buf_p = buf;
|
||||
|
|
|
@ -570,7 +570,7 @@ lws_spa_create_via_info(struct lws *wsi, const lws_spa_create_info_t *i)
|
|||
if (!spa->storage)
|
||||
goto bail2;
|
||||
|
||||
spa->end = spa->storage + i->max_storage - 1;
|
||||
spa->end = spa->storage + spa->i.max_storage - 1;
|
||||
|
||||
if (i->count_params) {
|
||||
if (i->ac)
|
||||
|
@ -583,7 +583,7 @@ lws_spa_create_via_info(struct lws *wsi, const lws_spa_create_info_t *i)
|
|||
goto bail3;
|
||||
}
|
||||
|
||||
spa->s = lws_urldecode_s_create(spa, wsi, spa->storage, i->max_storage,
|
||||
spa->s = lws_urldecode_s_create(spa, wsi, spa->storage, spa->i.max_storage,
|
||||
lws_urldecode_spa_cb);
|
||||
if (!spa->s)
|
||||
goto bail4;
|
||||
|
|
|
@ -345,9 +345,11 @@ done_list:
|
|||
if (setsockopt(wsi->desc.sockfd, IPPROTO_TCP,
|
||||
TCP_FASTOPEN,
|
||||
(const char*)&optval, sizeof(optval)) < 0) {
|
||||
#if (_LWS_ENABLED_LOGS & LLL_WARN)
|
||||
int error = LWS_ERRNO;
|
||||
lwsl_warn("%s: TCP_NODELAY failed with error %d\n",
|
||||
__func__, error);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -526,7 +526,6 @@ rops_pt_init_destroy_netlink(struct lws_context *context,
|
|||
|
||||
memset(&sanl, 0, sizeof(sanl));
|
||||
sanl.nl_family = AF_NETLINK;
|
||||
sanl.nl_pid = (uint32_t)getpid();
|
||||
sanl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR
|
||||
#if defined(LWS_WITH_IPV6)
|
||||
| RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR
|
||||
|
|
|
@ -60,12 +60,14 @@ lws_raw_skt_connect(struct lws *wsi)
|
|||
}
|
||||
#endif
|
||||
|
||||
n = user_callback_handle_rxflow(wsi->a.protocol->callback,
|
||||
wsi, wsi->role_ops->adoption_cb[lwsi_role_server(wsi)],
|
||||
wsi->user_space, NULL, 0);
|
||||
if (n) {
|
||||
lws_inform_client_conn_fail(wsi, (void *)"user", 4);
|
||||
return 1;
|
||||
if (!wsi->hdr_parsing_completed) {
|
||||
n = user_callback_handle_rxflow(wsi->a.protocol->callback,
|
||||
wsi, wsi->role_ops->adoption_cb[lwsi_role_server(wsi)],
|
||||
wsi->user_space, NULL, 0);
|
||||
if (n) {
|
||||
lws_inform_client_conn_fail(wsi, (void *)"user", 4);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
|
@ -172,7 +174,7 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi,
|
|||
#endif
|
||||
default:
|
||||
ebuf.token = NULL;
|
||||
ebuf.len = 0;
|
||||
ebuf.len = (int) wsi->a.protocol->rx_buffer_size;
|
||||
|
||||
buffered = lws_buflist_aware_read(pt, wsi, &ebuf, 1, __func__);
|
||||
switch (ebuf.len) {
|
||||
|
|
|
@ -943,7 +943,7 @@ rops_handle_POLLIN_ws(struct lws_context_per_thread *pt, struct lws *wsi,
|
|||
unsigned int pending = 0;
|
||||
struct lws_tokens ebuf;
|
||||
char buffered = 0;
|
||||
int n = 0, m, sanity = 10;
|
||||
int n = 0, m, sanity = 100;
|
||||
#if defined(LWS_WITH_HTTP2)
|
||||
struct lws *wsi1;
|
||||
#endif
|
||||
|
@ -1223,8 +1223,18 @@ drain:
|
|||
else
|
||||
pending = pending > wsi->a.context->pt_serv_buf_size ?
|
||||
wsi->a.context->pt_serv_buf_size : pending;
|
||||
if (--sanity)
|
||||
if (--sanity) {
|
||||
#if !defined(LWS_WITHOUT_EXTENSIONS)
|
||||
while (wsi->ws->rx_draining_ext) {
|
||||
// RX Extension needs to be drained before next read
|
||||
n = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR, 0);
|
||||
if (n < 0) {
|
||||
return LWS_HPI_RET_PLEASE_CLOSE_ME;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
goto read;
|
||||
}
|
||||
else
|
||||
/*
|
||||
* Something has gone wrong, we are spinning...
|
||||
|
|
|
@ -57,3 +57,9 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type,
|
|||
int
|
||||
lws_x509_get_crt_ext(mbedtls_x509_crt *crt, mbedtls_x509_buf *skid,
|
||||
lws_mbedtls_x509_authority *akid);
|
||||
|
||||
#if (MBEDTLS_VERSION_MAJOR == 3) && (MBEDTLS_VERSION_MINOR >= 5)
|
||||
int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
|
||||
mbedtls_x509_name *cur);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -421,24 +421,38 @@ int ssl_pm_clear(SSL *ssl)
|
|||
|
||||
int ssl_pm_read(SSL *ssl, void *buffer, int len)
|
||||
{
|
||||
int ret;
|
||||
struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
|
||||
int ret;
|
||||
struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
|
||||
|
||||
ret = mbedtls_ssl_read(&ssl_pm->ssl, buffer, (size_t)len);
|
||||
if (ret < 0) {
|
||||
// lwsl_notice("%s: mbedtls_ssl_read says -0x%x\n", __func__, -ret);
|
||||
SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_read() return -0x%x", -ret);
|
||||
if (ret == MBEDTLS_ERR_NET_CONN_RESET ||
|
||||
ret = mbedtls_ssl_read(&ssl_pm->ssl, buffer, (size_t)len);
|
||||
if (ret < 0) {
|
||||
// lwsl_notice("%s: mbedtls_ssl_read says -0x%x\n", __func__, -ret);
|
||||
SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_read() return -0x%x", -ret);
|
||||
if (ret == MBEDTLS_ERR_NET_CONN_RESET ||
|
||||
#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
ret <= MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE) /* fatal errors */
|
||||
ret <= MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE) /* fatal errors */
|
||||
#else
|
||||
ret <= MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) /* fatal errors */
|
||||
ret <= MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) /* fatal errors */
|
||||
#endif
|
||||
ssl->err = SSL_ERROR_SYSCALL;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
switch (ret) {
|
||||
case MBEDTLS_ERR_NET_CONN_RESET:
|
||||
ssl->err = SSL_ERROR_SYSCALL;
|
||||
break;
|
||||
case MBEDTLS_ERR_SSL_WANT_WRITE:
|
||||
ssl->err = SSL_ERROR_WANT_WRITE;
|
||||
break;
|
||||
case MBEDTLS_ERR_SSL_WANT_READ:
|
||||
ssl->err = SSL_ERROR_WANT_READ;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -308,7 +308,7 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi,
|
|||
flen);
|
||||
}
|
||||
#else
|
||||
ret = wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p, flen,
|
||||
ret = wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p, (long) flen,
|
||||
WOLFSSL_FILETYPE_ASN1);
|
||||
#endif
|
||||
lws_free_set_NULL(p);
|
||||
|
@ -439,7 +439,7 @@ check_key:
|
|||
lwsl_notice(" Using ECDH certificate support\n");
|
||||
|
||||
/* Get X509 certificate from ssl context */
|
||||
#if !defined(LWS_WITH_BORINGSSL)
|
||||
#if !defined(LWS_WITH_BORINGSSL) && !defined(USE_WOLFSSL)
|
||||
#if !defined(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS)
|
||||
x = sk_X509_value(vhost->tls.ssl_ctx->extra_certs, 0);
|
||||
#else
|
||||
|
@ -482,7 +482,7 @@ check_key:
|
|||
|
||||
EC_KEY_free(EC_key);
|
||||
|
||||
#if !defined(OPENSSL_NO_EC) && !defined(LWS_WITH_BORINGSSL)
|
||||
#if !defined(OPENSSL_NO_EC) && !defined(LWS_WITH_BORINGSSL) && !defined(USE_WOLFSSL)
|
||||
post_ecdh:
|
||||
#endif
|
||||
vhost->tls.skipped_certs = 0;
|
||||
|
|
|
@ -97,8 +97,9 @@ lws_context_init_ssl_library(struct lws_context *cx,
|
|||
#endif
|
||||
#endif
|
||||
if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) {
|
||||
lwsl_cx_info(cx, " SSL disabled: no "
|
||||
"LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT");
|
||||
if (!info->provided_client_ssl_ctx)
|
||||
lwsl_cx_info(cx, " SSL disabled: no "
|
||||
"LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,11 +47,13 @@ lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as)
|
|||
memset(&t, 0, sizeof(t));
|
||||
|
||||
if (strlen(p) == 13) {
|
||||
t.tm_year = (dec(p[0]) * 10) + dec(p[1]) + 100;
|
||||
t.tm_year = (dec(p[0]) * 10) + dec(p[1]);
|
||||
if (t.tm_year < 50) /* RFC5280: 13 char dates will break after 2049 */
|
||||
t.tm_year += 100; /* struct tm year is -1900, this gives 2000..2049 */
|
||||
p += 2;
|
||||
} else {
|
||||
t.tm_year = (dec(p[0]) * 1000) + (dec(p[1]) * 100) +
|
||||
(dec(p[2]) * 10) + dec(p[3]);
|
||||
t.tm_year = ((dec(p[0]) * 1000) + (dec(p[1]) * 100) +
|
||||
(dec(p[2]) * 10) + dec(p[3])) - 1900; /* struct tm year is -1900 */
|
||||
p += 4;
|
||||
}
|
||||
t.tm_mon = (dec(p[0]) * 10) + dec(p[1]) - 1;
|
||||
|
|
|
@ -138,9 +138,6 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info,
|
|||
if (info->client_ssl_ca_filepath)
|
||||
ca_filepath = info->client_ssl_ca_filepath;
|
||||
|
||||
if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
|
||||
return 0;
|
||||
|
||||
if (vhost->tls.ssl_client_ctx)
|
||||
return 0;
|
||||
|
||||
|
@ -155,6 +152,9 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
|
||||
return 0;
|
||||
|
||||
if (lws_tls_client_create_vhost_context(vhost, info, cipher_list,
|
||||
ca_filepath,
|
||||
info->client_ssl_ca_mem,
|
||||
|
|
|
@ -34,7 +34,7 @@ lws_tls_session_tag_discrete(const char *vhname, const char *host,
|
|||
* different client certs.
|
||||
*/
|
||||
|
||||
lws_snprintf(buf, len, "%s_%s_%u", vhname, host, port);
|
||||
lws_snprintf(buf, len, "%s_%s_%u", vhname, host, (unsigned int)port);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -4477,7 +4477,11 @@ static const uint8_t
|
|||
w26[] = { 0xF9, 0x3E, 0x00 },
|
||||
w27[] = { 0xFB, 0x3F, 0xF1, 0xF7, 0xCE, 0xD9, 0x16, 0x87, 0x2B },
|
||||
w28[] = { 0xA2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03 },
|
||||
w29[] = { 0x7F, 0x65, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0xFF
|
||||
w29[] = { 0x7F, 0x65, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0xFF },
|
||||
w30[] = { 0xA2, 0x63, 0x67, 0x68, 0x69, 0x18, 0x7B, 0x63, 0x6A, 0x6B, 0x6C, 0x02 },
|
||||
w31[] = { 0x82, 0x18, 0x81, 0x19, 0x04, 0x00 },
|
||||
w32[] = { 0xA2, 0x63, 0x67, 0x68, 0x69, 0x38, 0x7A, 0x63, 0x6A, 0x6B, 0x6C, 0x02 },
|
||||
w33[] = { 0x82, 0x38, 0x80, 0x39, 0x03, 0xFF
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -4604,7 +4608,7 @@ int main(int argc, const char **argv)
|
|||
{
|
||||
int n, m, e = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE,
|
||||
expected = (int)LWS_ARRAY_SIZE(cbor_tests) +
|
||||
29 /* <-- how many write tests */;
|
||||
33 /* <-- how many write tests */;
|
||||
struct lecp_ctx ctx;
|
||||
const char *p;
|
||||
|
||||
|
@ -5000,6 +5004,50 @@ int main(int argc, const char **argv)
|
|||
e++;
|
||||
} else
|
||||
pass++;
|
||||
|
||||
lwsl_user("%s: test30\n", __func__);
|
||||
lws_lec_setbuf(&ctx, buf, sizeof(buf));
|
||||
|
||||
if (lws_lec_printf(&ctx, "{'ghi':123,'jkl':2}") !=
|
||||
LWS_LECPCTX_RET_FINISHED ||
|
||||
ctx.used != sizeof(w30) || memcmp(w30, buf, ctx.used)) {
|
||||
lwsl_hexdump_notice(ctx.start, ctx.used);
|
||||
e++;
|
||||
} else
|
||||
pass++;
|
||||
|
||||
lwsl_user("%s: test31\n", __func__);
|
||||
lws_lec_setbuf(&ctx, buf, sizeof(buf));
|
||||
|
||||
if (lws_lec_printf(&ctx, "[129,1024]") !=
|
||||
LWS_LECPCTX_RET_FINISHED ||
|
||||
ctx.used != sizeof(w31) || memcmp(w31, buf, ctx.used)) {
|
||||
lwsl_hexdump_notice(ctx.start, ctx.used);
|
||||
e++;
|
||||
} else
|
||||
pass++;
|
||||
|
||||
lwsl_user("%s: test32\n", __func__);
|
||||
lws_lec_setbuf(&ctx, buf, sizeof(buf));
|
||||
|
||||
if (lws_lec_printf(&ctx, "{'ghi':-123,'jkl':2}") !=
|
||||
LWS_LECPCTX_RET_FINISHED ||
|
||||
ctx.used != sizeof(w32) || memcmp(w32, buf, ctx.used)) {
|
||||
lwsl_hexdump_notice(ctx.start, ctx.used);
|
||||
e++;
|
||||
} else
|
||||
pass++;
|
||||
|
||||
lwsl_user("%s: test33\n", __func__);
|
||||
lws_lec_setbuf(&ctx, buf, sizeof(buf));
|
||||
|
||||
if (lws_lec_printf(&ctx, "[-129,-1024]") !=
|
||||
LWS_LECPCTX_RET_FINISHED ||
|
||||
ctx.used != sizeof(w33) || memcmp(w33, buf, ctx.used)) {
|
||||
lwsl_hexdump_notice(ctx.start, ctx.used);
|
||||
e++;
|
||||
} else
|
||||
pass++;
|
||||
}
|
||||
|
||||
if (e)
|
||||
|
|
|
@ -127,6 +127,10 @@ static const char * const json_tests[] = {
|
|||
|
||||
"{" /* SHOULD_FAIL: test 10, missing open */
|
||||
"\"a\":123,\"b\":}"
|
||||
"}",
|
||||
|
||||
"{" /* test 13: float vs int */
|
||||
"\"a\": 1, \"b\": 1.0, \"c\": 1e-3, \"d\": 1e3"
|
||||
"}"
|
||||
};
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
uint8_t buf[1280];
|
||||
union lws_tls_cert_info_results *ci =
|
||||
(union lws_tls_cert_info_results *)buf;
|
||||
#if defined(LWS_HAVE_CTIME_R)
|
||||
#if defined(LWS_HAVE_CTIME_R) && !defined(LWS_WITH_NO_LOGS)
|
||||
char date[32];
|
||||
#endif
|
||||
|
||||
|
|
|
@ -244,6 +244,10 @@ wsi_logical_close_custom(struct lws *wsi)
|
|||
{
|
||||
struct pt_eventlibs_custom *priv = (struct pt_eventlibs_custom *)
|
||||
lws_evlib_wsi_to_evlib_pt(wsi);
|
||||
|
||||
if (lws_get_socket_fd(wsi) == LWS_SOCK_INVALID)
|
||||
return 0;
|
||||
|
||||
return custom_poll_del_fd(priv->io_loop, lws_get_socket_fd(wsi));
|
||||
}
|
||||
|
||||
|
|
|
@ -1125,8 +1125,10 @@ pkt_add_hdrs:
|
|||
goto pkt_add_hdrs;
|
||||
|
||||
case ACME_STATE_POLLING_CSR:
|
||||
if (ac->goes_around)
|
||||
break;
|
||||
if (ac->goes_around) {
|
||||
strcpy(ac->active_url, ac->order_url);
|
||||
goto pkt_add_hdrs;
|
||||
}
|
||||
lwsl_vhost_notice(vhd->vhost, "Generating ACME CSR... may take a little while");
|
||||
p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "{\"csr\":\"");
|
||||
n = lws_tls_acme_sni_csr_create(vhd->context,
|
||||
|
@ -1396,7 +1398,7 @@ poll_again:
|
|||
lws_acme_report_status(vhd->vhost, LWS_CUS_CHALLENGE,
|
||||
NULL);
|
||||
|
||||
if (ac->goes_around++ == 20) {
|
||||
if (ac->goes_around++ == 200) {
|
||||
lwsl_notice("%s: too many chall retries\n",
|
||||
__func__);
|
||||
|
||||
|
@ -1470,13 +1472,13 @@ poll_again:
|
|||
goto failed;
|
||||
}
|
||||
|
||||
if (ac->resp != 200) {
|
||||
if (ac->goes_around++ == 30) {
|
||||
if (ac->resp != 200 || ac->cert_url[0] == '\0') {
|
||||
if (ac->goes_around++ == 200) {
|
||||
lwsl_vhost_warn(vhd->vhost, "Too many retries");
|
||||
|
||||
goto failed;
|
||||
}
|
||||
strcpy(buf, ac->finalize_url);
|
||||
strcpy(buf, ac->order_url);
|
||||
cwsi = lws_acme_client_connect(vhd->context,
|
||||
vhd->vhost,
|
||||
&ac->cwsi, &ac->i, buf,
|
||||
|
|
|
@ -163,7 +163,6 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2))
|
|||
set_property(
|
||||
TARGET test-server-extpoll
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
LWS_WITH_EXTERNAL_POLL
|
||||
INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share"
|
||||
)
|
||||
|
||||
|
|
|
@ -720,8 +720,9 @@ int flush;
|
|||
if (copy > have) copy = have;
|
||||
if (copy) {
|
||||
if (state->head != Z_NULL &&
|
||||
state->head->extra != Z_NULL) {
|
||||
len = state->head->extra_len - state->length;
|
||||
state->head->extra != Z_NULL &&
|
||||
(len = state->head->extra_len - state->length) <
|
||||
state->head->extra_max) {
|
||||
zmemcpy(state->head->extra + len, next,
|
||||
len + copy > state->head->extra_max ?
|
||||
state->head->extra_max - len : copy);
|
||||
|
|
|
@ -1,330 +1,328 @@
|
|||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||
* Copyright (C) 1995-2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
|
||||
#define MAXBITS 15
|
||||
|
||||
const char inflate_copyright[] =
|
||||
" inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
include such an acknowledgment, I would appreciate that you keep this
|
||||
copyright string in the executable of your product.
|
||||
*/
|
||||
|
||||
/*
|
||||
Build a set of tables to decode the provided canonical Huffman code.
|
||||
The code lengths are lens[0..codes-1]. The result starts at *table,
|
||||
whose indices are 0..2^bits-1. work is a writable array of at least
|
||||
lens shorts, which is used as a work area. type is the type of code
|
||||
to be generated, CODES, LENS, or DISTS. On return, zero is success,
|
||||
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
|
||||
on return points to the next available entry's address. bits is the
|
||||
requested root table index bits, and on return it is the actual root
|
||||
table index bits. It will differ if the request is greater than the
|
||||
longest code or if it is less than the shortest code.
|
||||
*/
|
||||
int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
|
||||
codetype type;
|
||||
unsigned short FAR *lens;
|
||||
unsigned codes;
|
||||
code FAR * FAR *table;
|
||||
unsigned FAR *bits;
|
||||
unsigned short FAR *work;
|
||||
{
|
||||
unsigned len; /* a code's length in bits */
|
||||
unsigned sym; /* index of code symbols */
|
||||
unsigned min, max; /* minimum and maximum code lengths */
|
||||
unsigned root; /* number of index bits for root table */
|
||||
unsigned curr; /* number of index bits for current table */
|
||||
unsigned drop; /* code bits to drop for sub-table */
|
||||
int left; /* number of prefix codes available */
|
||||
unsigned used; /* code entries in table used */
|
||||
unsigned huff; /* Huffman code */
|
||||
unsigned incr; /* for incrementing code, index */
|
||||
unsigned fill; /* index for replicating entries */
|
||||
unsigned low; /* low bits for current root entry */
|
||||
unsigned mask; /* mask for low root bits */
|
||||
code here; /* table entry for duplication */
|
||||
code FAR *next; /* next available space in table */
|
||||
const unsigned short FAR *base; /* base value table to use */
|
||||
const unsigned short FAR *extra; /* extra bits table to use */
|
||||
int end; /* use base and extra for symbol > end */
|
||||
unsigned short count[MAXBITS+1]; /* number of codes of each length */
|
||||
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
|
||||
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
|
||||
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
8193, 12289, 16385, 24577, 0, 0};
|
||||
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
|
||||
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
|
||||
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
|
||||
28, 28, 29, 29, 64, 64};
|
||||
|
||||
/*
|
||||
Process a set of code lengths to create a canonical Huffman code. The
|
||||
code lengths are lens[0..codes-1]. Each length corresponds to the
|
||||
symbols 0..codes-1. The Huffman code is generated by first sorting the
|
||||
symbols by length from short to long, and retaining the symbol order
|
||||
for codes with equal lengths. Then the code starts with all zero bits
|
||||
for the first code of the shortest length, and the codes are integer
|
||||
increments for the same length, and zeros are appended as the length
|
||||
increases. For the deflate format, these bits are stored backwards
|
||||
from their more natural integer increment ordering, and so when the
|
||||
decoding tables are built in the large loop below, the integer codes
|
||||
are incremented backwards.
|
||||
|
||||
This routine assumes, but does not check, that all of the entries in
|
||||
lens[] are in the range 0..MAXBITS. The caller must assure this.
|
||||
1..MAXBITS is interpreted as that code length. zero means that that
|
||||
symbol does not occur in this code.
|
||||
|
||||
The codes are sorted by computing a count of codes for each length,
|
||||
creating from that a table of starting indices for each length in the
|
||||
sorted table, and then entering the symbols in order in the sorted
|
||||
table. The sorted table is work[], with that space being provided by
|
||||
the caller.
|
||||
|
||||
The length counts are used for other purposes as well, i.e. finding
|
||||
the minimum and maximum length codes, determining if there are any
|
||||
codes at all, checking for a valid set of lengths, and looking ahead
|
||||
at length counts to determine sub-table sizes when building the
|
||||
decoding tables.
|
||||
*/
|
||||
|
||||
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
|
||||
for (len = 0; len <= MAXBITS; len++)
|
||||
count[len] = 0;
|
||||
for (sym = 0; sym < codes; sym++)
|
||||
count[lens[sym]]++;
|
||||
|
||||
/* bound code lengths, force root to be within code lengths */
|
||||
root = *bits;
|
||||
for (max = MAXBITS; max >= 1; max--)
|
||||
if (count[max] != 0) break;
|
||||
if (root > max) root = max;
|
||||
if (max == 0) { /* no symbols to code at all */
|
||||
here.op = (unsigned char)64; /* invalid code marker */
|
||||
here.bits = (unsigned char)1;
|
||||
here.val = (unsigned short)0;
|
||||
*(*table)++ = here; /* make a table to force an error */
|
||||
*(*table)++ = here;
|
||||
*bits = 1;
|
||||
return 0; /* no symbols, but wait for decoding to report error */
|
||||
}
|
||||
for (min = 1; min < max; min++)
|
||||
if (count[min] != 0) break;
|
||||
if (root < min) root = min;
|
||||
|
||||
/* check for an over-subscribed or incomplete set of lengths */
|
||||
left = 1;
|
||||
for (len = 1; len <= MAXBITS; len++) {
|
||||
left <<= 1;
|
||||
left -= count[len];
|
||||
if (left < 0) return -1; /* over-subscribed */
|
||||
}
|
||||
if (left > 0 && (type == CODES || max != 1))
|
||||
return -1; /* incomplete set */
|
||||
|
||||
/* generate offsets into symbol table for each length for sorting */
|
||||
offs[1] = 0;
|
||||
for (len = 1; len < MAXBITS; len++)
|
||||
offs[len + 1] = offs[len] + count[len];
|
||||
|
||||
/* sort symbols by length, by symbol order within each length */
|
||||
for (sym = 0; sym < codes; sym++)
|
||||
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
|
||||
|
||||
/*
|
||||
Create and fill in decoding tables. In this loop, the table being
|
||||
filled is at next and has curr index bits. The code being used is huff
|
||||
with length len. That code is converted to an index by dropping drop
|
||||
bits off of the bottom. For codes where len is less than drop + curr,
|
||||
those top drop + curr - len bits are incremented through all values to
|
||||
fill the table with replicated entries.
|
||||
|
||||
root is the number of index bits for the root table. When len exceeds
|
||||
root, sub-tables are created pointed to by the root entry with an index
|
||||
of the low root bits of huff. This is saved in low to check for when a
|
||||
new sub-table should be started. drop is zero when the root table is
|
||||
being filled, and drop is root when sub-tables are being filled.
|
||||
|
||||
When a new sub-table is needed, it is necessary to look ahead in the
|
||||
code lengths to determine what size sub-table is needed. The length
|
||||
counts are used for this, and so count[] is decremented as codes are
|
||||
entered in the tables.
|
||||
|
||||
used keeps track of how many table entries have been allocated from the
|
||||
provided *table space. It is checked for LENS and DIST tables against
|
||||
the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
|
||||
the initial root table size constants. See the comments in inftrees.h
|
||||
for more information.
|
||||
|
||||
sym increments through all symbols, and the loop terminates when
|
||||
all codes of length max, i.e. all codes, have been processed. This
|
||||
routine permits incomplete codes, so another loop after this one fills
|
||||
in the rest of the decoding tables with invalid code markers.
|
||||
*/
|
||||
|
||||
/* set up for code type */
|
||||
switch (type) {
|
||||
case CODES:
|
||||
base = extra = work; /* dummy value--not used */
|
||||
end = 19;
|
||||
break;
|
||||
case LENS:
|
||||
base = lbase;
|
||||
base -= 257;
|
||||
extra = lext;
|
||||
extra -= 257;
|
||||
end = 256;
|
||||
break;
|
||||
default: /* DISTS */
|
||||
base = dbase;
|
||||
extra = dext;
|
||||
end = -1;
|
||||
}
|
||||
|
||||
/* initialize state for loop */
|
||||
huff = 0; /* starting code */
|
||||
sym = 0; /* starting code symbol */
|
||||
len = min; /* starting code length */
|
||||
next = *table; /* current table to fill in */
|
||||
curr = root; /* current table index bits */
|
||||
drop = 0; /* current bits to drop from code for index */
|
||||
low = (unsigned)(-1); /* trigger new sub-table when len > root */
|
||||
used = 1U << root; /* use root table entries */
|
||||
mask = used - 1; /* mask for comparing low */
|
||||
|
||||
/* check available table space */
|
||||
if ((type == LENS && used >= ENOUGH_LENS) ||
|
||||
(type == DISTS && used >= ENOUGH_DISTS))
|
||||
return 1;
|
||||
|
||||
/* process all codes and make table entries */
|
||||
for (;;) {
|
||||
/* create table entry */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
if ((int)(work[sym]) < end) {
|
||||
here.op = (unsigned char)0;
|
||||
here.val = work[sym];
|
||||
}
|
||||
else if ((int)(work[sym]) > end) {
|
||||
here.op = (unsigned char)(extra[work[sym]]);
|
||||
here.val = base[work[sym]];
|
||||
}
|
||||
else {
|
||||
here.op = (unsigned char)(32 + 64); /* end of block */
|
||||
here.val = 0;
|
||||
}
|
||||
|
||||
/* replicate for those indices with low len bits equal to huff */
|
||||
incr = 1U << (len - drop);
|
||||
fill = 1U << curr;
|
||||
min = fill; /* save offset to next table */
|
||||
do {
|
||||
fill -= incr;
|
||||
next[(huff >> drop) + fill] = here;
|
||||
} while (fill != 0);
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
|
||||
/* go to next symbol, update count, len */
|
||||
sym++;
|
||||
if (--(count[len]) == 0) {
|
||||
if (len == max) break;
|
||||
len = lens[work[sym]];
|
||||
}
|
||||
|
||||
/* create new sub-table if needed */
|
||||
if (len > root && (huff & mask) != low) {
|
||||
/* if first time, transition to sub-tables */
|
||||
if (drop == 0)
|
||||
drop = root;
|
||||
|
||||
/* increment past last table */
|
||||
next += min; /* here min is 1 << curr */
|
||||
|
||||
/* determine length of next table */
|
||||
curr = len - drop;
|
||||
left = (int)(1 << curr);
|
||||
while (curr + drop < max) {
|
||||
left -= count[curr + drop];
|
||||
if (left <= 0) break;
|
||||
curr++;
|
||||
left <<= 1;
|
||||
}
|
||||
|
||||
/* check for enough space */
|
||||
used += 1U << curr;
|
||||
if ((type == LENS && used >= ENOUGH_LENS) ||
|
||||
(type == DISTS && used >= ENOUGH_DISTS))
|
||||
return 1;
|
||||
|
||||
/* point entry in root table to sub-table */
|
||||
low = huff & mask;
|
||||
(*table)[low].op = (unsigned char)curr;
|
||||
(*table)[low].bits = (unsigned char)root;
|
||||
(*table)[low].val = (unsigned short)(next - *table);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Fill in rest of table for incomplete codes. This loop is similar to the
|
||||
loop above in incrementing huff for table indices. It is assumed that
|
||||
len is equal to curr + drop, so there is no loop needed to increment
|
||||
through high index bits. When the current sub-table is filled, the loop
|
||||
drops back to the root table to fill in any remaining entries there.
|
||||
*/
|
||||
here.op = (unsigned char)64; /* invalid code marker */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
here.val = (unsigned short)0;
|
||||
while (huff != 0) {
|
||||
/* when done with sub-table, drop back to root table */
|
||||
if (drop != 0 && (huff & mask) != low) {
|
||||
drop = 0;
|
||||
len = root;
|
||||
next = *table;
|
||||
here.bits = (unsigned char)len;
|
||||
}
|
||||
|
||||
/* put invalid code marker in table */
|
||||
next[huff >> drop] = here;
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
}
|
||||
|
||||
/* set return parameters */
|
||||
*table += used;
|
||||
*bits = root;
|
||||
return 0;
|
||||
}
|
||||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||
* Copyright (C) 1995-2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
|
||||
#define MAXBITS 15
|
||||
|
||||
const char inflate_copyright[] =
|
||||
" inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
include such an acknowledgment, I would appreciate that you keep this
|
||||
copyright string in the executable of your product.
|
||||
*/
|
||||
|
||||
/*
|
||||
Build a set of tables to decode the provided canonical Huffman code.
|
||||
The code lengths are lens[0..codes-1]. The result starts at *table,
|
||||
whose indices are 0..2^bits-1. work is a writable array of at least
|
||||
lens shorts, which is used as a work area. type is the type of code
|
||||
to be generated, CODES, LENS, or DISTS. On return, zero is success,
|
||||
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
|
||||
on return points to the next available entry's address. bits is the
|
||||
requested root table index bits, and on return it is the actual root
|
||||
table index bits. It will differ if the request is greater than the
|
||||
longest code or if it is less than the shortest code.
|
||||
*/
|
||||
int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
|
||||
codetype type;
|
||||
unsigned short FAR *lens;
|
||||
unsigned codes;
|
||||
code FAR * FAR *table;
|
||||
unsigned FAR *bits;
|
||||
unsigned short FAR *work;
|
||||
{
|
||||
unsigned len; /* a code's length in bits */
|
||||
unsigned sym; /* index of code symbols */
|
||||
unsigned min, max; /* minimum and maximum code lengths */
|
||||
unsigned root; /* number of index bits for root table */
|
||||
unsigned curr; /* number of index bits for current table */
|
||||
unsigned drop; /* code bits to drop for sub-table */
|
||||
int left; /* number of prefix codes available */
|
||||
unsigned used; /* code entries in table used */
|
||||
unsigned huff; /* Huffman code */
|
||||
unsigned incr; /* for incrementing code, index */
|
||||
unsigned fill; /* index for replicating entries */
|
||||
unsigned low; /* low bits for current root entry */
|
||||
unsigned mask; /* mask for low root bits */
|
||||
code here; /* table entry for duplication */
|
||||
code FAR *next; /* next available space in table */
|
||||
const unsigned short FAR *base; /* base value table to use */
|
||||
const unsigned short FAR *extra; /* extra bits table to use */
|
||||
unsigned match; /* use base and extra for symbol >= match */
|
||||
unsigned short count[MAXBITS+1]; /* number of codes of each length */
|
||||
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
|
||||
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
|
||||
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
8193, 12289, 16385, 24577, 0, 0};
|
||||
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
|
||||
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
|
||||
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
|
||||
28, 28, 29, 29, 64, 64};
|
||||
|
||||
/*
|
||||
Process a set of code lengths to create a canonical Huffman code. The
|
||||
code lengths are lens[0..codes-1]. Each length corresponds to the
|
||||
symbols 0..codes-1. The Huffman code is generated by first sorting the
|
||||
symbols by length from short to long, and retaining the symbol order
|
||||
for codes with equal lengths. Then the code starts with all zero bits
|
||||
for the first code of the shortest length, and the codes are integer
|
||||
increments for the same length, and zeros are appended as the length
|
||||
increases. For the deflate format, these bits are stored backwards
|
||||
from their more natural integer increment ordering, and so when the
|
||||
decoding tables are built in the large loop below, the integer codes
|
||||
are incremented backwards.
|
||||
|
||||
This routine assumes, but does not check, that all of the entries in
|
||||
lens[] are in the range 0..MAXBITS. The caller must assure this.
|
||||
1..MAXBITS is interpreted as that code length. zero means that that
|
||||
symbol does not occur in this code.
|
||||
|
||||
The codes are sorted by computing a count of codes for each length,
|
||||
creating from that a table of starting indices for each length in the
|
||||
sorted table, and then entering the symbols in order in the sorted
|
||||
table. The sorted table is work[], with that space being provided by
|
||||
the caller.
|
||||
|
||||
The length counts are used for other purposes as well, i.e. finding
|
||||
the minimum and maximum length codes, determining if there are any
|
||||
codes at all, checking for a valid set of lengths, and looking ahead
|
||||
at length counts to determine sub-table sizes when building the
|
||||
decoding tables.
|
||||
*/
|
||||
|
||||
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
|
||||
for (len = 0; len <= MAXBITS; len++)
|
||||
count[len] = 0;
|
||||
for (sym = 0; sym < codes; sym++)
|
||||
count[lens[sym]]++;
|
||||
|
||||
/* bound code lengths, force root to be within code lengths */
|
||||
root = *bits;
|
||||
for (max = MAXBITS; max >= 1; max--)
|
||||
if (count[max] != 0) break;
|
||||
if (root > max) root = max;
|
||||
if (max == 0) { /* no symbols to code at all */
|
||||
here.op = (unsigned char)64; /* invalid code marker */
|
||||
here.bits = (unsigned char)1;
|
||||
here.val = (unsigned short)0;
|
||||
*(*table)++ = here; /* make a table to force an error */
|
||||
*(*table)++ = here;
|
||||
*bits = 1;
|
||||
return 0; /* no symbols, but wait for decoding to report error */
|
||||
}
|
||||
for (min = 1; min < max; min++)
|
||||
if (count[min] != 0) break;
|
||||
if (root < min) root = min;
|
||||
|
||||
/* check for an over-subscribed or incomplete set of lengths */
|
||||
left = 1;
|
||||
for (len = 1; len <= MAXBITS; len++) {
|
||||
left <<= 1;
|
||||
left -= count[len];
|
||||
if (left < 0) return -1; /* over-subscribed */
|
||||
}
|
||||
if (left > 0 && (type == CODES || max != 1))
|
||||
return -1; /* incomplete set */
|
||||
|
||||
/* generate offsets into symbol table for each length for sorting */
|
||||
offs[1] = 0;
|
||||
for (len = 1; len < MAXBITS; len++)
|
||||
offs[len + 1] = offs[len] + count[len];
|
||||
|
||||
/* sort symbols by length, by symbol order within each length */
|
||||
for (sym = 0; sym < codes; sym++)
|
||||
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
|
||||
|
||||
/*
|
||||
Create and fill in decoding tables. In this loop, the table being
|
||||
filled is at next and has curr index bits. The code being used is huff
|
||||
with length len. That code is converted to an index by dropping drop
|
||||
bits off of the bottom. For codes where len is less than drop + curr,
|
||||
those top drop + curr - len bits are incremented through all values to
|
||||
fill the table with replicated entries.
|
||||
|
||||
root is the number of index bits for the root table. When len exceeds
|
||||
root, sub-tables are created pointed to by the root entry with an index
|
||||
of the low root bits of huff. This is saved in low to check for when a
|
||||
new sub-table should be started. drop is zero when the root table is
|
||||
being filled, and drop is root when sub-tables are being filled.
|
||||
|
||||
When a new sub-table is needed, it is necessary to look ahead in the
|
||||
code lengths to determine what size sub-table is needed. The length
|
||||
counts are used for this, and so count[] is decremented as codes are
|
||||
entered in the tables.
|
||||
|
||||
used keeps track of how many table entries have been allocated from the
|
||||
provided *table space. It is checked for LENS and DIST tables against
|
||||
the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
|
||||
the initial root table size constants. See the comments in inftrees.h
|
||||
for more information.
|
||||
|
||||
sym increments through all symbols, and the loop terminates when
|
||||
all codes of length max, i.e. all codes, have been processed. This
|
||||
routine permits incomplete codes, so another loop after this one fills
|
||||
in the rest of the decoding tables with invalid code markers.
|
||||
*/
|
||||
|
||||
/* set up for code type */
|
||||
switch (type) {
|
||||
case CODES:
|
||||
base = extra = work; /* dummy value--not used */
|
||||
match = 20;
|
||||
break;
|
||||
case LENS:
|
||||
base = lbase;
|
||||
extra = lext;
|
||||
match = 257;
|
||||
break;
|
||||
default: /* DISTS */
|
||||
base = dbase;
|
||||
extra = dext;
|
||||
match = 0;
|
||||
}
|
||||
|
||||
/* initialize state for loop */
|
||||
huff = 0; /* starting code */
|
||||
sym = 0; /* starting code symbol */
|
||||
len = min; /* starting code length */
|
||||
next = *table; /* current table to fill in */
|
||||
curr = root; /* current table index bits */
|
||||
drop = 0; /* current bits to drop from code for index */
|
||||
low = (unsigned)(-1); /* trigger new sub-table when len > root */
|
||||
used = 1U << root; /* use root table entries */
|
||||
mask = used - 1; /* mask for comparing low */
|
||||
|
||||
/* check available table space */
|
||||
if ((type == LENS && used >= ENOUGH_LENS) ||
|
||||
(type == DISTS && used >= ENOUGH_DISTS))
|
||||
return 1;
|
||||
|
||||
/* process all codes and make table entries */
|
||||
for (;;) {
|
||||
/* create table entry */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
if (work[sym] + 1 < match) {
|
||||
here.op = (unsigned char)0;
|
||||
here.val = work[sym];
|
||||
}
|
||||
else if (work[sym] >= match) {
|
||||
here.op = (unsigned char)(extra[work[sym] - match]);
|
||||
here.val = base[work[sym] - match];
|
||||
}
|
||||
else {
|
||||
here.op = (unsigned char)(32 + 64); /* end of block */
|
||||
here.val = 0;
|
||||
}
|
||||
|
||||
/* replicate for those indices with low len bits equal to huff */
|
||||
incr = 1U << (len - drop);
|
||||
fill = 1U << curr;
|
||||
min = fill; /* save offset to next table */
|
||||
do {
|
||||
fill -= incr;
|
||||
next[(huff >> drop) + fill] = here;
|
||||
} while (fill != 0);
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
|
||||
/* go to next symbol, update count, len */
|
||||
sym++;
|
||||
if (--(count[len]) == 0) {
|
||||
if (len == max) break;
|
||||
len = lens[work[sym]];
|
||||
}
|
||||
|
||||
/* create new sub-table if needed */
|
||||
if (len > root && (huff & mask) != low) {
|
||||
/* if first time, transition to sub-tables */
|
||||
if (drop == 0)
|
||||
drop = root;
|
||||
|
||||
/* increment past last table */
|
||||
next += min; /* here min is 1 << curr */
|
||||
|
||||
/* determine length of next table */
|
||||
curr = len - drop;
|
||||
left = (int)(1 << curr);
|
||||
while (curr + drop < max) {
|
||||
left -= count[curr + drop];
|
||||
if (left <= 0) break;
|
||||
curr++;
|
||||
left <<= 1;
|
||||
}
|
||||
|
||||
/* check for enough space */
|
||||
used += 1U << curr;
|
||||
if ((type == LENS && used >= ENOUGH_LENS) ||
|
||||
(type == DISTS && used >= ENOUGH_DISTS))
|
||||
return 1;
|
||||
|
||||
/* point entry in root table to sub-table */
|
||||
low = huff & mask;
|
||||
(*table)[low].op = (unsigned char)curr;
|
||||
(*table)[low].bits = (unsigned char)root;
|
||||
(*table)[low].val = (unsigned short)(next - *table);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Fill in rest of table for incomplete codes. This loop is similar to the
|
||||
loop above in incrementing huff for table indices. It is assumed that
|
||||
len is equal to curr + drop, so there is no loop needed to increment
|
||||
through high index bits. When the current sub-table is filled, the loop
|
||||
drops back to the root table to fill in any remaining entries there.
|
||||
*/
|
||||
here.op = (unsigned char)64; /* invalid code marker */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
here.val = (unsigned short)0;
|
||||
while (huff != 0) {
|
||||
/* when done with sub-table, drop back to root table */
|
||||
if (drop != 0 && (huff & mask) != low) {
|
||||
drop = 0;
|
||||
len = root;
|
||||
next = *table;
|
||||
here.bits = (unsigned char)len;
|
||||
}
|
||||
|
||||
/* put invalid code marker in table */
|
||||
next[huff >> drop] = here;
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
}
|
||||
|
||||
/* set return parameters */
|
||||
*table += used;
|
||||
*bits = root;
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue