Compare commits

...
Sign in to create a new pull request.

44 commits

Author SHA1 Message Date
Cory McWilliams
fff2bb5b21 Subject: Mismatched lws_zalloc / free 2017-08-17 07:33:54 +08:00
Andy Green
12a00ea821 docs: swap _all_protocol_vhost cut and paste
https://github.com/warmcat/libwebsockets/issues/989
2017-08-16 15:23:08 +08:00
Andy Green
e99d725e76 ah: reuse at end of transaction has no timeout
If we complete a transaction but end up keeping the ah, we must force
a timeout on it.  Otherwise a bad bot could keep the socket open and
exhaust the ah pool.
2017-08-15 08:06:32 +08:00
lnmx
dc4323f837 send content-type when LWS_WITH_RANGES=OFF
https://github.com/warmcat/libwebsockets/pull/987

With the RANGES feature disabled, lws_serve_http_file would
not add the content-type header to the response.
2017-08-12 20:55:14 +08:00
Andy Green
ffbefebc24 lwsws: remove no longer extant D option from help string
https://github.com/warmcat/libwebsockets/issues/986
2017-08-09 07:44:19 +08:00
Andy Green
4cca86926f v2.2.2 2017-07-19 01:05:49 +08:00
Andy Green
31b1029234 LWS_WITH_NO_LOGS: take care about unused array for log generation 2017-06-09 21:48:03 +08:00
Leonardo Maccari Rufino
5a473e0dc3 Subject: Support to IPv6 on Windows 2017-06-01 06:57:59 +08:00
Sergey Kovalevich
2e8c0256c0 Subject: Fixed value of LIBWEBSOCKETS_LIBRARIES_STATIC 2017-05-30 09:02:48 +08:00
Sergey Kovalevich
a64bdff642 Subject: Fixed build in scope of a project (add_subdirectory) 2017-05-30 09:02:45 +08:00
Petar Paradzik
a5463053e8 Subject: libuv: Fix closing handle multiple times
Sometimes "Assertion failed: !uv__is_closing(handle)" happens because
handle is being closed multiple times. To fix this, "uv_is_closing"
is added before calling "uv_close".

Signed-off-by: Petar Paradzik <petar.paradzik@sartura.hr>
2017-05-23 23:50:04 +08:00
Andy Green
7a8741ec0b LICENSE: clarify exceptions also apply to LGPL self-refernences
via Mike Atamas, Counsel for Epic Games
2017-05-19 09:27:54 +08:00
Andy Green
fe45fe1860 plugin-standalone: refactor cmake part to ease multiple sources 2017-05-06 06:40:23 +08:00
Andy Green
f6facad476 non-ssl: return 0 on pending
https://github.com/warmcat/libwebsockets/issues/887
2017-05-03 21:25:23 +08:00
Andy Green
ccecbb99ab snprintf: move contributed ssl patch to lws_snprintf 2017-05-03 20:26:58 +08:00
Andy Green
a68539492f mings: adjust plugin export name gen 2017-04-28 11:47:21 +08:00
Andy Green
36239951be mingw: use win32 plugin names 2017-04-28 10:14:40 +08:00
Andy Green
786e6dbf35 mingw: updates 2017-04-28 07:51:34 +08:00
Martin Milata
2238857ea4 Subject: ssl: stop spinning on close 2017-04-19 20:53:51 +08:00
dspname
2d6fd20c60 windows: constify first arg of plat fops open
https://github.com/warmcat/libwebsockets/issues/871
2017-04-19 20:41:57 +08:00
Andy Green
ba16f5172c windows: align choked trunc checking with unix 2017-04-18 15:18:14 +08:00
Gecko
2977272f0e Subject: Save copy of ah pointer even with WS client so that HTTP
error can be captured by calling lws_http_client_http_response.
2017-04-10 12:38:35 +08:00
Andy Green
6da41353ce boilerplate: add back missing Lesser that cut-and-pasted itself around 2017-04-06 23:12:30 +08:00
Martin Milata
8d511c834f Subject: ssl: fix OpenSSL client method detection 2017-04-06 23:12:11 +08:00
Andy Green
8e2fe3f12b ssl: OpenSSL v1.1 deprecated TLSv1_2_client_method 2017-04-06 08:51:17 +08:00
Andy Green
be333ac420 pollout: handle request for pollout during pollout service 2017-04-05 08:30:04 +08:00
Renyaow
89ad5714d6 windows: _snprintf_s
https://github.com/warmcat/libwebsockets/issues/859
2017-04-05 02:05:01 +08:00
Andy Green
a36ca4dc08 logs: reduce ah err to info 2017-04-02 13:02:28 +08:00
paularmitt
db26ccc38b windows: need LWS_INLINE 2017-03-31 19:59:50 +08:00
Olivier Basson
6f13ccf7c3 ev: stop event listeners during context destroy
I think I've found a bug in libev backend, in function lws_libev_io(). I'm using latest version from master branch.

When deleting a context with active connections via lws_context_destroy(), context->being_destroyed is set to 1 early in the function, before the loop calling lws_close_free_wsi() on each active connection.
lws_close_free_wsi() calls remove_wsi_socket_from_fds(), which calls lws_libev_io(), and here is my problem :

lws_libev_io() returns without doing anything if context->being_destroyed is set, so libev callbacks for deleted connections file descriptors stay registered after context is destroyed, which may lead to segfault/undefined behaviour if these file descriptors get reused later (which would trigger the callbacks).

I think the "if (!pt->io_loop_ev || context->being_destroyed) return;" statement should be replaced with " if (!pt->io_loop_ev) return;"

This fixes the problem for me and I have not seen any side effect yet. Moreover, libuv backend does not have such a test.
2017-03-29 08:22:54 +08:00
Andy Green
f80967b6c1 service: always restrict rx to serve_buf_size 2017-03-28 08:52:20 +08:00
Andy Green
d2d87776f9 pmd: handle case we are already on drain list
Provide internal helper for adding to list that takes care of the
case we are already on the list.

https://github.com/warmcat/libwebsockets/issues/847
2017-03-26 10:11:06 +08:00
Andy Green
5a354ae44a pmd: align client rx sm with server one 2017-03-25 08:51:06 +08:00
luk65
253ef2180e solaris: handle big-endian
https://github.com/warmcat/libwebsockets/issues/846
2017-03-23 23:58:01 +08:00
Andy Green
42ea3bd703 ext: pmd: improve dealing with partial input usage with drain
https://github.com/warmcat/libwebsockets/issues/841
2017-03-20 19:34:49 +08:00
a7e7d4ea08 rpm: added missing file to %files section of spec file 2017-03-18 11:20:46 +08:00
Andy Green
b4d2ad04bd windows: cannot use fstat 2017-03-17 11:44:47 +08:00
Andy Green
f8a995e8d5 docs: lws_callback_all_protocol: fix cut-n-paste error and explain it is probably not what you want 2017-03-15 07:29:55 +08:00
Andy Green
dca17ff614 windows: don't use LWS_EXTERN outside of function declarations 2017-03-15 07:29:45 +08:00
Andy Green
839b1af4e4 esp32: move helper code into lws 2017-03-10 14:33:25 +08:00
Silas Parker
906f137794 ssl: close sometimes continuously asserting POLLIN until timeout
https://github.com/warmcat/libwebsockets/issues/831
2017-03-10 07:48:27 +08:00
Silas Parker
98eed1871a fops_zip: require libz 2017-03-09 20:26:26 +08:00
Silas Parker
0be5279eb2 gcc-format-strings: 32-bit build 2017-03-09 18:48:55 +08:00
honjane
486e72f2cb http2: fix log compile errors 2017-03-09 13:30:44 +08:00
47 changed files with 1463 additions and 201 deletions

View file

@ -10,7 +10,7 @@ set(PACKAGE "libwebsockets")
set(CPACK_PACKAGE_NAME "${PACKAGE}")
set(CPACK_PACKAGE_VERSION_MAJOR "2")
set(CPACK_PACKAGE_VERSION_MINOR "2")
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(CPACK_PACKAGE_VERSION_PATCH "2")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
set(CPACK_PACKAGE_VENDOR "andy@warmcat.com")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${PACKAGE_VERSION}")
@ -313,19 +313,14 @@ if (LWS_WITH_SQLITE3)
endif()
# FIXME: This must be runtime-only option.
# The base dir where the test-apps look for the SSL certs.
set(LWS_OPENSSL_CLIENT_CERTS ../share CACHE PATH "Server SSL certificate directory")
if (WIN32)
set(LWS_OPENSSL_CLIENT_CERTS . CACHE PATH "Client SSL certificate directory")
if (LWS_IPV6)
set(LWS_IPV6 OFF)
message(WARNING "IPv6 does not currently work on Windows!")
endif()
if (LWS_UNIX_SOCK)
if (LWS_UNIX_SOCK)
set(LWS_UNIX_SOCK OFF)
message(WARNING "Windows does not support UNIX domain sockets")
message(WARNING "Windows does not support UNIX domain sockets")
endif()
else()
set(LWS_OPENSSL_CLIENT_CERTS /etc/pki/tls/certs/ CACHE PATH "Client SSL certificate directory")
@ -598,7 +593,8 @@ else()
else()
if (LWS_WITH_ESP32)
list(APPEND SOURCES
lib/lws-plat-esp32.c)
lib/lws-plat-esp32.c
lib/romfs.c)
else()
list(APPEND SOURCES
lib/lws-plat-unix.c)
@ -659,8 +655,12 @@ if (LWS_WITH_RANGES)
endif()
if (LWS_WITH_ZIP_FOPS)
list(APPEND SOURCES
lib/fops-zip.c)
if (LWS_WITH_ZLIB)
list(APPEND SOURCES
lib/fops-zip.c)
else()
message(FATAL_ERROR "Pre-zipped file support (LWS_WITH_ZIP_FOPS) requires ZLIB (LWS_WITH_ZLIB)")
endif()
endif()
# Add helper files for Windows.
@ -747,13 +747,13 @@ if (LWS_WITH_STATIC)
endif()
add_custom_command(
TARGET websockets
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/lib/libwebsockets.h
${CMAKE_BINARY_DIR}/include/libwebsockets.h
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/lib/libwebsockets.h
${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h
)
add_custom_command(
TARGET websockets
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/lws_config.h
${CMAKE_BINARY_DIR}/include/lws_config.h
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/lws_config.h
${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h
)
endif()
@ -786,13 +786,13 @@ if (LWS_WITH_SHARED)
add_custom_command(
TARGET websockets_shared
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/lib/libwebsockets.h
${CMAKE_BINARY_DIR}/include/libwebsockets.h
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/lib/libwebsockets.h
${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h
)
add_custom_command(
TARGET websockets_shared
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/lws_config.h
${CMAKE_BINARY_DIR}/include/lws_config.h
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/lws_config.h
${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h
)
@ -989,6 +989,8 @@ set (temp ${CMAKE_REQUIRED_LIBRARIES})
set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST})
CHECK_FUNCTION_EXISTS(SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param)
CHECK_FUNCTION_EXISTS(X509_VERIFY_PARAM_set1_host LWS_HAVE_X509_VERIFY_PARAM_set1_host)
CHECK_FUNCTION_EXISTS(TLS_client_method LWS_HAVE_TLS_CLIENT_METHOD)
CHECK_FUNCTION_EXISTS(TLSv1_2_client_method LWS_HAVE_TLSV1_2_CLIENT_METHOD)
set(CMAKE_REQUIRED_LIBRARIES ${temp})
# Generate the lws_config.h that includes all the public compilation settings.
configure_file(
@ -1716,7 +1718,7 @@ message("---------------------------------------------------------------------")
# These will be available to parent projects including libwebsockets using add_subdirectory()
set(LIBWEBSOCKETS_LIBRARIES ${LWS_LIBRARIES} CACHE STRING "Libwebsocket libraries")
if (LWS_WITH_STATIC)
set(LIBWEBSOCKETS_LIBRARIES_STATIC websocket CACHE STRING "Libwebsocket static library")
set(LIBWEBSOCKETS_LIBRARIES_STATIC websockets CACHE STRING "Libwebsocket static library")
endif()
if (LWS_WITH_SHARED)
set(LIBWEBSOCKETS_LIBRARIES_SHARED websockets_shared CACHE STRING "Libwebsocket shared library")

16
LICENSE
View file

@ -1,7 +1,13 @@
Libwebsockets and included programs are provided under the terms of the GNU
Library General Public License (LGPL) 2.1, with the following exceptions:
1) Static linking of programs with the libwebsockets library does not
1) Any reference, whether in these modifications or in the GNU
Library General Public License 2.1, to this License, these terms, the
GNU Lesser Public License, GNU Library General Public License, LGPL, or
any similar reference shall refer to the GNU Library General Public
License 2.1 as modified by these paragraphs 1) through 4).
2) Static linking of programs with the libwebsockets library does not
constitute a derivative work and does not require the author to provide
source code for the program, use the shared libwebsockets libraries, or
link their program against a user-supplied version of libwebsockets.
@ -10,7 +16,7 @@ If you link the program to a modified version of libwebsockets, then the
changes to libwebsockets must be provided under the terms of the LGPL in
sections 1, 2, and 4.
2) You do not have to provide a copy of the libwebsockets license with
3) You do not have to provide a copy of the libwebsockets license with
programs that are linked to the libwebsockets library, nor do you have to
identify the libwebsockets license in your program or documentation as
required by section 6 of the LGPL.
@ -22,7 +28,7 @@ satisfy this requirement:
"[program] is based in part on the work of the libwebsockets project
(https://libwebsockets.org)"
3) Some sources included have their own, more liberal licenses, or options
4) Some sources included have their own, more liberal licenses, or options
to get original sources with the liberal terms.
Original liberal license retained
@ -41,7 +47,9 @@ Public Domain (CC-zero) to simplify reuse
- test-server/*.c
- test-server/*.h
- lwsws/*
------ end of exceptions
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999

View file

@ -176,7 +176,7 @@ cmake from scratch.
2. Fix up MinGW headers
a) Add the following lines to C:\MinGW\include\winsock2.h:
a) (32-bit) Add the following lines to C:\MinGW\include\winsock2.h:
```
#if(_WIN32_WINNT >= 0x0600)
@ -192,9 +192,17 @@ cmake from scratch.
#endif // (_WIN32_WINNT >= 0x0600)
```
(64 bit) Update crtdefs.h line 47 to say:
```
typedef __int64 ssize_t;
```
b) Create C:\MinGW\include\mstcpip.h and copy and paste the content from following link into it:
http://wine-unstable.sourcearchive.com/documentation/1.1.32/mstcpip_8h-source.html
(32-bit) http://wine-unstable.sourcearchive.com/documentation/1.1.32/mstcpip_8h-source.html
(64-bit) https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-headers/include/mstcpip.h
3. Install CMake 2.6 or greater: http://cmake.org/cmake/resources/software.html

View file

@ -17,6 +17,7 @@ build:
cmake $(COMPONENT_PATH) -DLWS_C_FLAGS="$(CFLAGS)" \
-DCROSS_PATH=$(CROSS_PATH) \
-DCOMPONENT_PATH=$(COMPONENT_PATH) \
-DBUILD_DIR_BASE=$(BUILD_DIR_BASE) \
-DCMAKE_TOOLCHAIN_FILE=$(COMPONENT_PATH)/cross-esp32.cmake \
-DCMAKE_BUILD_TYPE=RELEASE \
-DLWS_WITH_NO_LOGS=0 \

View file

@ -12,7 +12,7 @@ set(CMAKE_SYSTEM_NAME Linux)
# Name of C compiler.
set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/xtensa-esp32-elf-gcc")
SET(CMAKE_C_FLAGS "-nostdlib -Wall -Werror -I${COMPONENT_PATH}/../lwip/include/lwip/posix -I${COMPONENT_PATH}/../lwip/include/lwip -I${COMPONENT_PATH}/../lwip/include/lwip/port -I${COMPONENT_PATH}/../esp32/include/ ${LWS_C_FLAGS} -I${COMPONENT_PATH}/../nvs_flash/test_nvs_host -I${COMPONENT_PATH}/../freertos/include -Os" CACHE STRING "" FORCE)
SET(CMAKE_C_FLAGS "-nostdlib -Wall -Werror -I${BUILD_DIR_BASE}/include -I${COMPONENT_PATH}/../driver/include -I${COMPONENT_PATH}/../spi_flash/include -I${COMPONENT_PATH}/../nvs_flash/include -I${COMPONENT_PATH}/../tcpip_adapter/include -I${COMPONENT_PATH}/../lwip/include/lwip/posix -I${COMPONENT_PATH}/../lwip/include/lwip -I${COMPONENT_PATH}/../lwip/include/lwip/port -I${COMPONENT_PATH}/../esp32/include/ ${LWS_C_FLAGS} -I${COMPONENT_PATH}/../nvs_flash/test_nvs_host -I${COMPONENT_PATH}/../freertos/include -Os" CACHE STRING "" FORCE)
# Where to look for the target environment. (More paths can be added here)
set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}")

View file

@ -101,6 +101,8 @@ lws_client_connect_2(struct lws *wsi)
memcpy(&server_addr6.sin6_addr,
&((struct sockaddr_in6 *)result->ai_addr)->sin6_addr,
sizeof(struct in6_addr));
server_addr6.sin6_scope_id = ((struct sockaddr_in6 *)result->ai_addr)->sin6_scope_id;
server_addr6.sin6_flowinfo = ((struct sockaddr_in6 *)result->ai_addr)->sin6_flowinfo;
break;
default:
lwsl_err("Unknown address family\n");

View file

@ -21,9 +21,13 @@
#include "private-libwebsockets.h"
/*
* parsers.c: lws_rx_sm() needs to be roughly kept in
* sync with changes here, esp related to ext draining
*/
int lws_client_rx_sm(struct lws *wsi, unsigned char c)
{
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
int handled, n, m, rx_draining_ext = 0;
unsigned short close_code;
@ -31,26 +35,19 @@ int lws_client_rx_sm(struct lws *wsi, unsigned char c)
unsigned char *pp;
if (wsi->u.ws.rx_draining_ext) {
struct lws **w = &pt->rx_draining_ext_list;
lwsl_ext("%s: RX EXT DRAINING: Removing from list\n", __func__);
assert(!c);
eff_buf.token = NULL;
eff_buf.token_len = 0;
wsi->u.ws.rx_draining_ext = 0;
/* remove us from context draining ext list */
while (*w) {
if (*w == wsi) {
*w = wsi->u.ws.rx_draining_ext_list;
break;
}
w = &((*w)->u.ws.rx_draining_ext_list);
}
wsi->u.ws.rx_draining_ext_list = NULL;
lws_remove_wsi_from_draining_ext_list(wsi);
rx_draining_ext = 1;
lwsl_debug("%s: doing draining flow\n", __func__);
goto drain_extension;
}
if (wsi->socket_is_permanently_unusable)
return -1;
switch (wsi->lws_rx_parse_state) {
case LWS_RXPS_NEW:
/* control frames (PING) may interrupt checkable sequences */
@ -308,6 +305,9 @@ int lws_client_rx_sm(struct lws *wsi, unsigned char c)
assert(wsi->u.ws.rx_ubuf);
if (wsi->u.ws.rx_draining_ext)
goto drain_extension;
if (wsi->u.ws.this_frame_masked && !wsi->u.ws.all_zero_nonce)
c ^= wsi->u.ws.mask[(wsi->u.ws.mask_idx++) & 3];
@ -365,10 +365,14 @@ spill:
wsi->u.ws.rx_ubuf_head);
if (wsi->u.ws.rx_ubuf_head >= 2) {
close_code = (pp[0] << 8) | pp[1];
if (close_code < 1000 || close_code == 1004 ||
close_code == 1005 || close_code == 1006 ||
close_code == 1012 || close_code == 1013 ||
close_code == 1014 || close_code == 1015 ||
if (close_code < 1000 ||
close_code == 1004 ||
close_code == 1005 ||
close_code == 1006 ||
close_code == 1012 ||
close_code == 1013 ||
close_code == 1014 ||
close_code == 1015 ||
(close_code >= 1016 && close_code < 3000)
) {
pp[0] = (LWS_CLOSE_STATUS_PROTOCOL_ERR >> 8) & 0xff;
@ -381,6 +385,7 @@ spill:
wsi->user_space, pp,
wsi->u.ws.rx_ubuf_head))
return -1;
if (lws_partial_buffered(wsi))
/*
* if we're in the middle of something,
@ -496,10 +501,14 @@ ping_drop:
eff_buf.token_len = wsi->u.ws.rx_ubuf_head;
drain_extension:
lwsl_ext("%s: passing %d to ext\n", __func__, eff_buf.token_len);
n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &eff_buf, 0);
lwsl_ext("Ext RX returned %d\n", n);
if (n < 0) /* fail */
if (n < 0) {
wsi->socket_is_permanently_unusable = 1;
return -1;
}
lwsl_ext("post inflate eff_buf len %d\n", eff_buf.token_len);
@ -515,7 +524,8 @@ drain_extension:
goto utf8_fail;
/* we are ending partway through utf-8 character? */
if (!wsi->u.ws.rx_packet_length && wsi->u.ws.final && wsi->u.ws.utf8 && !n) {
if (!wsi->u.ws.rx_packet_length && wsi->u.ws.final &&
wsi->u.ws.utf8 && !n) {
lwsl_info("FINAL utf8 error\n");
utf8_fail: lwsl_info("utf8 error\n");
return -1;
@ -537,17 +547,16 @@ utf8_fail: lwsl_info("utf8 error\n");
if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
lwsl_info("Client doing pong callback\n");
if (n && eff_buf.token_len) {
if (n && eff_buf.token_len)
/* extension had more... main loop will come back
* we want callback to be done with this set, if so,
* because lws_is_final() hides it was final until the
* last chunk
*/
wsi->u.ws.rx_draining_ext = 1;
wsi->u.ws.rx_draining_ext_list = pt->rx_draining_ext_list;
pt->rx_draining_ext_list = wsi;
lwsl_ext("%s: RX EXT DRAINING: Adding to list\n", __func__);
}
lws_add_wsi_to_draining_ext_list(wsi);
else
lws_remove_wsi_from_draining_ext_list(wsi);
if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY ||
wsi->state == LWSS_AWAITING_CLOSE_ACK)
goto already_done;

View file

@ -426,10 +426,10 @@ lws_client_interpret_server_handshake(struct lws *wsi)
void *v;
#endif
ah = wsi->u.hdr.ah;
if (!wsi->do_ws) {
/* we are being an http client...
*/
ah = wsi->u.hdr.ah;
lws_union_transition(wsi, LWSCM_HTTP_CLIENT_ACCEPTED);
wsi->state = LWSS_CLIENT_HTTP_ESTABLISHED;
wsi->u.http.ah = ah;

View file

@ -40,6 +40,7 @@ lws_get_library_version(void)
return library_version;
}
#if !defined(LWS_WITH_NO_LOGS)
static const char * const mount_protocols[] = {
"http://",
"https://",
@ -49,6 +50,7 @@ static const char * const mount_protocols[] = {
">https://",
"callback://"
};
#endif
LWS_VISIBLE void *
lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost, const struct lws_protocols *prot,
@ -419,7 +421,7 @@ lws_create_vhost(struct lws_context *context,
vh->protocols = lwsp;
else {
vh->protocols = info->protocols;
free(lwsp);
lws_free(lwsp);
}
vh->same_vh_protocol_list = (struct lws **)

View file

@ -202,7 +202,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
* rx buffer by the caller, so this assumption is safe while
* we block new rx while draining the existing rx
*/
if (eff_buf->token && eff_buf->token_len) {
if (!priv->rx.avail_in && eff_buf->token && eff_buf->token_len) {
priv->rx.next_in = (unsigned char *)eff_buf->token;
priv->rx.avail_in = eff_buf->token_len;
}

View file

@ -224,7 +224,7 @@ lws_fops_zip_scan(lws_fops_zip_t priv, const char *name, int len)
if (get_u32(buf + ZC_SIGNATURE) != 0x02014B50)
return LWS_FZ_ERR_CENTRAL_SANITY;
lwsl_debug("cstart 0x%lx\n", priv->content_start);
lwsl_debug("cstart 0x%lx\n", (unsigned long)priv->content_start);
priv->hdr.filename_len = get_u16(buf + ZC_FILE_NAME_LENGTH);
priv->hdr.extra = get_u16(buf + ZC_EXTRA_FIELD_LENGTH);
@ -272,7 +272,7 @@ lws_fops_zip_scan(lws_fops_zip_t priv, const char *name, int len)
get_u16(buf + ZL_REL_OFFSET_CONTENT);
lwsl_debug("content supposed to start at 0x%lx\n",
priv->content_start);
(unsigned long)priv->content_start);
if (priv->content_start > priv->zip_fop_fd->len)
return LWS_FZ_ERR_CONTENT_SANITY;

View file

@ -169,7 +169,7 @@ int lws_http2_frame_write(struct lws *wsi, int type, int flags,
*p++ = sid >> 8;
*p++ = sid;
lwsl_info("%s: %p (eff %p). type %d, flags 0x%x, sid=%d, len=%d\n",
lwsl_info("%s: %p (eff %p). type %d, flags 0x%x, sid=%d, len=%d, tx_credit=%d\n",
__func__, wsi, wsi_eff, type, flags, sid, len,
wsi->u.http2.tx_credit);

View file

@ -190,7 +190,7 @@ lws_libev_io(struct lws *wsi, int flags)
if (!LWS_LIBEV_ENABLED(context))
return;
if (!pt->io_loop_ev || context->being_destroyed)
if (!pt->io_loop_ev)
return;
assert((flags & (LWS_EV_START | LWS_EV_STOP)) &&

View file

@ -40,7 +40,7 @@ lws_uv_idle(uv_idle_t *handle
struct lws_context_per_thread *pt = lws_container_of(handle,
struct lws_context_per_thread, uv_idle);
lwsl_debug("%s\n", __func__);
// lwsl_debug("%s\n", __func__);
/*
* is there anybody with pending stuff that needs service forcing?
@ -51,7 +51,7 @@ lws_uv_idle(uv_idle_t *handle
/* still somebody left who wants forced service? */
if (!lws_service_adjust_timeout(pt->context, 1, pt->tid))
/* yes... come back again later */
lwsl_debug("%s: done again\n", __func__);
// lwsl_debug("%s: done again\n", __func__);
return;
}
@ -258,7 +258,8 @@ static void lws_uv_close_cb(uv_handle_t *handle)
static void lws_uv_walk_cb(uv_handle_t *handle, void *arg)
{
uv_close(handle, lws_uv_close_cb);
if (!uv_is_closing(handle))
uv_close(handle, lws_uv_close_cb);
}
void
@ -331,7 +332,7 @@ lws_libuv_accept(struct lws *wsi, lws_sock_file_fd_type desc)
wsi->w_read.context = context;
if (wsi->mode == LWSCM_RAW_FILEDESC)
uv_poll_init(pt->io_loop_uv, &wsi->w_read.uv_watcher,
desc.filefd);
(int)desc.filefd);
else
uv_poll_init_socket(pt->io_loop_uv, &wsi->w_read.uv_watcher,
desc.sockfd);
@ -541,6 +542,11 @@ lws_plat_plugins_init(struct lws_context *context, const char * const *d)
char path[256];
uv_loop_t loop;
uv_lib_t lib;
int pofs = 0;
#if defined(__MINGW32__) || !defined(WIN32)
pofs = 3;
#endif
lib.errmsg = NULL;
lib.handle = NULL;
@ -570,19 +576,20 @@ lws_plat_plugins_init(struct lws_context *context, const char * const *d)
lwsl_err("Error loading DSO: %s\n", lib.errmsg);
goto bail;
}
/* we could open it, can we get his init function? */
#if !defined(WIN32)
#if !defined(WIN32) && !defined(__MINGW32__)
m = lws_snprintf(path, sizeof(path) - 1, "init_%s",
dent.name + 3 /* snip lib... */);
dent.name + pofs /* snip lib... */);
path[m - 3] = '\0'; /* snip the .so */
#else
m = lws_snprintf(path, sizeof(path) - 1, "init_%s",
dent.name);
dent.name + pofs);
path[m - 4] = '\0'; /* snip the .dll */
#endif
if (uv_dlsym(&lib, path, &v)) {
uv_dlerror(&lib);
lwsl_err("Failed to get init on %s: %s",
lwsl_err("Failed to get %s on %s: %s", path,
dent.name, lib.errmsg);
goto bail;
}
@ -633,6 +640,11 @@ lws_plat_plugins_destroy(struct lws_context *context)
char path[256];
void *v;
int m;
int pofs = 0;
#if defined(__MINGW32__) || !defined(WIN32)
pofs = 3;
#endif
if (!plugin)
return 0;
@ -641,17 +653,17 @@ lws_plat_plugins_destroy(struct lws_context *context)
while (plugin) {
p = plugin;
#if !defined(WIN32)
m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s", plugin->name + 3);
#if !defined(WIN32) && !defined(__MINGW32__)
m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s", plugin->name + pofs);
path[m - 3] = '\0';
#else
m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s", plugin->name);
m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s", plugin->name + pofs);
path[m - 4] = '\0';
#endif
if (uv_dlsym(&plugin->lib, path, &v)) {
uv_dlerror(&plugin->lib);
lwsl_err("Failed to get init on %s: %s",
lwsl_err("Failed to get %s on %s: %s", path,
plugin->name, plugin->lib.errmsg);
} else {
func = (lws_plugin_destroy_func)v;

View file

@ -480,13 +480,28 @@ just_kill_connection:
!wsi->socket_is_permanently_unusable) {
#ifdef LWS_OPENSSL_SUPPORT
if (lws_is_ssl(wsi) && wsi->ssl)
{
lwsl_info("%s: shutting down SSL connection: %p (ssl %p, sock %d, state %d)\n", __func__, wsi, wsi->ssl, (int)(long)wsi->desc.sockfd, wsi->state);
{
lwsl_info("%s: shutting down SSL connection: %p (ssl %p, sock %d, state %d)\n", __func__, wsi, wsi->ssl, (int)(long)wsi->desc.sockfd, wsi->state);
n = SSL_shutdown(wsi->ssl);
if (n == 0) /* Complete bidirectional SSL shutdown */
SSL_shutdown(wsi->ssl);
n = shutdown(wsi->desc.sockfd, SHUT_WR);
}
if (n == 1) /* If finished the SSL shutdown, then do socket shutdown, else need to retry SSL shutdown */
n = shutdown(wsi->desc.sockfd, SHUT_WR);
else if (n == 0)
lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN);
else /* n < 0 */
{
int shutdown_error = SSL_get_error(wsi->ssl, n);
lwsl_debug("SSL_shutdown returned %d, SSL_get_error: %d\n", n, shutdown_error);
if (shutdown_error == SSL_ERROR_WANT_READ) {
lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN);
n = 0;
} else if (shutdown_error == SSL_ERROR_WANT_WRITE) {
lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLOUT);
n = 0;
} else { // actual error occurred, just close the connection
n = shutdown(wsi->desc.sockfd, SHUT_WR);
}
}
}
else
#endif
{
@ -1754,10 +1769,10 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
#endif
struct sockaddr_in serv_addr4;
#ifndef LWS_PLAT_OPTEE
socklen_t len = sizeof(struct sockaddr);
socklen_t len = sizeof(struct sockaddr_storage);
#endif
int n;
struct sockaddr_in sin;
struct sockaddr_storage sin;
struct sockaddr *v;
#ifdef LWS_USE_UNIX_SOCK
@ -1789,6 +1804,7 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
return -1;
}
#ifndef WIN32
if (iface) {
struct ifaddrs *addrs, *addr;
char ip[NI_MAXHOST];
@ -1820,6 +1836,7 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
}
freeifaddrs(addrs);
}
#endif
serv_addr6.sin6_family = AF_INET6;
serv_addr6.sin6_port = htons(port);
@ -1862,7 +1879,13 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
lwsl_warn("getsockname: %s\n", strerror(LWS_ERRNO));
else
#endif
port = ntohs(sin.sin_port);
#if defined(LWS_USE_IPV6)
port = (sin.ss_family == AF_INET6) ?
ntohs(((struct sockaddr_in6 *) &sin)->sin6_port) :
ntohs(((struct sockaddr_in *) &sin)->sin_port);
#else
port = ntohs(((struct sockaddr_in *) &sin)->sin_port);
#endif
#endif
return port;

View file

@ -33,12 +33,6 @@ extern "C" {
#include <stdarg.h>
#endif
static inline int lws_is_be(void) {
const int probe = ~0xff;
return *(const char *)&probe;
}
#if defined(LWS_WITH_ESP8266)
struct sockaddr_in;
#define LWS_POSIX 0
@ -99,6 +93,10 @@ struct sockaddr_in;
#define __func__ __FUNCTION__
#endif
#if !defined(__MINGW32__) &&(!defined(_MSC_VER) || _MSC_VER < 1900) && !defined(snprintf)
#define snprintf(buf,len, format,...) _snprintf_s(buf, len,len, format, __VA_ARGS__)
#endif
#else /* NOT WIN32 */
#include <unistd.h>
@ -292,6 +290,12 @@ LWS_VISIBLE LWS_EXTERN void lwsl_hexdump(void *buf, size_t len);
#endif
static LWS_INLINE int lws_is_be(void) {
const int probe = ~0xff;
return *(const char *)&probe;
}
/**
* lws_set_log_level() - Set the logging bitfield
* \param level: OR together the LLL_ debug contexts you want output from
@ -460,6 +464,16 @@ struct pollfd {
#define POLLHUP 0x0010
#define POLLNVAL 0x0020
#include <freertos/FreeRTOS.h>
#include <freertos/event_groups.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs.h"
#include "driver/gpio.h"
#include "esp_spi_flash.h"
#include "freertos/timers.h"
#if !defined(CONFIG_FREERTOS_HZ)
@ -513,8 +527,35 @@ static inline void uv_close(uv_handle_t *h, void *v)
xTimerDelete(*(uv_timer_t *)h, 0);
}
/* ESP32 helper declarations */
#define LWS_PLUGIN_STATIC
/* user code provides these */
extern char lws_esp32_model[16];
extern int
lws_esp32_is_booting_in_ap_mode(void);
extern void
lws_esp32_identify_physical_device(void);
/* lws-plat-esp32 provides these */
extern void (*lws_cb_scan_done)(void *);
extern void *lws_cb_scan_done_arg;
extern char lws_esp32_serial[], lws_esp32_force_ap, lws_esp32_region;
extern esp_err_t
lws_esp32_event_passthru(void *ctx, system_event_t *event);
extern void
lws_esp32_wlan_config(void);
extern void
lws_esp32_wlan_start(void);
struct lws_context_creation_info;
extern struct lws_context *
lws_esp32_init(struct lws_context_creation_info *, unsigned int _romfs);
#else
typedef int lws_sockfd_type;
@ -3527,7 +3568,7 @@ lws_callback_on_writable(struct lws *wsi);
/**
* lws_callback_on_writable_all_protocol() - Request a callback for all
* connections on same vhost using the given protocol when it
* connections using the given protocol when it
* becomes possible to write to each socket without
* blocking in turn.
*
@ -3544,8 +3585,8 @@ lws_callback_on_writable_all_protocol(const struct lws_context *context,
/**
* lws_callback_on_writable_all_protocol_vhost() - Request a callback for
* all connections using the given protocol when it
* becomes possible to write to each socket without
* all connections on same vhost using the given protocol
* when it becomes possible to write to each socket without
* blocking in turn.
*
* \param vhost: Only consider connections on this lws_vhost
@ -3568,8 +3609,12 @@ lws_callback_on_writable_all_protocol_vhost(const struct lws_vhost *vhost,
* \param reason: Callback reason index
*
* - Which: connections using this protocol on ALL VHOSTS
* - When: when the individual connection becomes writeable
* - When: before returning
* - What: reason
*
* This isn't normally what you want... normally any update of connection-
* specific information can wait until a network-related callback like rx,
* writable, or close.
*/
LWS_VISIBLE LWS_EXTERN int
lws_callback_all_protocol(struct lws_context *context,
@ -4296,7 +4341,7 @@ lws_cgi_kill(struct lws *wsi);
struct lws_plat_file_ops;
#if defined(WIN32) || defined(_WIN32)
#if (defined(WIN32) || defined(_WIN32)) && !defined(__MINGW32__)
/* ... */
#if !defined(ssize_t)
typedef SSIZE_T ssize_t;
@ -4428,7 +4473,7 @@ lws_vfs_file_seek_set(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
LWS_VISIBLE LWS_EXTERN lws_fileofs_t
lws_vfs_file_seek_end(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
LWS_VISIBLE LWS_EXTERN struct lws_plat_file_ops fops_zip;
extern struct lws_plat_file_ops fops_zip;
/**
* lws_plat_file_open() - open vfs filepath

View file

@ -528,3 +528,277 @@ char *ERR_error_string(unsigned long e, char *buf)
return "unknown";
}
/* helper functionality */
#include "romfs.h"
void (*lws_cb_scan_done)(void *);
void *lws_cb_scan_done_arg;
char lws_esp32_serial[16] = "unknown", lws_esp32_force_ap = 0,
lws_esp32_region = WIFI_COUNTRY_US; // default to safest option
static romfs_t lws_esp32_romfs;
/*
* configuration related to the AP setup website
*
* The 'esplws-scan' protocol drives the configuration
* site, and updates the scan results in realtime over
* a websocket link.
*/
#include "../plugins/protocol_esp32_lws_scan.c"
static const struct lws_protocols protocols_ap[] = {
{
"http-only",
lws_callback_http_dummy,
0, /* per_session_data_size */
900, 0, NULL
},
LWS_PLUGIN_PROTOCOL_ESPLWS_SCAN,
{ NULL, NULL, 0, 0, 0, NULL } /* terminator */
};
static const struct lws_protocol_vhost_options ap_pvo = {
NULL,
NULL,
"esplws-scan",
""
};
static const struct lws_http_mount mount_ap = {
.mountpoint = "/",
.origin = "/ap",
.def = "index.html",
.origin_protocol = LWSMPRO_FILE,
.mountpoint_len = 1,
};
struct esp32_file {
const struct inode *i;
};
esp_err_t lws_esp32_event_passthru(void *ctx, system_event_t *event)
{
switch(event->event_id) {
case SYSTEM_EVENT_SCAN_DONE:
if (lws_cb_scan_done)
lws_cb_scan_done(lws_cb_scan_done_arg);
break;
case SYSTEM_EVENT_STA_START:
esp_wifi_connect();
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
/* This is a workaround as ESP32 WiFi libs don't currently
auto-reassociate. */
esp_wifi_connect();
break;
default:
break;
}
return ESP_OK;
}
static lws_fop_fd_t IRAM_ATTR
esp32_lws_fops_open(const struct lws_plat_file_ops *fops, const char *filename,
const char *vfs_path, lws_fop_flags_t *flags)
{
struct esp32_file *f = malloc(sizeof(*f));
lws_fop_fd_t fop_fd;
size_t len;
lwsl_notice("%s: %s\n", __func__, filename);
if (!f)
return NULL;
f->i = romfs_get_info(lws_esp32_romfs, filename, &len);
if (!f->i)
goto bail;
fop_fd = malloc(sizeof(*fop_fd));
if (!fop_fd)
goto bail;
fop_fd->fops = fops;
fop_fd->filesystem_priv = f;
fop_fd->flags = *flags;
fop_fd->len = len;
fop_fd->pos = 0;
return fop_fd;
bail:
free(f);
return NULL;
}
static int IRAM_ATTR
esp32_lws_fops_close(lws_fop_fd_t *fop_fd)
{
free((*fop_fd)->filesystem_priv);
free(*fop_fd);
*fop_fd = NULL;
return 0;
}
static lws_fileofs_t IRAM_ATTR
esp32_lws_fops_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset_from_cur_pos)
{
fop_fd->pos += offset_from_cur_pos;
if (fop_fd->pos > fop_fd->len)
fop_fd->pos = fop_fd->len;
return 0;
}
static int IRAM_ATTR
esp32_lws_fops_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, uint8_t *buf,
lws_filepos_t len)
{
struct esp32_file *f = fop_fd->filesystem_priv;
if ((long)buf & 3) {
lwsl_err("misaligned buf\n");
return -1;
}
if (fop_fd->pos >= fop_fd->len)
return 0;
if (len > fop_fd->len - fop_fd->pos)
len = fop_fd->len - fop_fd->pos;
spi_flash_read((uint32_t)(char *)f->i + fop_fd->pos, buf, len);
*amount = len;
fop_fd->pos += len;
return 0;
}
static const struct lws_plat_file_ops fops = {
.LWS_FOP_OPEN = esp32_lws_fops_open,
.LWS_FOP_CLOSE = esp32_lws_fops_close,
.LWS_FOP_READ = esp32_lws_fops_read,
.LWS_FOP_SEEK_CUR = esp32_lws_fops_seek_cur,
};
static wifi_config_t sta_config = {
.sta = {
.bssid_set = false
}
}, ap_config = {
.ap = {
.channel = 6,
.authmode = WIFI_AUTH_OPEN,
.max_connection = 1,
}
};
void
lws_esp32_wlan_config(void)
{
nvs_handle nvh;
char r[2];
size_t s;
ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh));
s = sizeof(sta_config.sta.ssid) - 1;
if (nvs_get_str(nvh, "ssid", (char *)sta_config.sta.ssid, &s) != ESP_OK)
lws_esp32_force_ap = 1;
s = sizeof(sta_config.sta.password) - 1;
if (nvs_get_str(nvh, "password", (char *)sta_config.sta.password, &s) != ESP_OK)
lws_esp32_force_ap = 1;
s = sizeof(lws_esp32_serial) - 1;
if (nvs_get_str(nvh, "serial", lws_esp32_serial, &s) != ESP_OK)
lws_esp32_force_ap = 1;
else
snprintf((char *)ap_config.ap.ssid, sizeof(ap_config.ap.ssid) - 1,
"config-%s-%s", lws_esp32_model, lws_esp32_serial);
s = sizeof(r);
if (nvs_get_str(nvh, "region", r, &s) != ESP_OK)
lws_esp32_force_ap = 1;
else
lws_esp32_region = atoi(r);
nvs_close(nvh);
tcpip_adapter_init();
}
void
lws_esp32_wlan_start(void)
{
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK( esp_wifi_init(&cfg));
ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM));
ESP_ERROR_CHECK( esp_wifi_set_country(lws_esp32_region));
if (!lws_esp32_is_booting_in_ap_mode() && !lws_esp32_force_ap) {
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config));
} else {
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_APSTA) );
ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &ap_config) );
}
ESP_ERROR_CHECK( esp_wifi_start());
tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, (const char *)&ap_config.ap.ssid[7]);
if (!lws_esp32_is_booting_in_ap_mode() && !lws_esp32_force_ap)
ESP_ERROR_CHECK( esp_wifi_connect());
}
struct lws_context *
lws_esp32_init(struct lws_context_creation_info *info, unsigned int _romfs)
{
size_t romfs_size;
struct lws_context *context;
lws_set_log_level(65535, lwsl_emit_syslog);
context = lws_create_context(info);
if (context == NULL) {
lwsl_err("Failed to create context\n");
return NULL;
}
lws_esp32_romfs = (romfs_t)(void *)_romfs;
romfs_size = romfs_mount_check(lws_esp32_romfs);
if (!romfs_size) {
lwsl_err("Failed to mount ROMFS\n");
return NULL;
}
lwsl_notice("ROMFS length %uKiB\n", romfs_size >> 10);
/* set the lws vfs to use our romfs */
lws_set_fops(context, &fops);
if (lws_esp32_is_booting_in_ap_mode() || lws_esp32_force_ap) {
info->vhost_name = "ap";
info->protocols = protocols_ap;
info->mounts = &mount_ap;
info->pvo = &ap_pvo;
}
if (!lws_create_vhost(context, info))
lwsl_err("Failed to create vhost\n");
lws_protocol_init(context);
return context;
}

View file

@ -669,7 +669,7 @@ _lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
fop_fd->pos = r;
else
lwsl_err("error seeking from cur %ld, offset %ld\n",
fop_fd->pos, offset);
(long)fop_fd->pos, (long)offset);
return r;
}
@ -687,7 +687,7 @@ _lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
}
fop_fd->pos += n;
lwsl_debug("%s: read %ld of req %ld, pos %ld, len %ld\n", __func__, n,
(long)len, fop_fd->pos, fop_fd->len);
(long)len, (long)fop_fd->pos, (long)fop_fd->len);
*amount = n;
return 0;

View file

@ -108,6 +108,10 @@ LWS_VISIBLE int lws_get_random(struct lws_context *context,
LWS_VISIBLE int lws_send_pipe_choked(struct lws *wsi)
{
/* treat the fact we got a truncated send pending as if we're choked */
if (wsi->trunc_len)
return 1;
return (int)wsi->sock_send_blocking;
}
@ -522,7 +526,7 @@ lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
}
LWS_VISIBLE lws_fop_fd_t
_lws_plat_file_open(struct lws_plat_file_ops *fops, const char *filename,
_lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
const char *vpath, lws_fop_flags_t *flags)
{
HANDLE ret;

View file

@ -492,7 +492,7 @@ send_raw:
wsi->u.http.content_length) {
wsi->u.http.content_remain -= len;
lwsl_info("%s: content_remain = %lu\n", __func__,
wsi->u.http.content_remain);
(unsigned long)wsi->u.http.content_remain);
if (!wsi->u.http.content_remain) {
lwsl_info("%s: selecting final write mode\n", __func__);
wp = LWS_WRITE_HTTP_FINAL;
@ -801,5 +801,5 @@ LWS_VISIBLE int
lws_ssl_pending_no_ssl(struct lws *wsi)
{
(void)wsi;
return 1;
return 0;
}

View file

@ -955,36 +955,72 @@ LWS_VISIBLE int lws_frame_is_binary(struct lws *wsi)
return wsi->u.ws.frame_is_binary;
}
void
lws_add_wsi_to_draining_ext_list(struct lws *wsi)
{
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
if (wsi->u.ws.rx_draining_ext)
return;
lwsl_ext("%s: RX EXT DRAINING: Adding to list\n", __func__);
wsi->u.ws.rx_draining_ext = 1;
wsi->u.ws.rx_draining_ext_list = pt->rx_draining_ext_list;
pt->rx_draining_ext_list = wsi;
}
void
lws_remove_wsi_from_draining_ext_list(struct lws *wsi)
{
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
struct lws **w = &pt->rx_draining_ext_list;
if (!wsi->u.ws.rx_draining_ext)
return;
lwsl_ext("%s: RX EXT DRAINING: Removing from list\n", __func__);
wsi->u.ws.rx_draining_ext = 0;
/* remove us from context draining ext list */
while (*w) {
if (*w == wsi) {
/* if us, point it instead to who we were pointing to */
*w = wsi->u.ws.rx_draining_ext_list;
break;
}
w = &((*w)->u.ws.rx_draining_ext_list);
}
wsi->u.ws.rx_draining_ext_list = NULL;
}
/*
* client-parser.c: lws_client_rx_sm() needs to be roughly kept in
* sync with changes here, esp related to ext draining
*/
int
lws_rx_sm(struct lws *wsi, unsigned char c)
{
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
int callback_action = LWS_CALLBACK_RECEIVE;
int ret = 0, n, rx_draining_ext = 0;
struct lws_tokens eff_buf;
eff_buf.token = NULL;
eff_buf.token_len = 0;
if (wsi->socket_is_permanently_unusable)
return -1;
switch (wsi->lws_rx_parse_state) {
case LWS_RXPS_NEW:
if (wsi->u.ws.rx_draining_ext) {
struct lws **w = &pt->rx_draining_ext_list;
eff_buf.token = NULL;
eff_buf.token_len = 0;
wsi->u.ws.rx_draining_ext = 0;
/* remove us from context draining ext list */
while (*w) {
if (*w == wsi) {
*w = wsi->u.ws.rx_draining_ext_list;
break;
}
w = &((*w)->u.ws.rx_draining_ext_list);
}
wsi->u.ws.rx_draining_ext_list = NULL;
lws_remove_wsi_from_draining_ext_list(wsi);
rx_draining_ext = 1;
lwsl_err("%s: doing draining flow\n", __func__);
lwsl_debug("%s: doing draining flow\n", __func__);
goto drain_extension;
}
@ -1238,6 +1274,9 @@ handle_first:
case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
assert(wsi->u.ws.rx_ubuf);
if (wsi->u.ws.rx_draining_ext)
goto drain_extension;
if (wsi->u.ws.rx_ubuf_head + LWS_PRE >=
wsi->u.ws.rx_ubuf_alloc) {
lwsl_err("Attempted overflow \n");
@ -1413,6 +1452,9 @@ drain_extension:
goto already_done;
n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &eff_buf, 0);
/* eff_buf may be pointing somewhere completely different now,
* it's the output
*/
if (n < 0) {
/*
* we may rely on this to get RX, just drop connection
@ -1426,10 +1468,9 @@ drain_extension:
if (n && eff_buf.token_len) {
/* extension had more... main loop will come back */
wsi->u.ws.rx_draining_ext = 1;
wsi->u.ws.rx_draining_ext_list = pt->rx_draining_ext_list;
pt->rx_draining_ext_list = wsi;
}
lws_add_wsi_to_draining_ext_list(wsi);
} else
lws_remove_wsi_from_draining_ext_list(wsi);
if (eff_buf.token_len > 0 ||
callback_action == LWS_CALLBACK_RECEIVE_PONG) {

View file

@ -33,6 +33,26 @@ _lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa)
if (!wsi || wsi->position_in_fds_table < 0)
return 0;
if (wsi->handling_pollout && !_and && _or == LWS_POLLOUT) {
/*
* Happening alongside service thread handling POLLOUT.
* The danger is when he is finished, he will disable POLLOUT,
* countermanding what we changed here.
*
* Instead of changing the fds, inform the service thread
* what happened, and ask it to leave POLLOUT active on exit
*/
wsi->leave_pollout_active = 1;
/*
* by definition service thread is not in poll wait, so no need
* to cancel service
*/
lwsl_debug("%s: using leave_pollout_active\n", __func__);
return 0;
}
context = wsi->context;
pt = &context->pt[(int)wsi->tsi];
assert(wsi->position_in_fds_table >= 0 &&

View file

@ -367,11 +367,23 @@ extern "C" {
#endif
#if defined(__sun) && defined(__GNUC__)
#include <arpa/nameser_compat.h>
#if !defined (BYTE_ORDER)
# define BYTE_ORDER __BYTE_ORDER__
#endif
#if !defined(LITTLE_ENDIAN)
# define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
#endif
#if !defined(BIG_ENDIAN)
# define BIG_ENDIAN __ORDER_BIG_ENDIAN__
#endif
#endif /* sun + GNUC */
#if !defined(BYTE_ORDER)
# define BYTE_ORDER __BYTE_ORDER
#endif
@ -1445,7 +1457,7 @@ struct lws {
unsigned int sending_chunked:1;
unsigned int already_did_cce:1;
unsigned int told_user_closed:1;
unsigned int :1;
#if defined(LWS_WITH_ESP8266)
unsigned int pending_send_completion:3;
unsigned int close_is_pending_send_completion:1;
@ -1475,6 +1487,10 @@ struct lws {
unsigned int redirect_to_https:1;
#endif
/* volatile to make sure code is aware other thread can change */
volatile unsigned int handling_pollout:1;
volatile unsigned int leave_pollout_active:1;
#ifndef LWS_NO_CLIENT
unsigned short c_port;
#endif
@ -1977,6 +1993,10 @@ lws_plat_service_periodic(struct lws_context *context);
LWS_EXTERN int
lws_plat_change_pollfd(struct lws_context *context, struct lws *wsi,
struct lws_pollfd *pfd);
LWS_EXTERN void
lws_add_wsi_to_draining_ext_list(struct lws *wsi);
LWS_EXTERN void
lws_remove_wsi_from_draining_ext_list(struct lws *wsi);
LWS_EXTERN int
lws_plat_context_early_init(void);
LWS_EXTERN void

216
lib/romfs.c Normal file
View file

@ -0,0 +1,216 @@
/*
* Copyright (C) 2017 National Institute of Advanced Industrial Science
* and Technology (AIST)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 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.
*
* Neither the name of AIST 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 COPYRIGHT HOLDERS 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
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "romfs.h"
#include "esp_spi_flash.h"
#define RFS_STRING_MAX 64
static u32_be_t cache[(RFS_STRING_MAX + 32) / 4];
static romfs_inode_t ci = (romfs_inode_t)cache;
static romfs_t cr = (romfs_t)cache;
static void
set_cache(romfs_inode_t inode, size_t len)
{
spi_flash_read((uint32_t)inode, cache, len);
}
static uint32_t
ntohl(const u32_be_t be)
{
return ((be >> 24) & 0xff) |
((be >> 16) & 0xff) << 8 |
((be >> 8) & 0xff) << 16 |
(be & 0xff) << 24;
}
static romfs_inode_t
romfs_lookup(romfs_t romfs, romfs_inode_t start, const char *path);
static int
plus_padding(const uint8_t *s)
{
int n;
set_cache((romfs_inode_t)s, RFS_STRING_MAX);
n = strlen((const char *)cache);
if (!(n & 15))
n += 0x10;
return (n + 15) & ~15;
}
static romfs_inode_t
skip_and_pad(romfs_inode_t ri)
{
const uint8_t *p = ((const uint8_t *)ri) + sizeof(*ri);
return (romfs_inode_t)(p + plus_padding(p));
}
size_t
romfs_mount_check(romfs_t romfs)
{
set_cache((romfs_inode_t)romfs, sizeof(*romfs));
if (cr->magic1 != 0x6d6f722d ||
cr->magic2 != 0x2d736631)
return 0;
return ntohl(cr->size);
}
static romfs_inode_t
romfs_symlink(romfs_t romfs, romfs_inode_t level, romfs_inode_t i)
{
const char *p = (const char *)skip_and_pad(i);
if (*p == '/') {
level = skip_and_pad((romfs_inode_t)romfs);
p++;
}
return romfs_lookup(romfs, level, p);
}
static romfs_inode_t
dir_link(romfs_t romfs, romfs_inode_t i)
{
set_cache(i, sizeof(*i));
return (romfs_inode_t)((const uint8_t *)romfs +
ntohl(ci->dir_start));
}
static romfs_inode_t
romfs_lookup(romfs_t romfs, romfs_inode_t start, const char *path)
{
romfs_inode_t level, i = start;
const char *p, *n, *cp;
uint32_t next_be;
if (start == (romfs_inode_t)romfs)
i = skip_and_pad((romfs_inode_t)romfs);
level = i;
while (i != (romfs_inode_t)romfs) {
p = path;
n = ((const char *)i) + sizeof(*i);
set_cache(i, sizeof(*i));
next_be = ci->next;
cp = (const char *)cache;
set_cache((romfs_inode_t)n, RFS_STRING_MAX);
while (*p && *p != '/' && *cp && *p == *cp) {
p++;
n++;
cp++;
}
if (!*cp && (!*p || *p == '/') &&
(ntohl(next_be) & 7) == RFST_HARDLINK) {
set_cache(i, sizeof(*i));
return (romfs_inode_t)
((const uint8_t *)romfs +
(ntohl(ci->dir_start) & ~15));
}
if (!*p && !*cp) {
set_cache(i, sizeof(*i));
if ((ntohl(ci->next) & 7) == RFST_SYMLINK) {
i = romfs_symlink(romfs, level, i);
continue;
}
return i;
}
if (*p == '/' && !*cp) {
set_cache(i, sizeof(*i));
switch (ntohl(ci->next) & 7) {
case RFST_SYMLINK:
i = romfs_symlink(romfs, level, i);
if (!i)
return NULL;
i = dir_link(romfs, i);
while (*path != '/' && *path)
path++;
if (!*path)
return NULL;
path++;
continue;
case RFST_DIR:
path = p + 1;
i = dir_link(romfs, i);
break;
default:
path = p + 1;
i = skip_and_pad(i);
break;
}
level = i;
continue;
}
set_cache(i, sizeof(*i));
if (!(ntohl(ci->next) & ~15))
return NULL;
i = (romfs_inode_t)((const uint8_t *)romfs +
(ntohl(ci->next) & ~15));
}
return NULL;
}
const void *
romfs_get_info(romfs_t romfs, const char *path, size_t *len)
{
romfs_inode_t i;
if (*path == '/')
path++;
i = romfs_lookup(romfs, (romfs_inode_t)romfs, path);
if (!i)
return NULL;
set_cache(i, sizeof(*i));
*len = ntohl(ci->size);
return (void *)skip_and_pad(i);
}

63
lib/romfs.h Normal file
View file

@ -0,0 +1,63 @@
/*
* Copyright (C) 2017 National Institute of Advanced Industrial Science
* and Technology (AIST)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 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.
*
* Neither the name of AIST 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 COPYRIGHT HOLDERS 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
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
typedef uint32_t u32_be_t;
struct romfs_superblock {
u32_be_t magic1;
u32_be_t magic2;
u32_be_t size;
u32_be_t checksum;
};
struct romfs_i {
u32_be_t next;
u32_be_t dir_start;
u32_be_t size;
u32_be_t checksum;
};
enum {
RFST_HARDLINK = 0,
RFST_DIR = 1,
RFST_SYMLINK = 3,
};
typedef const struct romfs_i *romfs_inode_t;
typedef const struct romfs_superblock *romfs_t;
const void *
romfs_get_info(romfs_t romfs, const char *path, size_t *len);
size_t
romfs_mount_check(romfs_t romfs);

View file

@ -391,11 +391,17 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin,
/* if it can't be statted, don't try */
if (fflags & LWS_FOP_FLAG_VIRTUAL)
break;
#if !defined(WIN32)
if (fstat(wsi->u.http.fop_fd->fd, &st)) {
lwsl_info("unable to stat %s\n", path);
goto bail;
}
#else
if (stat(path, &st)) {
lwsl_info("unable to stat %s\n", path);
goto bail;
}
#endif
wsi->u.http.fop_fd->mod_time = (uint32_t)st.st_mtime;
fflags |= LWS_FOP_FLAG_MOD_TIME_VALID;
@ -1738,8 +1744,17 @@ lws_http_transaction_completed(struct lws *wsi)
if (!wsi->more_rx_waiting) {
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
lws_header_table_detach(wsi, 1);
} else
} else {
lws_header_table_reset(wsi, 1);
/*
* If we kept the ah, we should restrict the amount
* of time we are willing to keep it. Otherwise it
* will be bound the whole time the connection remains
* open.
*/
lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE,
wsi->vhost->keepalive_timeout);
}
}
/* If we're (re)starting on headers, need other implied init */
@ -1998,7 +2013,7 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi,
lws_sockfd_type accept_fd = LWS_SOCK_INVALID;
struct allocated_headers *ah;
#if LWS_POSIX
struct sockaddr_in cli_addr;
struct sockaddr_storage cli_addr;
socklen_t clilen;
#endif
int n, len;
@ -2061,7 +2076,7 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi,
//lwsl_err("wsi %p: missing ah\n", wsi);
/* no autoservice beacuse we will do it next */
if (lws_header_table_attach(wsi, 0)) {
lwsl_err("wsi %p: failed to acquire ah\n", wsi);
lwsl_info("wsi %p: failed to acquire ah\n", wsi);
goto try_pollout;
}
}
@ -2236,7 +2251,7 @@ try_pollout:
if (accept_fd < 0) {
if (LWS_ERRNO == LWS_EAGAIN ||
LWS_ERRNO == LWS_EWOULDBLOCK) {
lwsl_err("accept asks to try again\n");
// lwsl_err("accept asks to try again\n");
break;
}
lwsl_err("ERROR on accept: %s\n", strerror(LWS_ERRNO));
@ -2245,8 +2260,17 @@ try_pollout:
lws_plat_set_socket_options(wsi->vhost, accept_fd);
lwsl_debug("accepted new conn port %u on fd=%d\n",
ntohs(cli_addr.sin_port), accept_fd);
#if defined(LWS_USE_IPV6)
lwsl_debug("accepted new conn port %u on fd=%d\n",
((cli_addr.ss_family == AF_INET6) ?
ntohs(((struct sockaddr_in6 *) &cli_addr)->sin6_port) :
ntohs(((struct sockaddr_in *) &cli_addr)->sin_port)),
accept_fd);
#else
lwsl_debug("accepted new conn port %u on fd=%d\n",
ntohs(((struct sockaddr_in *) &cli_addr)->sin_port),
accept_fd);
#endif
#else
/* not very beautiful... */
@ -2370,13 +2394,17 @@ lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type,
lwsl_info("file is being provided in gzip\n");
}
if (
#if defined(LWS_WITH_RANGES)
if (ranges < 2 && content_type && content_type[0])
ranges < 2 &&
#endif
content_type && content_type[0])
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
(unsigned char *)content_type,
strlen(content_type), &p, end))
return -1;
#if defined(LWS_WITH_RANGES)
if (ranges >= 2) { /* multipart byteranges */
strncpy(wsi->u.http.multipart_content_type, content_type,
sizeof(wsi->u.http.multipart_content_type) - 1);
@ -2515,6 +2543,7 @@ lws_interpret_incoming_packet(struct lws *wsi, unsigned char **buf, size_t len)
}
if (wsi->u.ws.rx_draining_ext) {
// lwsl_notice("draining with 0\n");
m = lws_rx_sm(wsi, 0);
if (m < 0)
return -1;
@ -2526,7 +2555,8 @@ lws_interpret_incoming_packet(struct lws *wsi, unsigned char **buf, size_t len)
wsi->rxflow_pos++;
/* consume payload bytes efficiently */
if (wsi->lws_rx_parse_state ==
if (
wsi->lws_rx_parse_state ==
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED) {
m = lws_payload_until_length_exhausted(wsi, buf, &len);
if (wsi->rxflow_buffer)

View file

@ -64,6 +64,14 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
//lwsl_err("%s: %p\n", __func__, wsi);
wsi->leave_pollout_active = 0;
wsi->handling_pollout = 1;
/*
* if another thread wants POLLOUT on us, from here on while
* handling_pollout is set, he will only set leave_pollout_active.
* If we are going to disable POLLOUT, we will check that first.
*/
/*
* user callback is lowest priority to get these notifications
* actually, since other pending things cannot be disordered
@ -77,13 +85,13 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
if (lws_issue_raw(wsi, wsi->trunc_alloc + wsi->trunc_offset,
wsi->trunc_len) < 0) {
lwsl_info("%s signalling to close\n", __func__);
return -1;
goto bail_die;
}
/* leave POLLOUT active either way */
return 0;
goto bail_ok;
} else
if (wsi->state == LWSS_FLUSHING_STORED_SEND_BEFORE_CLOSE)
return -1; /* retry closing now */
goto bail_die; /* retry closing now */
if (wsi->mode == LWSCM_WSCL_ISSUE_HTTP_BODY)
goto user_service;
@ -105,7 +113,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
wsi->pps = LWS_PPS_NONE;
lws_rx_flow_control(wsi, 1);
return 0; /* leave POLLOUT active */
goto bail_ok; /* leave POLLOUT active */
}
#endif
@ -127,16 +135,16 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
n = lws_write(wsi, &wsi->u.ws.ping_payload_buf[LWS_PRE],
wsi->u.ws.ping_payload_len, write_type);
if (n < 0)
return -1;
goto bail_die;
/* well he is sent, mark him done */
wsi->u.ws.ping_pending_flag = 0;
if (wsi->u.ws.payload_is_close)
/* oh... a close frame was it... then we are done */
return -1;
goto bail_die;
/* otherwise for PING, leave POLLOUT active either way */
return 0;
goto bail_ok;
}
if (wsi->state == LWSS_ESTABLISHED &&
@ -148,7 +156,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
n = lws_write(wsi, &wsi->u.ws.ping_payload_buf[LWS_PRE],
0, LWS_WRITE_PING);
if (n < 0)
return -1;
goto bail_die;
/*
* we apparently were able to send the PING in a reasonable time
@ -159,7 +167,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
lws_set_timeout(wsi, PENDING_TIMEOUT_WS_PONG_CHECK_GET_PONG,
wsi->context->timeout_secs);
return 0;
goto bail_ok;
}
/* Priority 4: if we are closing, not allowed to send more data frags
@ -178,16 +186,16 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
if (wsi->state == LWSS_ESTABLISHED && wsi->u.ws.tx_draining_ext) {
lwsl_ext("SERVICING TX EXT DRAINING\n");
if (lws_write(wsi, NULL, 0, LWS_WRITE_CONTINUATION) < 0)
return -1;
goto bail_die;
/* leave POLLOUT active */
return 0;
goto bail_ok;
}
/* Priority 6: user can get the callback
*/
m = lws_ext_cb_active(wsi, LWS_EXT_CB_IS_WRITEABLE, NULL, 0);
if (m)
return -1;
goto bail_die;
#ifndef LWS_NO_EXTENSIONS
if (!wsi->extension_data_pending)
goto user_service;
@ -218,7 +226,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
&eff_buf, 0);
if (m < 0) {
lwsl_err("ext reports fatal error\n");
return -1;
goto bail_die;
}
if (m)
/*
@ -234,7 +242,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
eff_buf.token_len);
if (n < 0) {
lwsl_info("closing from POLLOUT spill\n");
return -1;
goto bail_die;
}
/*
* Keep amount spilled small to minimize chance of this
@ -242,7 +250,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
if (n != eff_buf.token_len) {
lwsl_err("Unable to spill ext %d vs %d\n",
eff_buf.token_len, n);
return -1;
goto bail_die;
}
} else
continue;
@ -270,7 +278,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
* when we come back here and there's nothing more to spill.
*/
return 0;
goto bail_ok;
}
#ifndef LWS_NO_EXTENSIONS
wsi->extension_data_pending = 0;
@ -278,15 +286,31 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
user_service:
/* one shot */
if (pollfd)
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
lwsl_info("failed at set pollfd\n");
return 1;
}
if (pollfd) {
int eff = wsi->leave_pollout_active;
if (!eff)
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
lwsl_info("failed at set pollfd\n");
goto bail_die;
}
wsi->handling_pollout = 0;
/* cannot get leave_pollout_active set after the above */
if (!eff && wsi->leave_pollout_active)
/* got set inbetween sampling eff and clearing
* handling_pollout, force POLLOUT on */
lws_calllback_as_writeable(wsi);
wsi->leave_pollout_active = 0;
}
if (wsi->mode != LWSCM_WSCL_ISSUE_HTTP_BODY &&
!wsi->hdr_parsing_completed)
return 0;
goto bail_ok;
#ifdef LWS_WITH_CGI
user_service_go_again:
@ -314,7 +338,7 @@ user_service_go_again:
wsi->u.http2.requested_POLLOUT = 0;
if (!wsi->u.http2.initialized) {
lwsl_info("pollout on uninitialized http2 conn\n");
return 0;
goto bail_ok;
}
lwsl_info("%s: doing children\n", __func__);
@ -337,10 +361,30 @@ user_service_go_again:
lwsl_info("%s: completed\n", __func__);
return 0;
goto bail_ok;
notify:
#endif
wsi->handling_pollout = 0;
wsi->leave_pollout_active = 0;
return lws_calllback_as_writeable(wsi);
/*
* since these don't disable the POLLOUT, they are always doing the
* right thing for leave_pollout_active whether it was set or not.
*/
bail_ok:
wsi->handling_pollout = 0;
wsi->leave_pollout_active = 0;
return 0;
bail_die:
wsi->handling_pollout = 0;
wsi->leave_pollout_active = 0;
return -1;
}
int
@ -489,9 +533,10 @@ lws_service_flag_pending(struct lws_context *context, int tsi)
while (wsi) {
pt->fds[wsi->position_in_fds_table].revents |=
pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN;
if (pt->fds[wsi->position_in_fds_table].revents &
LWS_POLLIN)
if (pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN) {
forced = 1;
break;
}
wsi = wsi->u.ws.rx_draining_ext_list;
}
@ -688,6 +733,17 @@ completed:
}
#endif
static int
lws_is_ws_with_ext(struct lws *wsi)
{
#if defined(LWS_NO_EXTENSIONS)
return 0;
#else
return wsi->state == LWSS_ESTABLISHED &&
!!wsi->count_act_ext;
#endif
}
LWS_VISIBLE int
lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int tsi)
{
@ -839,10 +895,48 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
#endif
lwsl_debug("fd=%d, revents=%d\n", pollfd->fd, pollfd->revents);
// lwsl_debug("fd=%d, revents=%d, mode=%d, state=%d\n", pollfd->fd, pollfd->revents, (int)wsi->mode, (int)wsi->state);
if (pollfd->revents & LWS_POLLHUP)
goto close_and_handled;
#ifdef LWS_OPENSSL_SUPPORT
if ((wsi->state == LWSS_SHUTDOWN) && lws_is_ssl(wsi) && wsi->ssl)
{
n = SSL_shutdown(wsi->ssl);
lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd);
if (n == 1)
{
n = shutdown(wsi->desc.sockfd, SHUT_WR);
goto close_and_handled;
}
else if (n == 0)
{
lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN);
n = 0;
goto handled;
}
else /* n < 0 */
{
int shutdown_error = SSL_get_error(wsi->ssl, n);
lwsl_debug("SSL_shutdown returned %d, SSL_get_error: %d\n", n, shutdown_error);
if (shutdown_error == SSL_ERROR_WANT_READ) {
lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN);
n = 0;
goto handled;
} else if (shutdown_error == SSL_ERROR_WANT_WRITE) {
lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLOUT);
n = 0;
goto handled;
}
// actual error occurred, just close the connection
n = shutdown(wsi->desc.sockfd, SHUT_WR);
goto close_and_handled;
}
}
#endif
/* okay, what we came here to do... */
switch (wsi->mode) {
@ -1010,9 +1104,24 @@ read:
wsi->u.hdr.ah->rxpos;
} else {
if (wsi->mode != LWSCM_HTTP_CLIENT_ACCEPTED) {
/*
* extension may not consume everything (eg, pmd may be constrained
* as to what it can output...) has to go in per-wsi rx buf area.
* Otherwise in large temp serv_buf area.
*/
eff_buf.token = (char *)pt->serv_buf;
if (lws_is_ws_with_ext(wsi)) {
eff_buf.token_len = wsi->u.ws.rx_ubuf_alloc;
} else {
eff_buf.token_len = context->pt_serv_buf_size;
}
if (eff_buf.token_len > context->pt_serv_buf_size)
eff_buf.token_len = context->pt_serv_buf_size;
eff_buf.token_len = lws_ssl_capable_read(wsi,
pt->serv_buf, pending ? pending :
context->pt_serv_buf_size);
(unsigned char *)eff_buf.token, pending ? pending :
eff_buf.token_len);
switch (eff_buf.token_len) {
case 0:
lwsl_info("%s: zero length read\n", __func__);
@ -1025,8 +1134,7 @@ read:
lwsl_info("Closing when error\n");
goto close_and_handled;
}
eff_buf.token = (char *)pt->serv_buf;
// lwsl_notice("Actual RX %d\n", eff_buf.token_len);
}
}
@ -1092,6 +1200,8 @@ drain:
* around again it will pick up from where it
* left off.
*/
// lwsl_notice("doing lws_read from pt->serv_buf %p %p for len %d\n", pt->serv_buf, eff_buf.token, (int)eff_buf.token_len);
n = lws_read(wsi, (unsigned char *)eff_buf.token,
eff_buf.token_len);
if (n < 0) {
@ -1118,7 +1228,11 @@ drain:
pending = lws_ssl_pending(wsi);
if (pending) {
pending = pending > context->pt_serv_buf_size ?
if (lws_is_ws_with_ext(wsi))
pending = pending > wsi->u.ws.rx_ubuf_alloc ?
wsi->u.ws.rx_ubuf_alloc : pending;
else
pending = pending > context->pt_serv_buf_size ?
context->pt_serv_buf_size : pending;
goto read;
}

View file

@ -4,7 +4,7 @@
* Copyright (C) 2016 Andy Green <andy@warmcat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*

View file

@ -382,7 +382,7 @@ lws_ssl_client_connect2(struct lws *wsi)
int lws_context_init_client_ssl(struct lws_context_creation_info *info,
struct lws_vhost *vhost)
{
SSL_METHOD *method;
SSL_METHOD *method = NULL;
struct lws wsi;
unsigned long error;
const char *cipher_list = info->ssl_cipher_list;
@ -421,7 +421,14 @@ int lws_context_init_client_ssl(struct lws_context_creation_info *info,
/* basic openssl init already happened in context init */
/* choose the most recent spin of the api */
#if defined(LWS_HAVE_TLS_CLIENT_METHOD)
method = (SSL_METHOD *)TLS_client_method();
#elif defined(LWS_HAVE_TLSV1_2_CLIENT_METHOD)
method = (SSL_METHOD *)TLSv1_2_client_method();
#else
method = (SSL_METHOD *)SSLv23_client_method();
#endif
if (!method) {
error = ERR_get_error();
lwsl_err("problem creating ssl method %lu: %s\n",

View file

@ -21,6 +21,10 @@
#include "private-libwebsockets.h"
/* workaround for mingw */
#if !defined(ECONNABORTED)
#define ECONNABORTED 103
#endif
int openssl_websocket_private_data_index,
openssl_SSL_CTX_private_data_index;
@ -57,13 +61,13 @@ char* lws_ssl_get_error_string(int status, int ret, char *buf, size_t len) {
case SSL_ERROR_SYSCALL:
switch (ret) {
case 0:
snprintf(buf, len, "SSL_ERROR_SYSCALL: EOF");
lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: EOF");
return buf;
case -1:
#ifndef LWS_PLAT_OPTEE
snprintf(buf, len, "SSL_ERROR_SYSCALL: %s", strerror(errno));
lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: %s", strerror(errno));
#else
snprintf(buf, len, "SSL_ERROR_SYSCALL: %d", errno);
lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: %d", errno);
#endif
return buf;
default:

View file

@ -1,5 +1,5 @@
Name: libwebsockets
Version: 2.2.0
Version: 2.2.2
Release: 1%{?dist}
Summary: Websocket Server and Client Library
@ -60,6 +60,8 @@ rm -rf $RPM_BUILD_ROOT
/%{_libdir}/cmake/libwebsockets/LibwebsocketsConfig.cmake
/%{_libdir}/cmake/libwebsockets/LibwebsocketsConfigVersion.cmake
/%{_libdir}/cmake/libwebsockets/LibwebsocketsTargets.cmake
/%{_libdir}/cmake/libwebsockets/LibwebsocketsTargets-release.cmake
/usr/share/libwebsockets-test-server
%doc
%files devel
@ -70,6 +72,9 @@ rm -rf $RPM_BUILD_ROOT
/%{_libdir}/pkgconfig/libwebsockets.pc
%changelog
* Mon Mar 06 2017 Andy Green <andy@warmcat.com> 2.2.2-1
- MINOR Upstream 2.2.2 release
* Mon Mar 06 2017 Andy Green <andy@warmcat.com> 2.2.0-1
- MAJOR SONAMEBUMP APICHANGES Upstream 2.2.0 release

View file

@ -127,4 +127,10 @@
#cmakedefine LWS_HAVE_STDINT_H
#cmakedefine LWS_FALLBACK_GETHOSTBYNAME
/* OpenSSL various APIs */
#cmakedefine LWS_HAVE_TLS_CLIENT_METHOD
#cmakedefine LWS_HAVE_TLSV1_2_CLIENT_METHOD
${LWS_SIZEOFPTR_CODE}

View file

@ -219,11 +219,11 @@ int main(int argc, char **argv)
break;
case 'h':
fprintf(stderr, "Usage: lwsws [-c <config dir>] "
"[-d <log bitfield>] [-D] [--help]\n");
"[-d <log bitfield>] [--help]\n");
exit(1);
}
}
#ifndef _WIN32
/*
* We leave our original process up permanently, because that
* suits systemd.
@ -267,7 +267,7 @@ int main(int argc, char **argv)
// !!! implemenation needed
#endif
}
#endif
/* child process */
#ifndef _WIN32

View file

@ -17,6 +17,9 @@ set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${PACKAGE_VERSION}")
set(SOVERSION "1")
set(VERSION "0.1")
set(PLUGIN_NAME "protocol_example_standalone")
# space-separated list of sources
set(PLUGIN_SRCS protocol_example_standalone.c)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
@ -50,29 +53,21 @@ endif()
set(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
macro(create_plugin PLUGIN_NAME MAIN_SRC)
set(PLUGIN_SRCS ${MAIN_SRC})
source_group("Headers Private" FILES ${PLUGIN_HDR})
source_group("Sources" FILES ${PLUGIN_SRCS})
add_library(${PLUGIN_NAME} SHARED ${PLUGIN_SRCS} ${PLUGIN_HDR})
target_link_libraries(${PLUGIN_NAME} -lwebsockets)
# Set test app specific defines.
set_property(TARGET ${PLUGIN_NAME}
PROPERTY COMPILE_DEFINITIONS
INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/plugins"
)
list(APPEND PLUGINS_LIST ${PLUGIN_NAME})
endmacro()
source_group("Headers Private" FILES ${PLUGIN_HDR})
source_group("Sources" FILES ${PLUGIN_SRCS})
add_library(${PLUGIN_NAME} SHARED ${PLUGIN_SRCS} ${PLUGIN_HDR})
target_link_libraries(${PLUGIN_NAME} -lwebsockets)
create_plugin(protocol_example_standalone
"protocol_example_standalone.c")
# Set test app specific defines.
set_property(TARGET ${PLUGIN_NAME}
PROPERTY COMPILE_DEFINITIONS
INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/plugins"
)
list(APPEND PLUGINS_LIST ${PLUGIN_NAME})
install(TARGETS ${PLUGINS_LIST}
PERMISSIONS OWNER_WRITE OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_READ GROUP_READ WORLD_READ
DESTINATION share/libwebsockets-test-server/plugins
COMPONENT plugins)
COMPONENT plugins)

View file

@ -4,7 +4,7 @@
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*

View file

@ -4,7 +4,7 @@
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*

View file

@ -4,7 +4,7 @@
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*

View file

@ -4,7 +4,7 @@
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*

View file

@ -4,7 +4,7 @@
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*

View file

@ -4,7 +4,7 @@
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*

View file

@ -0,0 +1,333 @@
/*
* Example ESP32 app code using Libwebsockets
*
* Copyright (C) 2017 Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*
* The person who associated a work with this deed has dedicated
* the work to the public domain by waiving all of his or her rights
* to the work worldwide under copyright law, including all related
* and neighboring rights, to the extent allowed by law. You can copy,
* modify, distribute and perform the work, even for commercial purposes,
* all without asking permission.
*
* The test apps are intended to be adapted for use in your code, which
* may be proprietary. So unlike the library itself, they are licensed
* Public Domain.
*
*/
#include <string.h>
#include <nvs.h>
typedef enum {
SCAN_STATE_NONE,
SCAN_STATE_INITIAL,
SCAN_STATE_LIST,
SCAN_STATE_FINAL
} scan_state;
struct store_json {
const char *j;
const char *nvs;
};
struct per_session_data__esplws_scan {
struct per_session_data__esplws_scan *next;
scan_state scan_state;
char ap_record;
unsigned char subsequent:1;
unsigned char changed_partway:1;
};
struct per_vhost_data__esplws_scan {
wifi_ap_record_t ap_records[20];
TimerHandle_t timer;
struct per_session_data__esplws_scan *live_pss_list;
struct lws_context *context;
struct lws_vhost *vhost;
const struct lws_protocols *protocol;
uint16_t count_ap_records;
char count_live_pss;
unsigned char scan_ongoing:1;
unsigned char completed_any_scan:1;
unsigned char reboot:1;
};
static const struct store_json store_json[] = {
{ "ssid\":\"", "ssid" },
{ ",\"pw\":\"", "password" },
{ ",\"serial\":\"", "serial" },
{ ",\"region\":\"", "region" },
};
static wifi_scan_config_t scan_config = {
.ssid = 0,
.bssid = 0,
.channel = 0,
.show_hidden = true
};
extern void (*lws_cb_scan_done)(void *);
extern void *lws_cb_scan_done_arg;
static void
scan_finished(void *v);
static int
esplws_simple_arg(char *dest, int len, const char *in, const char *match)
{
const char *p = strstr(in, match);
int n = 0;
if (!p) {
lwsl_err("No match %s\n", match);
return 1;
}
p += strlen(match);
while (*p && *p != '\"' && n < len - 1)
dest[n++] = *p++;
dest[n] = '\0';
return 0;
}
static void
scan_start(struct per_vhost_data__esplws_scan *vhd)
{
int n;
if (vhd->reboot)
esp_restart();
if (vhd->scan_ongoing)
return;
vhd->scan_ongoing = 1;
lws_cb_scan_done = scan_finished;
lws_cb_scan_done_arg = vhd;
n = esp_wifi_scan_start(&scan_config, false);
if (n != ESP_OK)
lwsl_err("scan start failed %d\n", n);
}
static void timer_cb(TimerHandle_t t)
{
struct per_vhost_data__esplws_scan *vhd = pvTimerGetTimerID(t);
scan_start(vhd);
}
static void
scan_finished(void *v)
{
struct per_vhost_data__esplws_scan *vhd = v;
struct per_session_data__esplws_scan *p = vhd->live_pss_list;
vhd->scan_ongoing = 0;
vhd->count_ap_records = ARRAY_SIZE(vhd->ap_records);
if (esp_wifi_scan_get_ap_records(&vhd->count_ap_records, vhd->ap_records) != ESP_OK) {
lwsl_err("%s: failed\n", __func__);
return;
}
while (p) {
if (p->scan_state != SCAN_STATE_INITIAL && p->scan_state != SCAN_STATE_NONE)
p->changed_partway = 1;
else
p->scan_state = SCAN_STATE_INITIAL;
p = p->next;
}
lws_callback_on_writable_all_protocol(vhd->context, vhd->protocol);
}
static int
callback_esplws_scan(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
struct per_session_data__esplws_scan *pss =
(struct per_session_data__esplws_scan *)user;
struct per_vhost_data__esplws_scan *vhd =
(struct per_vhost_data__esplws_scan *)
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
lws_get_protocol(wsi));
char buf[LWS_PRE + 384], /*ip[24],*/ *start = buf + LWS_PRE - 1, *p = start,
*end = buf + sizeof(buf) - 1;
wifi_ap_record_t *r;
int n, m;
switch (reason) {
case LWS_CALLBACK_PROTOCOL_INIT:
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
lws_get_protocol(wsi),
sizeof(struct per_vhost_data__esplws_scan));
vhd->context = lws_get_context(wsi);
vhd->protocol = lws_get_protocol(wsi);
vhd->vhost = lws_get_vhost(wsi);
vhd->timer = xTimerCreate("x", pdMS_TO_TICKS(10000), 1, vhd,
(TimerCallbackFunction_t)timer_cb);
xTimerStart(vhd->timer, 0);
vhd->scan_ongoing = 0;
scan_start(vhd);
break;
case LWS_CALLBACK_PROTOCOL_DESTROY:
if (!vhd)
break;
xTimerStop(vhd->timer, 0);
xTimerDelete(vhd->timer, 0);
break;
case LWS_CALLBACK_ESTABLISHED:
vhd->count_live_pss++;
pss->next = vhd->live_pss_list;
vhd->live_pss_list = pss;
/* if we have scan results, update them. Otherwise wait */
if (vhd->count_ap_records) {
pss->scan_state = SCAN_STATE_INITIAL;
lws_callback_on_writable(wsi);
}
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
switch (pss->scan_state) {
case SCAN_STATE_INITIAL:
n = LWS_WRITE_TEXT | LWS_WRITE_NO_FIN;;
p += snprintf(p, end - p,
"{ \"model\":\"%s\","
" \"serial\":\"%s\","
" \"host\":\"%s-%s\","
" \"region\":\"%d\","
" \"aps\":[",
lws_esp32_model,
lws_esp32_serial,
lws_esp32_model, lws_esp32_serial,
lws_esp32_region);
pss->scan_state = SCAN_STATE_LIST;
pss->ap_record = 0;
pss->subsequent = 0;
break;
case SCAN_STATE_LIST:
n = LWS_WRITE_CONTINUATION | LWS_WRITE_NO_FIN;
if (pss->ap_record >= vhd->count_ap_records)
goto scan_state_final;
if (pss->subsequent)
*p++ = ',';
pss->subsequent = 1;
r = &vhd->ap_records[(int)pss->ap_record++];
p += snprintf(p, end - p,
"{\"ssid\":\"%s\","
"\"bssid\":\"%02X:%02X:%02X:%02X:%02X:%02X\","
"\"rssi\":\"%d\","
"\"chan\":\"%d\","
"\"auth\":\"%d\"}",
r->ssid,
r->bssid[0], r->bssid[1], r->bssid[2],
r->bssid[3], r->bssid[4], r->bssid[5],
r->rssi, r->primary, r->authmode);
if (pss->ap_record >= vhd->count_ap_records)
pss->scan_state = SCAN_STATE_FINAL;
break;
case SCAN_STATE_FINAL:
scan_state_final:
n = LWS_WRITE_CONTINUATION;
p += sprintf(p, "]}");
if (pss->changed_partway) {
pss->subsequent = 0;
pss->scan_state = SCAN_STATE_INITIAL;
} else
pss->scan_state = SCAN_STATE_NONE;
break;
default:
return 0;
}
m = lws_write(wsi, (unsigned char *)start, p - start, n);
if (m < 0) {
lwsl_err("ERROR %d writing to di socket\n", m);
return -1;
}
if (pss->scan_state != SCAN_STATE_NONE)
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_RECEIVE:
{
nvs_handle nvh;
char p[64];
int n;
if (strstr((const char *)in, "identify")) {
lws_esp32_identify_physical_device();
break;
}
if (nvs_open("lws-station", NVS_READWRITE, &nvh) != ESP_OK) {
lwsl_err("Unable to open nvs\n");
break;
}
for (n = 0; n < ARRAY_SIZE(store_json); n++) {
if (esplws_simple_arg(p, sizeof(p), in, store_json[n].j))
goto bail_nvs;
if (nvs_set_str(nvh, store_json[n].nvs, p) != ESP_OK) {
lwsl_err("Unable to store %s in nvm\n", store_json[n].nvs);
goto bail_nvs;
}
}
nvs_commit(nvh);
nvs_close(nvh);
vhd->reboot = 1;
break;
bail_nvs:
nvs_close(nvh);
return 1;
}
case LWS_CALLBACK_CLOSED:
{
struct per_session_data__esplws_scan **p = &vhd->live_pss_list;
while (*p) {
if ((*p) == pss) {
*p = pss->next;
continue;
}
p = &((*p)->next);
}
vhd->count_live_pss--;
}
break;
default:
break;
}
return 0;
}
#define LWS_PLUGIN_PROTOCOL_ESPLWS_SCAN \
{ \
"esplws-scan", \
callback_esplws_scan, \
sizeof(struct per_session_data__esplws_scan), \
512, 0, NULL \
}

View file

@ -95,7 +95,7 @@ uv_timeout_cb_server_status(uv_timer_t *w
l -= n;
}
fd = open(fp->filepath, LWS_O_RDONLY);
if (fd != LWS_INVALID_FILE) {
if (fd >= 0) {
n = read(fd, contents, sizeof(contents) - 1);
if (n >= 0) {
contents[n] = '\0';

View file

@ -200,6 +200,11 @@ walk_final:
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_RECEIVE:
lwsl_notice("pmd test: RX len %d\n", (int)len);
puts(in);
break;
case LWS_CALLBACK_CLOSED:
pss1 = vhd->live_pss_list;
pss2 = NULL;

View file

@ -74,7 +74,7 @@ file_upload_cb(void *data, const char *name, const char *filename,
* simple demo use a fixed name so we don't have to deal with
* attacks */
#if !defined(LWS_WITH_ESP8266)
pss->fd = open("/tmp/post-file",
pss->fd = (lws_filefd_type)open("/tmp/post-file",
O_CREAT | O_TRUNC | O_RDWR, 0600);
#endif
break;
@ -88,7 +88,7 @@ file_upload_cb(void *data, const char *name, const char *filename,
return 1;
#if !defined(LWS_WITH_ESP8266)
n = write(pss->fd, buf, len);
n = write((int)pss->fd, buf, len);
lwsl_notice("%s: write %d says %d\n", __func__, len, n);
#else
lwsl_notice("%s: Received chunk size %d\n", __func__, len);
@ -97,7 +97,7 @@ file_upload_cb(void *data, const char *name, const char *filename,
if (state == LWS_UFS_CONTENT)
break;
#if !defined(LWS_WITH_ESP8266)
close(pss->fd);
close((int)pss->fd);
pss->fd = LWS_INVALID_FILE;
#endif
break;

View file

@ -147,7 +147,7 @@ file_upload_cb(void *data, const char *name, const char *filename,
/* we get the original filename in @filename arg, but for
* simple demo use a fixed name so we don't have to deal with
* attacks */
pss->post_fd = open("/tmp/post-file",
pss->post_fd = (lws_filefd_type)open("/tmp/post-file",
O_CREAT | O_TRUNC | O_RDWR, 0600);
break;
case LWS_UFS_FINAL_CONTENT:
@ -159,12 +159,12 @@ file_upload_cb(void *data, const char *name, const char *filename,
if (pss->file_length > 100000)
return 1;
n = write(pss->post_fd, buf, len);
n = write((int)pss->post_fd, buf, len);
lwsl_notice("%s: write %d says %d\n", __func__, len, n);
}
if (state == LWS_UFS_CONTENT)
break;
close(pss->post_fd);
close((int)pss->post_fd);
pss->post_fd = LWS_INVALID_FILE;
break;
}
@ -184,7 +184,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
struct per_session_data__http *pss =
(struct per_session_data__http *)user;
unsigned char buffer[4096 + LWS_PRE];
unsigned long amount, file_len, sent;
lws_filepos_t amount, file_len, sent;
char leaf_path[1024];
const char *mimetype;
char *other_headers;

View file

@ -131,6 +131,11 @@ callback_lws_status(struct lws *wsi, enum lws_callback_reasons reason,
update_status(wsi, pss);
break;
case LWS_CALLBACK_RECEIVE:
lwsl_notice("pmd test: RX len %d\n", (int)len);
puts(in);
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
m = lws_write(wsi, (unsigned char *)cache + LWS_PRE, cache_len,
LWS_WRITE_TEXT);

File diff suppressed because one or more lines are too long