Compare commits

..

54 commits
temp ... master

Author SHA1 Message Date
7f6db4fe8d fix Spec file by adding / removing new files to the package 2017-08-27 14:59:52 +02:00
Andy Green
debb7aa043 LWS_WITH_ACCESS_LOG: add referrer to log format and quotes around user agent
This also forces any double-quotes in the UA or referrer to be single-quotes.

This aligns to log to the "combined log format" described here

https://httpd.apache.org/docs/1.3/logs.html#combined
2017-08-27 20:18:48 +08:00
Andy Green
ca045d4a8e docs: lwsws under gdb / valgrind from ml 2017-08-27 09:50:04 +08:00
Andy Green
4ce725903d lwsws: survive LWS_WITHOUT_EXTENSIONS 2017-08-26 12:18:47 +08:00
Petar Paradzik
a2943ca41d cgi: fix killing cgi before draining its output
CGI's which don't have content-length nor they are explicitly chunked
are killed immediately after being reaped even if their output has not
being drained. This is fixed by deferring from killing them like those
which are explicitly chunked.

Signed-off-by: Petar Paradzik <petar.paradzik@sartura.hr>
2017-08-26 12:16:33 +08:00
Petar Paradzik
04134742f9 cgi: fix overriding 'PATH' environment variable
Signed-off-by: Petar Paradzik <petar.paradzik@sartura.hr>
2017-08-26 12:15:51 +08:00
Andy Green
2e5110e731 cgi: provide constants for reason_bf 2017-08-26 12:15:40 +08:00
Petar Paradzik
afc9c0ac26 cgi: add support for manual chunking of CGI output
In cases when CGI output doesn't contain content-length nor it is
explicitly chunked, do manual chunking of CGI output.

Signed-off-by: Petar Paradzik <petar.paradzik@sartura.hr>
2017-08-26 12:04:15 +08:00
Petar Paradzik
5b23b8c99f cgi: remove and kill CGI after closing its STDOUT handler
Signed-off-by: Petar Paradzik <petar.paradzik@sartura.hr>
2017-08-26 12:00:16 +08:00
Petar Paradzik
b66e8e1898 cgi: fix not getting POLLHUP on fd associated to CGI STDOUT
Signed-off-by: Petar Paradzik <petar.paradzik@sartura.hr>
2017-08-26 11:59:58 +08:00
Mike Messina
0bb3646256 win32: skip delay in WSAWaitForMultipleEvents if POLLOUT expected
https://github.com/warmcat/libwebsockets/issues/994
2017-08-22 21:32:47 +08:00
Andy Green
c60b2413a4 ah: double-check timeouts on all active ah independent of wsi and dump info 2017-08-21 08:55:13 +08:00
Andy Green
58195fbc1e esp-idf v3: account for optional SHA256 when walking segments 2017-08-19 13:14:34 +08:00
Andy Green
c2abf59c68 esp32: align build system for esp-idf v3 2017-08-19 08:14:49 +08:00
Cory McWilliams
4b24369d64 Subject: Mismatched lws_zalloc / free 2017-08-17 07:30:23 +08:00
Andy Green
872e8d7e9d docs: swap _all_protocol_vhost cut and paste
https://github.com/warmcat/libwebsockets/issues/989
2017-08-16 15:21:22 +08:00
Andy Green
5da9ce2f06 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 07:58:53 +08:00
lnmx
b93c057472 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:50:25 +08:00
Andy Green
5a38d88fdd handle same vh protocol reinsert 2017-08-12 20:50:21 +08:00
Andy Green
a9f74f2dbe lwsws: remove no longer extant D option from help string
https://github.com/warmcat/libwebsockets/issues/986
2017-08-09 07:40:19 +08:00
Andy Green
219a367a4c esp32: allow return of default vhost at init time 2017-08-06 06:53:38 +08:00
Andy Green
93a5b586a3 lws_callback_all_protocol_vhost_args 2017-08-05 10:38:59 +08:00
Andy Green
040b408029 ping test app: avoid FPE when no packets received 2017-08-04 13:28:01 +08:00
Andy Green
16ef37ef5d close path: make sure a second time timeout and ssl buffered lists are scrubbed
lws_meta children can have a different close path
2017-08-04 13:27:34 +08:00
Andy Green
e6bd6296bd v2.3.0 2017-07-28 14:27:25 +08:00
Andy Green
4a9c23e9ec coverity 182069: coverity confused by use of bool as array index 2017-07-28 14:25:25 +08:00
Andy Green
c6233ce403 coverity 182068: 155650: unnecessary check against illegal NULL 2017-07-28 14:19:24 +08:00
Andy Green
7849c5a8ad pmd: autobahn fixes 2017-07-28 13:12:03 +08:00
Andy Green
414f114b8f attack.sh: adapt to changes 2017-07-28 07:04:54 +08:00
Andy Green
855f7e8712 log: downgrade logging for ah wait 2017-07-28 07:04:47 +08:00
Andy Green
9f31e94e09 correct status payload size 2017-07-28 07:03:57 +08:00
Andy Green
855453d1ae lws_meta: explicitly declare all of lws_protocols members for ESP32 2017-07-27 08:27:34 +08:00
Andy Green
d86641ed3a libevent: update to use static plugins and work with new libevent2
Plus fix broken indent style
2017-07-27 07:57:59 +08:00
Andy Green
41c15511eb test-server-libuv: add lws_meta 2017-07-27 07:29:56 +08:00
Andy Green
d766c99861 dummy handler: LWS_CALLBACK_HTTP_FILE_COMPLETION 2017-07-27 07:26:00 +08:00
Andy Green
ba45f7cf9f ah: allow configurable ah hold timeout 2017-07-26 11:49:41 +08:00
Andy Green
19a320a578 http2: remove cmake option leave code in for now
https://github.com/warmcat/libwebsockets/issues/979
2017-07-25 17:36:31 +08:00
namowen
61e58885f4 client: ipv6 reject when lws_getaddrinfo46 failed
https://github.com/warmcat/libwebsockets/issues/978
2017-07-25 17:14:37 +08:00
Andy Green
3562e441e3 client-fix-header-stash-leak-on-close-before-success 2017-07-21 21:49:24 +08:00
Andy Green
003bd7dcee client: fix hdr stash leak 2017-07-21 21:34:46 +08:00
Andy Green
75bbb3b2c0 client: always set port even if sockfd already created 2017-07-21 21:34:46 +08:00
Andy Green
8ccc64679f client: fix redirect ssl to ssl 2017-07-21 20:25:32 +08:00
Andy Green
6c09952065 url cleaning: leave // after http[s]: alone 2017-07-21 20:04:02 +08:00
Andy Green
09f3947b4c lws_intptr_t: fix ordering
https://github.com/warmcat/libwebsockets/issues/973
2017-07-21 19:25:41 +08:00
Andy Green
941e93ea33 test-server-libuv: also call context_destroy2 when using foreign loop
https://github.com/warmcat/libwebsockets/issues/972
2017-07-21 11:09:03 +08:00
Andy Green
c9da1ffa2e appveyor: remove cache 2017-07-19 15:29:38 +08:00
Andy Green
ad15082563 coverity-181580: supposedly dead code 2017-07-19 14:47:30 +08:00
Andy Green
2d313bdc02 coverity 181577: lejp_conf loop on calling uv_loop_close to keep coverity happy 2017-07-19 14:37:04 +08:00
Andy Green
3526fde154 coverity 181573: false positive since lws_is_ssl returns a bool 2017-07-19 14:37:04 +08:00
Andy Green
bd1dd7efd4 coverity 181576: remove dead code to keep coverity happy 2017-07-19 14:37:04 +08:00
Andy Green
1690581cd2 coverity 181574: confirm uri_ptr non-null before deref 2017-07-19 14:19:03 +08:00
Andy Green
3c360d5192 coverity 181579: check result of malloc as intended 2017-07-19 14:17:39 +08:00
Andy Green
8a4881a142 coverity 181575: check vhost iface non-null if using via bind_iface 2017-07-19 14:16:32 +08:00
Andy Green
6f11c1361a lws-meta 2017-07-19 08:59:42 +08:00
37 changed files with 827 additions and 440 deletions

View file

@ -11,7 +11,6 @@ env:
- LWS_METHOD=noext CMAKE_ARGS="-DLWS_WITHOUT_EXTENSIONS=ON" - LWS_METHOD=noext CMAKE_ARGS="-DLWS_WITHOUT_EXTENSIONS=ON"
- LWS_METHOD=libev CMAKE_ARGS="-DLWS_WITH_LIBEV=ON" - LWS_METHOD=libev CMAKE_ARGS="-DLWS_WITH_LIBEV=ON"
- LWS_METHOD=noipv6 CMAKE_ARGS="-DLWS_IPV6=OFF" - LWS_METHOD=noipv6 CMAKE_ARGS="-DLWS_IPV6=OFF"
- LWS_METHOD=http2 CMAKE_ARGS="-DLWS_WITH_HTTP2=ON"
- LWS_METHOD=nossl CMAKE_ARGS="-DLWS_WITH_SSL=OFF" - LWS_METHOD=nossl CMAKE_ARGS="-DLWS_WITH_SSL=OFF"
- LWS_METHOD=nodaemon CMAKE_ARGS="-DLWS_WITHOUT_DAEMONIZE=ON" - LWS_METHOD=nodaemon CMAKE_ARGS="-DLWS_WITHOUT_DAEMONIZE=ON"
- LWS_METHOD=cgi CMAKE_ARGS="-DLWS_WITH_CGI=ON" - LWS_METHOD=cgi CMAKE_ARGS="-DLWS_WITH_CGI=ON"

View file

@ -9,12 +9,12 @@ project(libwebsockets C)
set(PACKAGE "libwebsockets") set(PACKAGE "libwebsockets")
set(CPACK_PACKAGE_NAME "${PACKAGE}") set(CPACK_PACKAGE_NAME "${PACKAGE}")
set(CPACK_PACKAGE_VERSION_MAJOR "2") set(CPACK_PACKAGE_VERSION_MAJOR "2")
set(CPACK_PACKAGE_VERSION_MINOR "2") set(CPACK_PACKAGE_VERSION_MINOR "3")
set(CPACK_PACKAGE_VERSION_PATCH "0") set(CPACK_PACKAGE_VERSION_PATCH "0")
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") 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_VENDOR "andy@warmcat.com")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${PACKAGE_VERSION}") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${PACKAGE_VERSION}")
set(SOVERSION "10") set(SOVERSION "11")
if(NOT CPACK_GENERATOR) if(NOT CPACK_GENERATOR)
if(UNIX) if(UNIX)
set(CPACK_GENERATOR "TGZ") set(CPACK_GENERATOR "TGZ")
@ -95,7 +95,7 @@ option(LWS_WITH_LATENCY "Build latency measuring code into the library" OFF)
option(LWS_WITHOUT_DAEMONIZE "Don't build the daemonization api" ON) option(LWS_WITHOUT_DAEMONIZE "Don't build the daemonization api" ON)
option(LWS_IPV6 "Compile with support for ipv6" OFF) option(LWS_IPV6 "Compile with support for ipv6" OFF)
option(LWS_UNIX_SOCK "Compile with support for UNIX domain socket" OFF) option(LWS_UNIX_SOCK "Compile with support for UNIX domain socket" OFF)
option(LWS_WITH_HTTP2 "Compile with support for http2" OFF) #option(LWS_WITH_HTTP2 "Compile with support for http2" OFF)
option(LWS_SSL_SERVER_WITH_ECDH_CERT "Include SSL server use ECDH certificate" OFF) option(LWS_SSL_SERVER_WITH_ECDH_CERT "Include SSL server use ECDH certificate" OFF)
option(LWS_WITH_CGI "Include CGI (spawn process with network-connected stdin/out/err) APIs" OFF) option(LWS_WITH_CGI "Include CGI (spawn process with network-connected stdin/out/err) APIs" OFF)
option(LWS_WITH_HTTP_PROXY "Support for rewriting HTTP proxying (requires libhubbub)" OFF) option(LWS_WITH_HTTP_PROXY "Support for rewriting HTTP proxying (requires libhubbub)" OFF)

View file

@ -576,3 +576,26 @@ Prepare the log directory like this
sudo mkdir /var/log/lwsws sudo mkdir /var/log/lwsws
sudo chmod 700 /var/log/lwsws sudo chmod 700 /var/log/lwsws
``` ```
@section lwswsgdb Debugging lwsws with gdb
Hopefully you won't need to debug lwsws itself, but you may want to debug your plugins. start lwsws like this to have everything running under gdb
```
sudo gdb -ex "set follow-fork-mode child" -ex "run" --args /usr/local/bin/lwsws
```
this will give nice backtraces in lwsws itself and in plugins, if they were built with symbols.
@section lwswsvgd Running lwsws under valgrind
You can just run lwsws under galgrind as usual and get valid results. However the results / analysis part of valgrind runs
after the plugins have removed themselves, this means valgrind backtraces into plugin code is opaque, without
source-level info because the dynamic library is gone.
There's a simple workaround, use LD_PRELOAD=<plugin.so> before running lwsws, this has the loader bring the plugin
in before executing lwsws as if it was a direct dependency. That means it's still mapped until the whole process
exits after valgtind has done its thing.

View file

@ -8,14 +8,13 @@ libwebsockets
News News
---- ----
v2.3 is out... see the changelog https://github.com/warmcat/libwebsockets/blob/v2.3-stable/changelog
ESP32 is now supported in lws! Download the ESP32 is now supported in lws! Download the
- factory https://github.com/warmcat/lws-esp32-factory and - factory https://github.com/warmcat/lws-esp32-factory and
- test server app https://github.com/warmcat/lws-esp32-test-server-demos - test server app https://github.com/warmcat/lws-esp32-test-server-demos
v2.2 is out... see the changelog https://github.com/warmcat/libwebsockets/blob/v2.2-stable/changelog
This is the libwebsockets C library for lightweight websocket clients and This is the libwebsockets C library for lightweight websocket clients and
servers. For support, visit servers. For support, visit

View file

@ -22,8 +22,8 @@ install:
- mkdir c:\assets\libuv - mkdir c:\assets\libuv
- 7z x -oc:\assets\libuv win-libuv.zip - 7z x -oc:\assets\libuv win-libuv.zip
# - appveyor DownloadFile https://slproweb.com/download/Win32OpenSSL-1_0_2h.exe # - appveyor DownloadFile https://slproweb.com/download/Win32OpenSSL-1_0_2h.exe
- appveyor DownloadFile https://libwebsockets.org:444/Win32OpenSSL-1_0_2h.exe # - appveyor DownloadFile https://libwebsockets.org:444/Win32OpenSSL-1_0_2L.exe
- Win32OpenSSL-1_0_2h.exe /silent /verysilent /sp- /suppressmsgboxes # - Win32OpenSSL-1_0_2L.exe /silent /verysilent /sp- /suppressmsgboxes
- appveyor DownloadFile https://libwebsockets.org:444/nsis-3.0rc1-setup.exe - appveyor DownloadFile https://libwebsockets.org:444/nsis-3.0rc1-setup.exe
- cmd /c start /wait nsis-3.0rc1-setup.exe /S /D=C:\nsis - cmd /c start /wait nsis-3.0rc1-setup.exe /S /D=C:\nsis
- appveyor DownloadFile https://libwebsockets.org:444/sqlite-dll-win32-x86-3130000.zip - appveyor DownloadFile https://libwebsockets.org:444/sqlite-dll-win32-x86-3130000.zip
@ -51,8 +51,8 @@ artifacts:
name: lws.zip name: lws.zip
type: Zip type: Zip
cache: #cache:
- C:\OpenSSL-Win32 # - C:\OpenSSL-Win32
matrix: matrix:
fast_finish: true fast_finish: true

View file

@ -6,7 +6,7 @@ N=1
OS=`uname` OS=`uname`
for i in '1.1.1' '1.1.2' '1.1.3' '1.1.4' '1.1.5' '1.1.6' '1.1.7' '1.1.8' '1.2.1' '1.2.2' '1.2.3' '1.2.4' '1.2.5' '1.2.6' '1.2.7' '1.2.8' '2.1' '2.2' '2.3' '2.4' '2.5' '2.6' '2.7' '2.8' '2.9' '2.10' '2.11' '3.1' '3.2' '3.3' '3.4' '3.5' '3.6' '3.7' '4.1.1' '4.1.2' '4.1.3' '4.1.4' '4.1.5' '4.2.1' '4.2.2' '4.2.3' '4.2.4' '4.2.5' '5.1' '5.2' '5.3' '5.4' '5.5' '5.6' '5.7' '5.8' '5.9' '5.10' '5.11' '5.12' '5.13' '5.14' '5.15' '5.16' '5.17' '5.18' '5.19' '5.20' '6.1.1' '6.1.2' '6.1.3' '6.2.1' '6.2.2' '6.2.3' '6.2.4' '6.3.1' '6.3.2' '6.4.1' '6.4.2' '6.4.3' '6.4.4' '6.5.1' '6.5.2' '6.5.3' '6.5.4' '6.5.5' '6.6.1' '6.6.2' '6.6.3' '6.6.4' '6.6.5' '6.6.6' '6.6.7' '6.6.8' '6.6.9' '6.6.10' '6.6.11' '6.7.1' '6.7.2' '6.7.3' '6.7.4' '6.8.1' '6.8.2' '6.9.1' '6.9.2' '6.9.3' '6.9.4' '6.10.1' '6.10.2' '6.10.3' '6.11.1' '6.11.2' '6.11.3' '6.11.4' '6.11.5' '6.12.1' '6.12.2' '6.12.3' '6.12.4' '6.12.5' '6.12.6' '6.12.7' '6.12.8' '6.13.1' '6.13.2' '6.13.3' '6.13.4' '6.13.5' '6.14.1' '6.14.2' '6.14.3' '6.14.4' '6.14.5' '6.14.6' '6.14.7' '6.14.8' '6.14.9' '6.14.10' '6.15.1' '6.16.1' '6.16.2' '6.16.3' '6.17.1' '6.17.2' '6.17.3' '6.17.4' '6.17.5' '6.18.1' '6.18.2' '6.18.3' '6.18.4' '6.18.5' '6.19.1' '6.19.2' '6.19.3' '6.19.4' '6.19.5' '6.20.1' '6.20.2' '6.20.3' '6.20.4' '6.20.5' '6.20.6' '6.20.7' '6.21.1' '6.21.2' '6.21.3' '6.21.4' '6.21.5' '6.21.6' '6.21.7' '6.21.8' '6.22.1' '6.22.2' '6.22.3' '6.22.4' '6.22.5' '6.22.6' '6.22.7' '6.22.8' '6.22.9' '6.22.10' '6.22.11' '6.22.12' '6.22.13' '6.22.14' '6.22.15' '6.22.16' '6.22.17' '6.22.18' '6.22.19' '6.22.20' '6.22.21' '6.22.22' '6.22.23' '6.22.24' '6.22.25' '6.22.26' '6.22.27' '6.22.28' '6.22.29' '6.22.30' '6.22.31' '6.22.32' '6.22.33' '6.22.34' '6.23.1' '6.23.2' '6.23.3' '6.23.4' '6.23.5' '6.23.6' '6.23.7' '7.1.1' '7.1.2' '7.1.3' '7.1.4' '7.1.5' '7.1.6' '7.3.1' '7.3.2' '7.3.3' '7.3.4' '7.3.5' '7.3.6' '7.5.1' '7.7.1' '7.7.2' '7.7.3' '7.7.4' '7.7.5' '7.7.6' '7.7.7' '7.7.8' '7.7.9' '7.7.10' '7.7.11' '7.7.12' '7.7.13' '7.9.1' '7.9.2' '7.9.3' '7.9.4' '7.9.5' '7.9.6' '7.9.7' '7.9.8' '7.9.9' '7.9.10' '7.9.11' '7.9.12' '7.9.13' '7.13.1' '7.13.2' '9.1.1' '9.1.2' '9.1.3' '9.1.4' '9.1.5' '9.1.6' '9.2.1' '9.2.2' '9.2.3' '9.2.4' '9.2.5' '9.2.6' '9.3.1' '9.3.2' '9.3.3' '9.3.4' '9.3.5' '9.3.6' '9.3.7' '9.3.8' '9.3.9' '9.4.1' '9.4.2' '9.4.3' '9.4.4' '9.4.5' '9.4.6' '9.4.7' '9.4.8' '9.4.9' '9.5.1' '9.5.2' '9.5.3' '9.5.4' '9.5.5' '9.5.6' '9.6.1' '9.6.2' '9.6.3' '9.6.4' '9.6.5' '9.6.6' '9.7.1' '9.7.2' '9.7.3' '9.7.4' '9.7.5' '9.7.6' '9.8.1' '9.8.2' '9.8.3' '9.8.4' '9.8.5' '9.8.6' '10.1.1' '12.1.1' '12.1.2' '12.1.3' '12.1.4' '12.1.5' '12.1.6' '12.1.7' '12.1.8' '12.1.9' '12.1.10' '12.1.11' '12.1.12' '12.1.13' '12.1.14' '12.1.15' '12.1.16' '12.1.17' '12.1.18' '12.2.1' '12.2.2' '12.2.3' '12.2.4' '12.2.5' '12.2.6' '12.2.7' '12.2.8' '12.2.9' '12.2.10' '12.2.11' '12.2.12' '12.2.13' '12.2.14' '12.2.15' '12.2.16' '12.2.17' '12.2.18' '12.3.1' '12.3.2' '12.3.3' '12.3.4' '12.3.5' '12.3.6' '12.3.7' '12.3.8' '12.3.9' '12.3.10' '12.3.11' '12.3.12' '12.3.13' '12.3.14' '12.3.15' '12.3.16' '12.3.17' '12.3.18' '12.4.1' '12.4.2' '12.4.3' '12.4.4' '12.4.5' '12.4.6' '12.4.7' '12.4.8' '12.4.9' '12.4.10' '12.4.11' '12.4.12' '12.4.13' '12.4.14' '12.4.15' '12.4.16' '12.4.17' '12.4.18' '12.5.1' '12.5.2' '12.5.3' '12.5.4' '12.5.5' '12.5.6' '12.5.7' '12.5.8' '12.5.9' '12.5.10' '12.5.11' '12.5.12' '12.5.13' '12.5.14' '12.5.15' '12.5.16' '12.5.17' '12.5.18' '13.1.1' '13.1.2' '13.1.3' '13.1.4' '13.1.5' '13.1.6' '13.1.7' '13.1.8' '13.1.9' '13.1.10' '13.1.11' '13.1.12' '13.1.13' '13.1.14' '13.1.15' '13.1.16' '13.1.17' '13.1.18' '13.2.1' '13.2.2' '13.2.3' '13.2.4' '13.2.5' '13.2.6' '13.2.7' '13.2.8' '13.2.9' '13.2.10' '13.2.11' '13.2.12' '13.2.13' '13.2.14' '13.2.15' '13.2.16' '13.2.17' '13.2.18' '13.3.1' '13.3.2' '13.3.3' '13.3.4' '13.3.5' '13.3.6' '13.3.7' '13.3.8' '13.3.9' '13.3.10' '13.3.11' '13.3.12' '13.3.13' '13.3.14' '13.3.15' '13.3.16' '13.3.17' '13.3.18' '13.4.1' '13.4.2' '13.4.3' '13.4.4' '13.4.5' '13.4.6' '13.4.7' '13.4.8' '13.4.9' '13.4.10' '13.4.11' '13.4.12' '13.4.13' '13.4.14' '13.4.15' '13.4.16' '13.4.17' '13.4.18' '13.5.1' '13.5.2' '13.5.3' '13.5.4' '13.5.5' '13.5.6' '13.5.7' '13.5.8' '13.5.9' '13.5.10' '13.5.11' '13.5.12' '13.5.13' '13.5.14' '13.5.15' '13.5.16' '13.5.17' '13.5.18' '13.6.1' '13.6.2' '13.6.3' '13.6.4' '13.6.5' '13.6.6' '13.6.7' '13.6.8' '13.6.9' '13.6.10' '13.6.11' '13.6.12' '13.6.13' '13.6.14' '13.6.15' '13.6.16' '13.6.17' '13.6.18' '13.7.1' '13.7.2' '13.7.3' '13.7.4' '13.7.5' '13.7.6' '13.7.7' '13.7.8' '13.7.9' '13.7.10' '13.7.11' '13.7.12' '13.7.13' '13.7.14' '13.7.15' '13.7.16' '13.7.17' '13.7.18' ; do for i in '1.1.1' '1.1.2' '1.1.3' '1.1.4' '1.1.5' '1.1.6' '1.1.7' '1.1.8' '1.2.1' '1.2.2' '1.2.3' '1.2.4' '1.2.5' '1.2.6' '1.2.7' '1.2.8' '2.1' '2.2' '2.3' '2.4' '2.5' '2.6' '2.7' '2.8' '2.9' '2.10' '2.11' '3.1' '3.2' '3.3' '3.4' '3.5' '3.6' '3.7' '4.1.1' '4.1.2' '4.1.3' '4.1.4' '4.1.5' '4.2.1' '4.2.2' '4.2.3' '4.2.4' '4.2.5' '5.1' '5.2' '5.3' '5.4' '5.5' '5.6' '5.7' '5.8' '5.9' '5.10' '5.11' '5.12' '5.13' '5.14' '5.15' '5.16' '5.17' '5.18' '5.19' '5.20' '6.1.1' '6.1.2' '6.1.3' '6.2.1' '6.2.2' '6.2.3' '6.2.4' '6.3.1' '6.3.2' '6.4.1' '6.4.2' '6.4.3' '6.4.4' '6.5.1' '6.5.2' '6.5.3' '6.5.4' '6.5.5' '6.6.1' '6.6.2' '6.6.3' '6.6.4' '6.6.5' '6.6.6' '6.6.7' '6.6.8' '6.6.9' '6.6.10' '6.6.11' '6.7.1' '6.7.2' '6.7.3' '6.7.4' '6.8.1' '6.8.2' '6.9.1' '6.9.2' '6.9.3' '6.9.4' '6.10.1' '6.10.2' '6.10.3' '6.11.1' '6.11.2' '6.11.3' '6.11.4' '6.11.5' '6.12.1' '6.12.2' '6.12.3' '6.12.4' '6.12.5' '6.12.6' '6.12.7' '6.12.8' '6.13.1' '6.13.2' '6.13.3' '6.13.4' '6.13.5' '6.14.1' '6.14.2' '6.14.3' '6.14.4' '6.14.5' '6.14.6' '6.14.7' '6.14.8' '6.14.9' '6.14.10' '6.15.1' '6.16.1' '6.16.2' '6.16.3' '6.17.1' '6.17.2' '6.17.3' '6.17.4' '6.17.5' '6.18.1' '6.18.2' '6.18.3' '6.18.4' '6.18.5' '6.19.1' '6.19.2' '6.19.3' '6.19.4' '6.19.5' '6.20.1' '6.20.2' '6.20.3' '6.20.4' '6.20.5' '6.20.6' '6.20.7' '6.21.1' '6.21.2' '6.21.3' '6.21.4' '6.21.5' '6.21.6' '6.21.7' '6.21.8' '6.22.1' '6.22.2' '6.22.3' '6.22.4' '6.22.5' '6.22.6' '6.22.7' '6.22.8' '6.22.9' '6.22.10' '6.22.11' '6.22.12' '6.22.13' '6.22.14' '6.22.15' '6.22.16' '6.22.17' '6.22.18' '6.22.19' '6.22.20' '6.22.21' '6.22.22' '6.22.23' '6.22.24' '6.22.25' '6.22.26' '6.22.27' '6.22.28' '6.22.29' '6.22.30' '6.22.31' '6.22.32' '6.22.33' '6.22.34' '6.23.1' '6.23.2' '6.23.3' '6.23.4' '6.23.5' '6.23.6' '6.23.7' '7.1.1' '7.1.2' '7.1.3' '7.1.4' '7.1.5' '7.1.6' '7.3.1' '7.3.2' '7.3.3' '7.3.4' '7.3.5' '7.3.6' '7.5.1' '7.7.1' '7.7.2' '7.7.3' '7.7.4' '7.7.5' '7.7.6' '7.7.7' '7.7.8' '7.7.9' '7.7.10' '7.7.11' '7.7.12' '7.7.13' '7.9.1' '7.9.2' '7.9.3' '7.9.4' '7.9.5' '7.9.6' '7.9.7' '7.9.8' '7.9.9' '7.9.10' '7.9.11' '7.9.12' '7.9.13' '7.13.1' '7.13.2' '9.1.1' '9.1.2' '9.1.3' '9.1.4' '9.1.5' '9.1.6' '9.2.1' '9.2.2' '9.2.3' '9.2.4' '9.2.5' '9.2.6' '9.3.1' '9.3.2' '9.3.3' '9.3.4' '9.3.5' '9.3.6' '9.3.7' '9.3.8' '9.3.9' '9.4.1' '9.4.2' '9.4.3' '9.4.4' '9.4.5' '9.4.6' '9.4.7' '9.4.8' '9.4.9' '9.5.1' '9.5.2' '9.5.3' '9.5.4' '9.5.5' '9.5.6' '9.6.1' '9.6.2' '9.6.3' '9.6.4' '9.6.5' '9.6.6' '9.7.1' '9.7.2' '9.7.3' '9.7.4' '9.7.5' '9.7.6' '9.8.1' '9.8.2' '9.8.3' '9.8.4' '9.8.5' '9.8.6' '10.1.1' '12.1.1' '12.1.2' '12.1.3' '12.1.4' '12.1.5' '12.1.6' '12.1.7' '12.1.8' '12.1.9' '12.1.10' '12.1.11' '12.1.12' '12.1.13' '12.1.14' '12.1.15' '12.1.16' '12.1.17' '12.1.18' '12.2.1' '12.2.2' '12.2.3' '12.2.4' '12.2.5' '12.2.6' '12.2.7' '12.2.8' '12.2.9' '12.2.10' '12.2.11' '12.2.12' '12.2.13' '12.2.14' '12.2.15' '12.2.16' '12.2.17' '12.2.18' '12.3.1' '12.3.2' '12.3.3' '12.3.4' '12.3.5' '12.3.6' '12.3.7' '12.3.8' '12.3.9' '12.3.10' '12.3.11' '12.3.12' '12.3.13' '12.3.14' '12.3.15' '12.3.16' '12.3.17' '12.3.18' '12.4.1' '12.4.2' '12.4.3' '12.4.4' '12.4.5' '12.4.6' '12.4.7' '12.4.8' '12.4.9' '12.4.10' '12.4.11' '12.4.12' '12.4.13' '12.4.14' '12.4.15' '12.4.16' '12.4.17' '12.4.18' '12.5.1' '12.5.2' '12.5.3' '12.5.4' '12.5.5' '12.5.6' '12.5.7' '12.5.8' '12.5.9' '12.5.10' '12.5.11' '12.5.12' '12.5.13' '12.5.14' '12.5.15' '12.5.16' '12.5.17' '12.5.18' '13.1.1' '13.1.2' '13.1.3' '13.1.4' '13.1.5' '13.1.6' '13.1.7' '13.1.8' '13.1.9' '13.1.10' '13.1.11' '13.1.12' '13.1.13' '13.1.14' '13.1.15' '13.1.16' '13.1.17' '13.1.18' '13.2.1' '13.2.2' '13.2.3' '13.2.4' '13.2.5' '13.2.6' '13.2.7' '13.2.8' '13.2.9' '13.2.10' '13.2.11' '13.2.12' '13.2.13' '13.2.14' '13.2.15' '13.2.16' '13.2.17' '13.2.18' '13.3.1' '13.3.2' '13.3.3' '13.3.4' '13.3.5' '13.3.6' '13.3.7' '13.3.8' '13.3.9' '13.3.10' '13.3.11' '13.3.12' '13.3.13' '13.3.14' '13.3.15' '13.3.16' '13.3.17' '13.3.18' '13.4.1' '13.4.2' '13.4.3' '13.4.4' '13.4.5' '13.4.6' '13.4.7' '13.4.8' '13.4.9' '13.4.10' '13.4.11' '13.4.12' '13.4.13' '13.4.14' '13.4.15' '13.4.16' '13.4.17' '13.4.18' '13.5.1' '13.5.2' '13.5.3' '13.5.4' '13.5.5' '13.5.6' '13.5.7' '13.5.8' '13.5.9' '13.5.10' '13.5.11' '13.5.12' '13.5.13' '13.5.14' '13.5.15' '13.5.16' '13.5.17' '13.5.18' '13.6.1' '13.6.2' '13.6.3' '13.6.4' '13.6.5' '13.6.6' '13.6.7' '13.6.8' '13.6.9' '13.6.10' '13.6.11' '13.6.12' '13.6.13' '13.6.14' '13.6.15' '13.6.16' '13.6.17' '13.6.18' '13.7.1' '13.7.2' '13.7.3' '13.7.4' '13.7.5' '13.7.6' '13.7.7' '13.7.8' '13.7.9' '13.7.10' '13.7.11' '13.7.12' '13.7.13' '13.7.14' '13.7.15' '13.7.16' '13.7.17' '13.7.18' ; do
libwebsockets-test-echo --client localhost --port 9001 -u "/runCase?case=$N&agent=libwebsockets" -v -n 1 & libwebsockets-test-echo --client 127.0.0.1 --port 9001 -u "/runCase?case=$N&agent=libwebsockets" -v -n 1 &
C=99 C=99
while [ $C -gt 8 ] ; do while [ $C -gt 8 ] ; do

View file

@ -1,6 +1,43 @@
Changelog Changelog
--------- ---------
v2.3.0
======
- ESP32 OpenSSL support for client and server
- ESP32 4 x WLAN credential slots may be configured
- Libevent event loop support
- SOCKS5 proxy support
- lws_meta protocol for websocket connection multiplexing
- lws_vhost_destroy() added... allows dynamic removal of listening
vhosts. Vhosts with shared listen sockets adopt the listen socket
automatically if the owner is destroyed.
- IPv6 on Windows
- Improved CGI handling suitable for general CGI scripting, eg, PHP
- Convert even the "old style" test servers to use statically included
plugin sources
- LWS_WITH_STATS cmake option dumps resource usage and timing information
every few seconds to debug log, including latency information about
delay from asking for writeable callback to getting it
- Large (> 2GB) files may be served
- LWS_WITH_HTTP_PROXY Cmake option adds proxying mounts
- Workaround for libev build by disabling -Werror on the test app
- HTTP2 support disabled since no way to serve websockets on it
v2.2.0 v2.2.0
====== ======

View file

@ -111,6 +111,14 @@ lws_client_connect_2(struct lws *wsi)
#ifdef LWS_USE_IPV6 #ifdef LWS_USE_IPV6
if (wsi->ipv6) { if (wsi->ipv6) {
if (n) {
/* lws_getaddrinfo46 failed, there is no usable result */
lwsl_notice("%s: lws_getaddrinfo46 failed %d\n",
__func__, n);
cce = "ipv6 lws_getaddrinfo46 failed";
goto oom4;
}
memset(&sa46, 0, sizeof(sa46)); memset(&sa46, 0, sizeof(sa46));
sa46.sa6.sin6_family = AF_INET6; sa46.sa6.sin6_family = AF_INET6;
@ -213,15 +221,11 @@ lws_client_connect_2(struct lws *wsi)
#endif #endif
#ifdef LWS_USE_IPV6 #ifdef LWS_USE_IPV6
if (wsi->ipv6) { if (wsi->ipv6)
sa46.sa6.sin6_port = htons(port);
wsi->desc.sockfd = socket(AF_INET6, SOCK_STREAM, 0); wsi->desc.sockfd = socket(AF_INET6, SOCK_STREAM, 0);
} else else
#endif #endif
{
sa46.sa4.sin_port = htons(port);
wsi->desc.sockfd = socket(AF_INET, SOCK_STREAM, 0); wsi->desc.sockfd = socket(AF_INET, SOCK_STREAM, 0);
}
if (!lws_socket_is_valid(wsi->desc.sockfd)) { if (!lws_socket_is_valid(wsi->desc.sockfd)) {
lwsl_warn("Unable to open socket\n"); lwsl_warn("Unable to open socket\n");
@ -276,11 +280,15 @@ lws_client_connect_2(struct lws *wsi)
} }
#ifdef LWS_USE_IPV6 #ifdef LWS_USE_IPV6
if (wsi->ipv6) if (wsi->ipv6) {
sa46.sa6.sin6_port = htons(port);
n = sizeof(struct sockaddr_in6); n = sizeof(struct sockaddr_in6);
else } else
#endif #endif
{
sa46.sa4.sin_port = htons(port);
n = sizeof(struct sockaddr); n = sizeof(struct sockaddr);
}
if (connect(wsi->desc.sockfd, (const struct sockaddr *)&sa46, n) == -1 || if (connect(wsi->desc.sockfd, (const struct sockaddr *)&sa46, n) == -1 ||
LWS_ERRNO == LWS_EISCONN) { LWS_ERRNO == LWS_EISCONN) {
@ -454,15 +462,6 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
} }
wsi->redirects++; wsi->redirects++;
#ifdef LWS_OPENSSL_SUPPORT
wsi->use_ssl = ssl;
#else
if (ssl) {
lwsl_err("%s: not configured for ssl\n", __func__);
return NULL;
}
#endif
p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN); p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN);
if (p) if (p)
strncpy(origin, p, sizeof(origin) - 1); strncpy(origin, p, sizeof(origin) - 1);
@ -479,11 +478,15 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
if (p) if (p)
strncpy(method, p, sizeof(iface) - 1); strncpy(method, p, sizeof(iface) - 1);
lwsl_debug("redirect ads='%s', port=%d, path='%s', ssl = %d\n", lwsl_notice("redirect ads='%s', port=%d, path='%s', ssl = %d\n",
address, port, path, ssl); address, port, path, ssl);
/* close the connection by hand */ /* close the connection by hand */
#ifdef LWS_OPENSSL_SUPPORT
lws_ssl_close(wsi);
#endif
#ifdef LWS_USE_LIBUV #ifdef LWS_USE_LIBUV
if (LWS_LIBUV_ENABLED(wsi->context)) { if (LWS_LIBUV_ENABLED(wsi->context)) {
lwsl_debug("%s: lws_libuv_closehandle: wsi %p\n", __func__, wsi); lwsl_debug("%s: lws_libuv_closehandle: wsi %p\n", __func__, wsi);
@ -502,6 +505,15 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
remove_wsi_socket_from_fds(wsi); remove_wsi_socket_from_fds(wsi);
#ifdef LWS_OPENSSL_SUPPORT
wsi->use_ssl = ssl;
#else
if (ssl) {
lwsl_err("%s: not configured for ssl\n", __func__);
return NULL;
}
#endif
wsi->desc.sockfd = LWS_SOCK_INVALID; wsi->desc.sockfd = LWS_SOCK_INVALID;
wsi->state = LWSS_CLIENT_UNCONNECTED; wsi->state = LWSS_CLIENT_UNCONNECTED;
wsi->protocol = NULL; wsi->protocol = NULL;

View file

@ -573,7 +573,7 @@ lws_http_transaction_completed_client(struct lws *wsi)
/* we don't support chained client connections yet */ /* we don't support chained client connections yet */
return 1; return 1;
#if 0
/* otherwise set ourselves up ready to go again */ /* otherwise set ourselves up ready to go again */
wsi->state = LWSS_CLIENT_HTTP_ESTABLISHED; wsi->state = LWSS_CLIENT_HTTP_ESTABLISHED;
wsi->mode = LWSCM_HTTP_CLIENT_ACCEPTED; wsi->mode = LWSCM_HTTP_CLIENT_ACCEPTED;
@ -598,6 +598,7 @@ lws_http_transaction_completed_client(struct lws *wsi)
lwsl_info("%s: %p: keep-alive await new transaction\n", __func__, wsi); lwsl_info("%s: %p: keep-alive await new transaction\n", __func__, wsi);
return 0; return 0;
#endif
} }
LWS_VISIBLE LWS_EXTERN unsigned int LWS_VISIBLE LWS_EXTERN unsigned int
@ -630,6 +631,8 @@ lws_client_interpret_server_handshake(struct lws *wsi)
int more = 1; int more = 1;
void *v; void *v;
#endif #endif
if (wsi->u.hdr.stash)
lws_free_set_NULL(wsi->u.hdr.stash);
ah = wsi->u.hdr.ah; ah = wsi->u.hdr.ah;
if (!wsi->do_ws) { if (!wsi->do_ws) {

View file

@ -237,22 +237,36 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
#endif #endif
return -1; return -1;
break; break;
#if !defined(LWS_NO_SERVER)
case LWS_CALLBACK_HTTP_FILE_COMPLETION:
if (lws_http_transaction_completed(wsi))
return -1;
break;
#endif
case LWS_CALLBACK_HTTP_WRITEABLE: case LWS_CALLBACK_HTTP_WRITEABLE:
#ifdef LWS_WITH_CGI #ifdef LWS_WITH_CGI
if (wsi->reason_bf & 1) { if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI) {
if (lws_cgi_write_split_stdout_headers(wsi) < 0) if (lws_cgi_write_split_stdout_headers(wsi) < 0)
return -1; return -1;
if (wsi->reason_bf & 8) if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_HEADERS)
wsi->reason_bf &= ~8; wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__CGI_HEADERS;
else else
wsi->reason_bf &= ~1; wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__CGI;
break;
}
if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_CHUNK_END) {
n = lws_write(wsi, (unsigned char *)"0\x0d\x0a\x0d\x0a",
5, LWS_WRITE_HTTP);
if (n < 0)
return -1;
break; break;
} }
#endif #endif
#if defined(LWS_WITH_HTTP_PROXY) #if defined(LWS_WITH_HTTP_PROXY)
if (wsi->reason_bf & 2) { if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__PROXY) {
char *px = buf + LWS_PRE; char *px = buf + LWS_PRE;
int lenx = sizeof(buf) - LWS_PRE; int lenx = sizeof(buf) - LWS_PRE;
/* /*
@ -262,8 +276,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
* is the smaller. * is the smaller.
*/ */
wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__PROXY;
wsi->reason_bf &= ~2;
if (!lws_get_child(wsi)) if (!lws_get_child(wsi))
break; break;
if (lws_http_client_read(lws_get_child(wsi), &px, &lenx) < 0) if (lws_http_client_read(lws_get_child(wsi), &px, &lenx) < 0)
@ -279,7 +292,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
assert(lws_get_parent(wsi)); assert(lws_get_parent(wsi));
if (!lws_get_parent(wsi)) if (!lws_get_parent(wsi))
break; break;
lws_get_parent(wsi)->reason_bf |= 2; lws_get_parent(wsi)->reason_bf |= LWS_CB_REASON_AUX_BF__PROXY;
lws_callback_on_writable(lws_get_parent(wsi)); lws_callback_on_writable(lws_get_parent(wsi));
break; break;
@ -351,7 +364,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
/* TBD stdin rx flow control */ /* TBD stdin rx flow control */
break; break;
case LWS_STDOUT: case LWS_STDOUT:
wsi->reason_bf |= 1; wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI;
/* when writing to MASTER would not block */ /* when writing to MASTER would not block */
lws_callback_on_writable(wsi); lws_callback_on_writable(wsi);
break; break;
@ -369,6 +382,11 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
break; break;
case LWS_CALLBACK_CGI_TERMINATED: case LWS_CALLBACK_CGI_TERMINATED:
if (!wsi->cgi->explicitly_chunked && !wsi->cgi->content_length) {
/* send terminating chunk */
wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_CHUNK_END;
lws_callback_on_writable(wsi);
}
return -1; return -1;
case LWS_CALLBACK_CGI_STDIN_DATA: /* POST body for stdin */ case LWS_CALLBACK_CGI_STDIN_DATA: /* POST body for stdin */
@ -470,6 +488,11 @@ lws_create_vhost(struct lws_context *context,
else else
vh->keepalive_timeout = 5; vh->keepalive_timeout = 5;
if (info->timeout_secs_ah_idle)
vh->timeout_secs_ah_idle = info->timeout_secs_ah_idle;
else
vh->timeout_secs_ah_idle = 10;
/* /*
* give the vhost a unified list of protocols including the * give the vhost a unified list of protocols including the
* ones that came from plugins * ones that came from plugins
@ -524,7 +547,7 @@ lws_create_vhost(struct lws_context *context,
vh->protocols = lwsp; vh->protocols = lwsp;
else { else {
vh->protocols = info->protocols; vh->protocols = info->protocols;
free(lwsp); lws_free(lwsp);
} }
vh->same_vh_protocol_list = (struct lws **) vh->same_vh_protocol_list = (struct lws **)

View file

@ -94,13 +94,16 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
case LWS_EXT_CB_OPTION_SET: case LWS_EXT_CB_OPTION_SET:
oa = in; oa = in;
lwsl_info("%s: option set: idx %d, %s, len %d\n", __func__, lwsl_notice("%s: option set: idx %d, %s, len %d\n", __func__,
oa->option_index, oa->start, oa->len); oa->option_index, oa->start, oa->len);
if (oa->start) if (oa->start)
priv->args[oa->option_index] = atoi(oa->start); priv->args[oa->option_index] = atoi(oa->start);
else else
priv->args[oa->option_index] = 1; priv->args[oa->option_index] = 1;
if (priv->args[PMD_CLIENT_MAX_WINDOW_BITS] == 8)
priv->args[PMD_CLIENT_MAX_WINDOW_BITS] = 9;
lws_extension_pmdeflate_restrict_args(wsi, priv); lws_extension_pmdeflate_restrict_args(wsi, priv);
break; break;
@ -325,16 +328,18 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
case LWS_EXT_CB_PAYLOAD_TX: case LWS_EXT_CB_PAYLOAD_TX:
if (!priv->tx_init) if (!priv->tx_init) {
if (deflateInit2(&priv->tx, priv->args[PMD_COMP_LEVEL], n = deflateInit2(&priv->tx, priv->args[PMD_COMP_LEVEL],
Z_DEFLATED, Z_DEFLATED,
-priv->args[PMD_CLIENT_MAX_WINDOW_BITS + -priv->args[PMD_SERVER_MAX_WINDOW_BITS +
!wsi->vhost->listen_port], (wsi->vhost->listen_port <= 0)],
priv->args[PMD_MEM_LEVEL], priv->args[PMD_MEM_LEVEL],
Z_DEFAULT_STRATEGY) != Z_OK) { Z_DEFAULT_STRATEGY);
lwsl_ext("inflateInit2 failed\n"); if (n != Z_OK) {
lwsl_ext("inflateInit2 failed %d\n", n);
return 1; return 1;
} }
}
priv->tx_init = 1; priv->tx_init = 1;
if (!priv->buf_tx_deflated) if (!priv->buf_tx_deflated)
priv->buf_tx_deflated = lws_malloc(LWS_PRE + 7 + 5 + priv->buf_tx_deflated = lws_malloc(LWS_PRE + 7 + 5 +
@ -436,7 +441,9 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
break; break;
priv->compressed_out = 0; priv->compressed_out = 0;
if ((*(eff_buf->token) & 0x80) && priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER]) { if ((*(eff_buf->token) & 0x80) &&
priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER]) {
lwsl_debug("PMD_CLIENT_NO_CONTEXT_TAKEOVER\n");
(void)deflateEnd(&priv->tx); (void)deflateEnd(&priv->tx);
priv->tx_init = 0; priv->tx_init = 0;
} }

View file

@ -62,7 +62,7 @@ lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi,
oa.option_index = n; oa.option_index = n;
lwsl_ext("hit %d\n", oa.option_index); lwsl_ext("hit %d\n", oa.option_index);
leap = LEAPS_SEEK_VAL; leap = LEAPS_SEEK_VAL;
if (len ==1) if (len == 1)
goto set_arg; goto set_arg;
break; break;
} }

View file

@ -238,7 +238,7 @@ lws_return_http_status(struct lws *wsi, unsigned int code,
&p, end)) &p, end))
return 1; return 1;
len = 37 + strlen(html_body) + sprintf(slen, "%d", code); len = 35 + strlen(html_body) + sprintf(slen, "%d", code);
n = sprintf(slen, "%d", len); n = sprintf(slen, "%d", len);
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,

View file

@ -776,7 +776,8 @@ lwsws_get_config_d(void *user, const char *d, const char * const *paths,
bail: bail:
uv_fs_req_cleanup(&req); uv_fs_req_cleanup(&req);
uv_loop_close(&loop); while (uv_loop_close(&loop))
;
return ret; return ret;
} }

View file

@ -39,12 +39,15 @@ lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx)
if (revents & EV_TIMEOUT) if (revents & EV_TIMEOUT)
return; return;
/* !!! EV_CLOSED doesn't exist in libevent2 */
#if LIBEVENT_VERSION_NUMBER < 0x02000000
if (revents & EV_CLOSED) if (revents & EV_CLOSED)
{ {
event_del(lws_io->event_watcher); event_del(lws_io->event_watcher);
event_free(lws_io->event_watcher); event_free(lws_io->event_watcher);
return; return;
} }
#endif
eventfd.fd = sock_fd; eventfd.fd = sock_fd;
eventfd.events = 0; eventfd.events = 0;

View file

@ -65,9 +65,14 @@ static const char * const log_level_names[] = {
void void
lws_free_wsi(struct lws *wsi) lws_free_wsi(struct lws *wsi)
{ {
struct lws_context_per_thread *pt;
int n;
if (!wsi) if (!wsi)
return; return;
pt = &wsi->context->pt[(int)wsi->tsi];
/* Protocol user data may be allocated either internally by lws /* Protocol user data may be allocated either internally by lws
* or by specified the user. * or by specified the user.
* We should only free what we allocated. */ * We should only free what we allocated. */
@ -80,8 +85,27 @@ lws_free_wsi(struct lws *wsi)
/* we may not have an ah, but may be on the waiting list... */ /* we may not have an ah, but may be on the waiting list... */
lwsl_info("ah det due to close\n"); lwsl_info("ah det due to close\n");
/* we're closing, losing some rx is OK */
lws_header_table_force_to_detachable_state(wsi);
lws_header_table_detach(wsi, 0); lws_header_table_detach(wsi, 0);
lws_pt_lock(pt);
for (n = 0; n < wsi->context->max_http_header_pool; n++) {
if (pt->ah_pool[n].in_use &&
pt->ah_pool[n].wsi == wsi) {
lwsl_err("%s: ah leak: wsi %p\n", __func__, wsi);
pt->ah_pool[n].in_use = 0;
pt->ah_pool[n].wsi = NULL;
pt->ah_count_in_use--;
}
}
lws_pt_unlock(pt);
/* since we will destroy the wsi, make absolutely sure now */
lws_ssl_remove_wsi_from_buffered_list(wsi);
lws_remove_from_timeout_list(wsi);
wsi->context->count_wsi_allocated--; wsi->context->count_wsi_allocated--;
lwsl_debug("%s: %p, remaining wsi %d\n", __func__, wsi, lwsl_debug("%s: %p, remaining wsi %d\n", __func__, wsi,
wsi->context->count_wsi_allocated); wsi->context->count_wsi_allocated);
@ -232,6 +256,33 @@ lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p)
return 0; return 0;
} }
#ifdef LWS_WITH_CGI
static void
lws_cgi_remove_and_kill(struct lws *wsi)
{
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
struct lws_cgi **pcgi = &pt->cgi_list;
/* remove us from the cgi list */
lwsl_debug("%s: remove cgi %p from list\n", __func__, wsi->cgi);
while (*pcgi) {
if (*pcgi == wsi->cgi) {
/* drop us from the pt cgi list */
*pcgi = (*pcgi)->cgi_list;
break;
}
pcgi = &(*pcgi)->cgi_list;
}
if (wsi->cgi->headers_buf) {
lwsl_debug("close: freed cgi headers\n");
lws_free_set_NULL(wsi->cgi->headers_buf);
}
/* we have a cgi going, we must kill it */
wsi->cgi->being_closed = 1;
lws_cgi_kill(wsi);
}
#endif
void void
lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason) lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
{ {
@ -295,35 +346,38 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
#ifdef LWS_WITH_CGI #ifdef LWS_WITH_CGI
if (wsi->mode == LWSCM_CGI) { if (wsi->mode == LWSCM_CGI) {
/* we are not a network connection, but a handler for CGI io */ /* we are not a network connection, but a handler for CGI io */
if (wsi->parent && wsi->parent->cgi) if (wsi->parent && wsi->parent->cgi) {
if (wsi->cgi_channel == LWS_STDOUT)
lws_cgi_remove_and_kill(wsi->parent);
/* end the binding between us and master */ /* end the binding between us and master */
wsi->parent->cgi->stdwsi[(int)wsi->cgi_channel] = NULL; wsi->parent->cgi->stdwsi[(int)wsi->cgi_channel] = NULL;
}
wsi->socket_is_permanently_unusable = 1; wsi->socket_is_permanently_unusable = 1;
lwsl_debug("------ %s: detected cgi fdhandler wsi %p\n", __func__, wsi); lwsl_debug("------ %s: detected cgi fdhandler wsi %p\n", __func__, wsi);
goto just_kill_connection; goto just_kill_connection;
} }
if (wsi->cgi) { if (wsi->cgi)
struct lws_cgi **pcgi = &pt->cgi_list; lws_cgi_remove_and_kill(wsi);
/* remove us from the cgi list */ #endif
lwsl_debug("%s: remove cgi %p from list\n", __func__, wsi->cgi);
while (*pcgi) { #if !defined(LWS_NO_CLIENT)
if (*pcgi == wsi->cgi) { if (wsi->mode == LWSCM_HTTP_CLIENT ||
/* drop us from the pt cgi list */ wsi->mode == LWSCM_WSCL_WAITING_CONNECT ||
*pcgi = (*pcgi)->cgi_list; wsi->mode == LWSCM_WSCL_WAITING_PROXY_REPLY ||
break; wsi->mode == LWSCM_WSCL_ISSUE_HANDSHAKE ||
} wsi->mode == LWSCM_WSCL_ISSUE_HANDSHAKE2 ||
pcgi = &(*pcgi)->cgi_list; wsi->mode == LWSCM_WSCL_WAITING_SSL ||
} wsi->mode == LWSCM_WSCL_WAITING_SERVER_REPLY ||
if (wsi->cgi->headers_buf) { wsi->mode == LWSCM_WSCL_WAITING_EXTENSION_CONNECT ||
lwsl_debug("close: freed cgi headers\n"); wsi->mode == LWSCM_WSCL_WAITING_SOCKS_GREETING_REPLY ||
lws_free_set_NULL(wsi->cgi->headers_buf); wsi->mode == LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY ||
} wsi->mode == LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY)
/* we have a cgi going, we must kill it */ if (wsi->u.hdr.stash)
wsi->cgi->being_closed = 1; lws_free_set_NULL(wsi->u.hdr.stash);
lws_cgi_kill(wsi);
}
#endif #endif
if (wsi->mode == LWSCM_RAW) { if (wsi->mode == LWSCM_RAW) {
@ -729,12 +783,13 @@ lws_close_free_wsi_final(struct lws *wsi)
#ifdef LWS_WITH_CGI #ifdef LWS_WITH_CGI
if (wsi->cgi) { if (wsi->cgi) {
for (n = 0; n < 6; n++) {
if (wsi->cgi->pipe_fds[n / 2][n & 1] == 0) for (n = 0; n < 3; n++) {
if (wsi->cgi->pipe_fds[n][!!(n == 0)] == 0)
lwsl_err("ZERO FD IN CGI CLOSE"); lwsl_err("ZERO FD IN CGI CLOSE");
if (wsi->cgi->pipe_fds[n / 2][n & 1] >= 0) if (wsi->cgi->pipe_fds[n][!!(n == 0)] >= 0)
close(wsi->cgi->pipe_fds[n / 2][n & 1]); close(wsi->cgi->pipe_fds[n][!!(n == 0)]);
} }
lws_free(wsi->cgi); lws_free(wsi->cgi);
@ -785,8 +840,7 @@ lws_get_addresses(struct lws_vhost *vh, void *ads, char *name,
struct addrinfo ai, *res; struct addrinfo ai, *res;
struct sockaddr_in addr4; struct sockaddr_in addr4;
if (rip) rip[0] = '\0';
rip[0] = '\0';
name[0] = '\0'; name[0] = '\0';
addr4.sin_family = AF_UNSPEC; addr4.sin_family = AF_UNSPEC;
@ -821,8 +875,6 @@ lws_get_addresses(struct lws_vhost *vh, void *ads, char *name,
name, name_len, NULL, 0, 0)) name, name_len, NULL, 0, 0))
return -1; return -1;
#endif #endif
if (!rip)
return 0;
if (getaddrinfo(name, NULL, &ai, &result)) if (getaddrinfo(name, NULL, &ai, &result))
return -1; return -1;
@ -1019,8 +1071,9 @@ lws_callback_all_protocol(struct lws_context *context,
} }
LWS_VISIBLE int LWS_VISIBLE int
lws_callback_all_protocol_vhost(struct lws_vhost *vh, lws_callback_all_protocol_vhost_args(struct lws_vhost *vh,
const struct lws_protocols *protocol, int reason) const struct lws_protocols *protocol, int reason,
void *argp, size_t len)
{ {
struct lws_context *context = vh->context; struct lws_context *context = vh->context;
struct lws_context_per_thread *pt = &context->pt[0]; struct lws_context_per_thread *pt = &context->pt[0];
@ -1032,9 +1085,10 @@ lws_callback_all_protocol_vhost(struct lws_vhost *vh,
wsi = wsi_from_fd(context, pt->fds[n].fd); wsi = wsi_from_fd(context, pt->fds[n].fd);
if (!wsi) if (!wsi)
continue; continue;
if (wsi->vhost == vh && wsi->protocol == protocol) if (wsi->vhost == vh && (wsi->protocol == protocol ||
protocol->callback(wsi, reason, wsi->user_space, !protocol))
NULL, 0); wsi->protocol->callback(wsi, reason,
wsi->user_space, argp, len);
} }
pt++; pt++;
} }
@ -1042,6 +1096,13 @@ lws_callback_all_protocol_vhost(struct lws_vhost *vh,
return 0; return 0;
} }
LWS_VISIBLE int
lws_callback_all_protocol_vhost(struct lws_vhost *vh,
const struct lws_protocols *protocol, int reason)
{
return lws_callback_all_protocol_vhost_args(vh, protocol, reason, NULL, 0);
}
LWS_VISIBLE LWS_EXTERN int LWS_VISIBLE LWS_EXTERN int
lws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, int len) lws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, int len)
{ {
@ -2585,6 +2646,8 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
p++; p++;
} }
} }
env_array[n++] = "PATH=/bin:/usr/bin:/usr/local/bin:/var/www/cgi-bin";
env_array[n++] = p; env_array[n++] = p;
p += lws_snprintf(p, end - p, "SCRIPT_PATH=%s", exec_array[0]) + 1; p += lws_snprintf(p, end - p, "SCRIPT_PATH=%s", exec_array[0]) + 1;
@ -2599,7 +2662,6 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
} }
env_array[n++] = "SERVER_SOFTWARE=libwebsockets"; env_array[n++] = "SERVER_SOFTWARE=libwebsockets";
env_array[n++] = "PATH=/bin:/usr/bin:/usr/local/bin:/var/www/cgi-bin";
env_array[n] = NULL; env_array[n] = NULL;
#if 0 #if 0
@ -2634,6 +2696,10 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
/* we are the parent process */ /* we are the parent process */
wsi->context->count_cgi_spawned++; wsi->context->count_cgi_spawned++;
lwsl_debug("%s: cgi %p spawned PID %d\n", __func__, cgi, cgi->pid); lwsl_debug("%s: cgi %p spawned PID %d\n", __func__, cgi, cgi->pid);
for (n = 0; n < 3; n++)
close(cgi->pipe_fds[n][!(n == 0)]);
return 0; return 0;
} }
@ -2716,11 +2782,11 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
return -1; return -1;
while (wsi->hdr_state != LHCS_PAYLOAD) { while (wsi->hdr_state != LHCS_PAYLOAD) {
/* we have to separate header / finalize and /*
* we have to separate header / finalize and
* payload chunks, since they need to be * payload chunks, since they need to be
* handled separately * handled separately
*/ */
switch (wsi->hdr_state) { switch (wsi->hdr_state) {
case LHCS_RESPONSE: case LHCS_RESPONSE:
@ -2728,6 +2794,12 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
wsi->cgi->response_code); wsi->cgi->response_code);
if (lws_add_http_header_status(wsi, wsi->cgi->response_code, &p, end)) if (lws_add_http_header_status(wsi, wsi->cgi->response_code, &p, end))
return 1; return 1;
if (!wsi->cgi->explicitly_chunked &&
!wsi->cgi->content_length &&
lws_add_http_header_by_token(wsi,
WSI_TOKEN_HTTP_TRANSFER_ENCODING,
(unsigned char *)"chunked", 7, &p, end))
return 1;
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION, if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION,
(unsigned char *)"close", 5, &p, end)) (unsigned char *)"close", 5, &p, end))
return 1; return 1;
@ -2744,7 +2816,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
} }
wsi->hdr_state = LHCS_DUMP_HEADERS; wsi->hdr_state = LHCS_DUMP_HEADERS;
wsi->reason_bf |= 8; wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_HEADERS;
lws_callback_on_writable(wsi); lws_callback_on_writable(wsi);
/* back to the loop for writeability again */ /* back to the loop for writeability again */
return 0; return 0;
@ -2769,7 +2841,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
lws_free_set_NULL(wsi->cgi->headers_buf); lws_free_set_NULL(wsi->cgi->headers_buf);
lwsl_debug("freed cgi headers\n"); lwsl_debug("freed cgi headers\n");
} else { } else {
wsi->reason_bf |= 8; wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_HEADERS;
lws_callback_on_writable(wsi); lws_callback_on_writable(wsi);
} }
@ -2925,14 +2997,24 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
/* payload processing */ /* payload processing */
m = !wsi->cgi->explicitly_chunked && !wsi->cgi->content_length;
n = read(lws_get_socket_fd(wsi->cgi->stdwsi[LWS_STDOUT]), n = read(lws_get_socket_fd(wsi->cgi->stdwsi[LWS_STDOUT]),
start, sizeof(buf) - LWS_PRE); start, sizeof(buf) - LWS_PRE - (m ? LWS_HTTP_CHUNK_HDR_SIZE : 0));
if (n < 0 && errno != EAGAIN) { if (n < 0 && errno != EAGAIN) {
lwsl_debug("%s: stdout read says %d\n", __func__, n); lwsl_debug("%s: stdout read says %d\n", __func__, n);
return -1; return -1;
} }
if (n > 0) { if (n > 0) {
if (m) {
char chdr[LWS_HTTP_CHUNK_HDR_SIZE];
m = lws_snprintf(chdr, LWS_HTTP_CHUNK_HDR_SIZE - 3, "%X\x0d\x0a", n);
memmove(start + m, start, n);
memcpy(start, chdr, m);
memcpy(start + m + n, "\x0d\x0a", 2);
n += m + 2;
}
m = lws_write(wsi, (unsigned char *)start, n, LWS_WRITE_HTTP); m = lws_write(wsi, (unsigned char *)start, n, LWS_WRITE_HTTP);
//lwsl_notice("write %d\n", m); //lwsl_notice("write %d\n", m);
if (m < 0) { if (m < 0) {
@ -3063,7 +3145,7 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt)
lwsl_debug("%s: found PID %d on cgi list\n", lwsl_debug("%s: found PID %d on cgi list\n",
__func__, n); __func__, n);
if (!cgi->content_length && cgi->explicitly_chunked) { if (!cgi->content_length) {
/* /*
* well, if he sends chunked... give him 5s after the * well, if he sends chunked... give him 5s after the
* cgi terminated to send buffered * cgi terminated to send buffered
@ -3166,7 +3248,8 @@ lws_set_extension_option(struct lws *wsi, const char *ext_name,
int int
lws_access_log(struct lws *wsi) lws_access_log(struct lws *wsi)
{ {
char *p = wsi->access_log.user_agent, ass[512]; char *p = wsi->access_log.user_agent, ass[512],
*p1 = wsi->access_log.referrer;
int l; int l;
if (!wsi->access_log_pending) if (!wsi->access_log_pending)
@ -3178,9 +3261,12 @@ lws_access_log(struct lws *wsi)
if (!p) if (!p)
p = ""; p = "";
l = lws_snprintf(ass, sizeof(ass) - 1, "%s %d %lu %s\n", if (!p1)
p1 = "";
l = lws_snprintf(ass, sizeof(ass) - 1, "%s %d %lu \"%s\" \"%s\"\n",
wsi->access_log.header_log, wsi->access_log.header_log,
wsi->access_log.response, wsi->access_log.sent, p); wsi->access_log.response, wsi->access_log.sent, p1, p);
if (wsi->vhost->log_fd != (int)LWS_INVALID_FILE) { if (wsi->vhost->log_fd != (int)LWS_INVALID_FILE) {
if (write(wsi->vhost->log_fd, ass, l) != l) if (write(wsi->vhost->log_fd, ass, l) != l)
@ -3196,6 +3282,10 @@ lws_access_log(struct lws *wsi)
lws_free(wsi->access_log.user_agent); lws_free(wsi->access_log.user_agent);
wsi->access_log.user_agent = NULL; wsi->access_log.user_agent = NULL;
} }
if (wsi->access_log.referrer) {
lws_free(wsi->access_log.referrer);
wsi->access_log.referrer = NULL;
}
wsi->access_log_pending = 0; wsi->access_log_pending = 0;
return 0; return 0;

View file

@ -33,12 +33,11 @@ extern "C" {
#include <stdarg.h> #include <stdarg.h>
#endif #endif
#if defined(LWS_HAS_INTPTR_T) #include "lws_config.h"
#include <stdint.h>
#define lws_intptr_t intptr_t /*
#else * CARE: everything using cmake defines needs to be below here
typedef unsigned long long lws_intptr_t; */
#endif
#if defined(LWS_WITH_ESP8266) #if defined(LWS_WITH_ESP8266)
struct sockaddr_in; struct sockaddr_in;
@ -47,7 +46,12 @@ struct sockaddr_in;
#define LWS_POSIX 1 #define LWS_POSIX 1
#endif #endif
#include "lws_config.h" #if defined(LWS_HAS_INTPTR_T)
#include <stdint.h>
#define lws_intptr_t intptr_t
#else
typedef unsigned long long lws_intptr_t;
#endif
#if defined(WIN32) || defined(_WIN32) #if defined(WIN32) || defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
@ -632,6 +636,7 @@ struct lws_esp32_image {
}; };
extern struct lws_esp32 lws_esp32; extern struct lws_esp32 lws_esp32;
struct lws_vhost;
extern esp_err_t extern esp_err_t
lws_esp32_event_passthru(void *ctx, system_event_t *event); lws_esp32_event_passthru(void *ctx, system_event_t *event);
@ -645,7 +650,7 @@ struct lws_context_creation_info;
extern void extern void
lws_esp32_set_creation_defaults(struct lws_context_creation_info *info); lws_esp32_set_creation_defaults(struct lws_context_creation_info *info);
extern struct lws_context * extern struct lws_context *
lws_esp32_init(struct lws_context_creation_info *); lws_esp32_init(struct lws_context_creation_info *, struct lws_vhost **pvh);
extern int extern int
lws_esp32_wlan_nvs_get(int retry); lws_esp32_wlan_nvs_get(int retry);
extern esp_err_t extern esp_err_t
@ -851,7 +856,7 @@ enum lws_meta_commands {
/* channel numbers are transported offset by 0x20 so they are valid unicode */ /* channel numbers are transported offset by 0x20 so they are valid unicode */
#define LWS_META_CHANNEL_OFFSET_TRANSPORT 0x20 #define LWS_META_TRANSPORT_OFFSET 0x20
///@} ///@}
@ -1321,6 +1326,11 @@ enum lws_callback_reasons {
typedef int typedef int
lws_callback_function(struct lws *wsi, enum lws_callback_reasons reason, lws_callback_function(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len); void *user, void *in, size_t len);
#define LWS_CB_REASON_AUX_BF__CGI 1
#define LWS_CB_REASON_AUX_BF__PROXY 2
#define LWS_CB_REASON_AUX_BF__CGI_CHUNK_END 4
#define LWS_CB_REASON_AUX_BF__CGI_HEADERS 8
///@} ///@}
/*! \defgroup extensions /*! \defgroup extensions
@ -2111,6 +2121,9 @@ struct lws_context_creation_info {
* the form SSL_CB_ALERT, defined in openssl/ssl.h. The default of * the form SSL_CB_ALERT, defined in openssl/ssl.h. The default of
* 0 means no info events will be reported. * 0 means no info events will be reported.
*/ */
unsigned int timeout_secs_ah_idle;
/**< VHOST: seconds to allow a client to hold an ah without using it.
* 0 defaults to 10s. */
void *_unused[8]; /**< dummy */ void *_unused[8]; /**< dummy */
}; };
@ -3666,6 +3679,7 @@ enum pending_timeout {
PENDING_TIMEOUT_KILLED_BY_SSL_INFO = 22, PENDING_TIMEOUT_KILLED_BY_SSL_INFO = 22,
PENDING_TIMEOUT_KILLED_BY_PARENT = 23, PENDING_TIMEOUT_KILLED_BY_PARENT = 23,
PENDING_TIMEOUT_CLOSE_SEND = 24, PENDING_TIMEOUT_CLOSE_SEND = 24,
PENDING_TIMEOUT_HOLDING_AH = 25,
/****** add new things just above ---^ ******/ /****** add new things just above ---^ ******/
}; };
@ -3912,7 +3926,7 @@ lws_callback_on_writable(struct lws *wsi);
/** /**
* lws_callback_on_writable_all_protocol() - Request a callback for all * 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 * becomes possible to write to each socket without
* blocking in turn. * blocking in turn.
* *
@ -3929,8 +3943,8 @@ lws_callback_on_writable_all_protocol(const struct lws_context *context,
/** /**
* lws_callback_on_writable_all_protocol_vhost() - Request a callback for * lws_callback_on_writable_all_protocol_vhost() - Request a callback for
* all connections using the given protocol when it * all connections on same vhost using the given protocol
* becomes possible to write to each socket without * when it becomes possible to write to each socket without
* blocking in turn. * blocking in turn.
* *
* \param vhost: Only consider connections on this lws_vhost * \param vhost: Only consider connections on this lws_vhost
@ -3966,10 +3980,11 @@ lws_callback_all_protocol(struct lws_context *context,
/** /**
* lws_callback_all_protocol_vhost() - Callback all connections using * lws_callback_all_protocol_vhost() - Callback all connections using
* the given protocol with the given reason * the given protocol with the given reason. This is
* deprecated since v2.4: use lws_callback_all_protocol_vhost_args
* *
* \param vh: Vhost whose connections will get callbacks * \param vh: Vhost whose connections will get callbacks
* \param protocol: Which protocol to match * \param protocol: Which protocol to match. NULL means all.
* \param reason: Callback reason index * \param reason: Callback reason index
* *
* - Which: connections using this protocol on GIVEN VHOST ONLY * - Which: connections using this protocol on GIVEN VHOST ONLY
@ -3978,7 +3993,27 @@ lws_callback_all_protocol(struct lws_context *context,
*/ */
LWS_VISIBLE LWS_EXTERN int LWS_VISIBLE LWS_EXTERN int
lws_callback_all_protocol_vhost(struct lws_vhost *vh, lws_callback_all_protocol_vhost(struct lws_vhost *vh,
const struct lws_protocols *protocol, int reason); const struct lws_protocols *protocol, int reason)
LWS_WARN_DEPRECATED;
/**
* lws_callback_all_protocol_vhost_args() - Callback all connections using
* the given protocol with the given reason and args
*
* \param vh: Vhost whose connections will get callbacks
* \param protocol: Which protocol to match. NULL means all.
* \param reason: Callback reason index
* \param argp: Callback "in" parameter
* \param len: Callback "len" parameter
*
* - Which: connections using this protocol on GIVEN VHOST ONLY
* - When: now
* - What: reason
*/
LWS_VISIBLE int
lws_callback_all_protocol_vhost_args(struct lws_vhost *vh,
const struct lws_protocols *protocol, int reason,
void *argp, size_t len);
/** /**
* lws_callback_vhost_protocols() - Callback all protocols enabled on a vhost * lws_callback_vhost_protocols() - Callback all protocols enabled on a vhost

View file

@ -1613,7 +1613,12 @@ lws_esp32_get_image_info(const esp_partition_t *part, struct lws_esp32_image *i,
} }
hdr += (~hdr & 15) + 1; hdr += (~hdr & 15) + 1;
i->romfs = hdr + 4; if (eih.hash_appended)
hdr += 0x20;
// lwsl_notice("romfs estimated at 0x%x\n", hdr);
i->romfs = hdr + 0x4;
spi_flash_read(hdr, &i->romfs_len, sizeof(i->romfs_len)); spi_flash_read(hdr, &i->romfs_len, sizeof(i->romfs_len));
i->json = i->romfs + i->romfs_len + 4; i->json = i->romfs + i->romfs_len + 4;
spi_flash_read(i->json - 4, &i->json_len, sizeof(i->json_len)); spi_flash_read(i->json - 4, &i->json_len, sizeof(i->json_len));
@ -1627,7 +1632,7 @@ lws_esp32_get_image_info(const esp_partition_t *part, struct lws_esp32_image *i,
} }
struct lws_context * struct lws_context *
lws_esp32_init(struct lws_context_creation_info *info) lws_esp32_init(struct lws_context_creation_info *info, struct lws_vhost **pvh)
{ {
const esp_partition_t *part = lws_esp_ota_get_boot_partition(); const esp_partition_t *part = lws_esp_ota_get_boot_partition();
struct lws_context *context; struct lws_context *context;
@ -1683,6 +1688,9 @@ lws_esp32_init(struct lws_context_creation_info *info)
else else
lws_init_vhost_client_ssl(info, vhost); lws_init_vhost_client_ssl(info, vhost);
if (pvh)
*pvh = vhost;
lws_protocol_init(context); lws_protocol_init(context);
return context; return context;

View file

@ -256,7 +256,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd)
} }
#if defined(SO_BINDTODEVICE) #if defined(SO_BINDTODEVICE)
if (vhost->bind_iface) { if (vhost->bind_iface && vhost->iface) {
lwsl_info("binding listen skt to %s using SO_BINDTODEVICE\n", vhost->iface); lwsl_info("binding listen skt to %s using SO_BINDTODEVICE\n", vhost->iface);
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, vhost->iface, if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, vhost->iface,
strlen(vhost->iface)) < 0) { strlen(vhost->iface)) < 0) {

View file

@ -218,6 +218,9 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
/* if something closed, retry this slot */ /* if something closed, retry this slot */
if (n) if (n)
i--; i--;
if (wsi->trunc_len)
WSASetEvent(pt->events[0]);
} }
/* /*

View file

@ -286,7 +286,8 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len,
if (wsi->state == LWSS_ESTABLISHED && wsi->u.ws.tx_draining_ext) { if (wsi->state == LWSS_ESTABLISHED && wsi->u.ws.tx_draining_ext) {
/* remove us from the list */ /* remove us from the list */
struct lws **w = &pt->tx_draining_ext_list; struct lws **w = &pt->tx_draining_ext_list;
lwsl_debug("%s: TX EXT DRAINING: Remove from list\n", __func__);
// lwsl_notice("%s: TX EXT DRAINING: Remove from list\n", __func__);
wsi->u.ws.tx_draining_ext = 0; wsi->u.ws.tx_draining_ext = 0;
/* remove us from context draining ext list */ /* remove us from context draining ext list */
while (*w) { while (*w) {
@ -349,11 +350,13 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len,
case LWS_WRITE_CLOSE: case LWS_WRITE_CLOSE:
break; break;
default: default:
lwsl_debug("LWS_EXT_CB_PAYLOAD_TX\n");
n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_TX, &eff_buf, wp); n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_TX, &eff_buf, wp);
if (n < 0) if (n < 0)
return -1; return -1;
if (n && eff_buf.token_len) { if (n && eff_buf.token_len) {
lwsl_debug("drain len %d\n", (int)eff_buf.token_len);
/* extension requires further draining */ /* extension requires further draining */
wsi->u.ws.tx_draining_ext = 1; wsi->u.ws.tx_draining_ext = 1;
wsi->u.ws.tx_draining_ext_list = pt->tx_draining_ext_list; wsi->u.ws.tx_draining_ext_list = pt->tx_draining_ext_list;
@ -387,8 +390,8 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len,
*/ */
if ((char *)buf != eff_buf.token) { if ((char *)buf != eff_buf.token) {
/* /*
* ext might eat it, but no have anything to issue yet * ext might eat it, but not have anything to issue yet.
* in that case we have to follow his lead, but stash and * In that case we have to follow his lead, but stash and
* replace the write type that was lost here the first time. * replace the write type that was lost here the first time.
*/ */
if (len && !eff_buf.token_len) { if (len && !eff_buf.token_len) {
@ -407,6 +410,13 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len,
buf = (unsigned char *)eff_buf.token; buf = (unsigned char *)eff_buf.token;
len = eff_buf.token_len; len = eff_buf.token_len;
lwsl_debug("%p / %d\n", buf, (int)len);
if (!buf) {
lwsl_err("null buf (%d)\n", (int)len);
return -1;
}
switch (wsi->ietf_spec_revision) { switch (wsi->ietf_spec_revision) {
case 13: case 13:
if (masked7) { if (masked7) {

View file

@ -92,6 +92,10 @@ lws_header_table_reset(struct lws *wsi, int autoservice)
/* since we will restart the ah, our new headers are not completed */ /* since we will restart the ah, our new headers are not completed */
wsi->hdr_parsing_completed = 0; wsi->hdr_parsing_completed = 0;
/* while we hold the ah, keep a timeout on the wsi */
lws_set_timeout(wsi, PENDING_TIMEOUT_HOLDING_AH,
wsi->vhost->timeout_secs_ah_idle);
/* /*
* if we inherited pending rx (from socket adoption deferred * if we inherited pending rx (from socket adoption deferred
* processing), apply and free it. * processing), apply and free it.

View file

@ -449,8 +449,8 @@ lws_same_vh_protocol_insert(struct lws *wsi, int n)
// wsi->same_vh_protocol_prev); // wsi->same_vh_protocol_prev);
if (wsi->same_vh_protocol_prev || wsi->same_vh_protocol_next) { if (wsi->same_vh_protocol_prev || wsi->same_vh_protocol_next) {
lwsl_err("Attempted to attach wsi twice to same vh prot\n"); lws_same_vh_protocol_remove(wsi);
assert(0); lwsl_notice("Attempted to attach wsi twice to same vh prot\n");
} }
wsi->same_vh_protocol_prev = /* guy who points to us */ wsi->same_vh_protocol_prev = /* guy who points to us */

View file

@ -891,6 +891,7 @@ struct lws_vhost {
int ka_probes; int ka_probes;
int ka_interval; int ka_interval;
int keepalive_timeout; int keepalive_timeout;
int timeout_secs_ah_idle;
int ssl_info_event_mask; int ssl_info_event_mask;
#ifdef LWS_WITH_ACCESS_LOG #ifdef LWS_WITH_ACCESS_LOG
int log_fd; int log_fd;
@ -1489,6 +1490,8 @@ struct _lws_websocket_related {
#ifdef LWS_WITH_CGI #ifdef LWS_WITH_CGI
#define LWS_HTTP_CHUNK_HDR_SIZE 16
enum { enum {
SIGNIFICANT_HDR_CONTENT_LENGTH, SIGNIFICANT_HDR_CONTENT_LENGTH,
SIGNIFICANT_HDR_LOCATION, SIGNIFICANT_HDR_LOCATION,
@ -1542,6 +1545,7 @@ struct lws_rewrite;
struct lws_access_log { struct lws_access_log {
char *header_log; char *header_log;
char *user_agent; char *user_agent;
char *referrer;
unsigned long sent; unsigned long sent;
int response; int response;
}; };

View file

@ -689,6 +689,17 @@ lws_unauthorised_basic_auth(struct lws *wsi)
int lws_clean_url(char *p) int lws_clean_url(char *p)
{ {
if (p[0] == 'h' && p[1] == 't' && p[2] == 't' && p[3] == 'p') {
p += 4;
if (*p == 's')
p++;
if (*p == ':') {
p++;
if (*p == '/')
p++;
}
}
while (*p) { while (*p) {
if (p[0] == '/' && p[1] == '/') { if (p[0] == '/' && p[1] == '/') {
char *p1 = p; char *p1 = p;
@ -777,7 +788,7 @@ lws_http_action(struct lws *wsi)
/* we insist on absolute paths */ /* we insist on absolute paths */
if (uri_ptr[0] != '/') { if (!uri_ptr || uri_ptr[0] != '/') {
lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL); lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
goto bail_nuke_ah; goto bail_nuke_ah;
@ -895,7 +906,7 @@ lws_http_action(struct lws *wsi)
const char *pa, *me; const char *pa, *me;
struct tm *tmp; struct tm *tmp;
time_t t = time(NULL); time_t t = time(NULL);
int l = 256; int l = 256, m;
if (wsi->access_log_pending) if (wsi->access_log_pending)
lws_access_log(wsi); lws_access_log(wsi);
@ -913,10 +924,7 @@ lws_http_action(struct lws *wsi)
if (!pa) if (!pa)
pa = "(unknown)"; pa = "(unknown)";
if (meth >= 0) me = method_names[meth];
me = method_names[meth];
else
me = "unknown";
lws_snprintf(wsi->access_log.header_log, l, lws_snprintf(wsi->access_log.header_log, l,
"%s - - [%s] \"%s %s %s\"", "%s - - [%s] \"%s %s %s\"",
@ -931,6 +939,23 @@ lws_http_action(struct lws *wsi)
l + 1, WSI_TOKEN_HTTP_USER_AGENT); l + 1, WSI_TOKEN_HTTP_USER_AGENT);
else else
lwsl_err("OOM getting user agent\n"); lwsl_err("OOM getting user agent\n");
for (m = 0; m < l; m++)
if (wsi->access_log.user_agent[m] == '\"')
wsi->access_log.user_agent[m] = '\'';
}
l = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_REFERER);
if (l) {
wsi->access_log.referrer = lws_malloc(l + 2);
if (wsi->access_log.referrer)
lws_hdr_copy(wsi, wsi->access_log.referrer,
l + 1, WSI_TOKEN_HTTP_REFERER);
else
lwsl_err("OOM getting user agent\n");
for (m = 0; m < l; m++)
if (wsi->access_log.referrer[m] == '\"')
wsi->access_log.referrer[m] = '\'';
} }
wsi->access_log_pending = 1; wsi->access_log_pending = 1;
} }
@ -997,10 +1022,13 @@ lws_http_action(struct lws *wsi)
hit->origin); hit->origin);
else else
n = lws_snprintf((char *)end, 256, n = lws_snprintf((char *)end, 256,
"%s%s%s/", oprot[lws_is_ssl(wsi)], "%s%s%s/", oprot[!!lws_is_ssl(wsi)],
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST), lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST),
uri_ptr); uri_ptr);
lwsl_notice("%s\n", end);
lws_clean_url((char *)end); lws_clean_url((char *)end);
lwsl_notice("%s\n", end);
n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY, n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
end, n, &p, end); end, n, &p, end);
@ -1878,8 +1906,17 @@ lws_http_transaction_completed(struct lws *wsi)
return 1; return 1;
} }
#endif #endif
} else } else {
lws_header_table_reset(wsi, 1); 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_HOLDING_AH,
wsi->vhost->keepalive_timeout);
}
} }
/* If we're (re)starting on headers, need other implied init */ /* If we're (re)starting on headers, need other implied init */
@ -2029,11 +2066,10 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
goto fail; goto fail;
if (type & LWS_ADOPT_HTTP) { if (type & LWS_ADOPT_HTTP) {
if (!lws_header_table_attach(new_wsi, 0)) { if (!lws_header_table_attach(new_wsi, 0))
lwsl_debug("Attached ah immediately\n"); lwsl_debug("Attached ah immediately\n");
} else { else
lwsl_notice("%s: waiting for ah\n", __func__); lwsl_info("%s: waiting for ah\n", __func__);
}
} }
return new_wsi; return new_wsi;
@ -2609,13 +2645,17 @@ lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type,
lwsl_info("file is being provided in gzip\n"); lwsl_info("file is being provided in gzip\n");
} }
if (
#if defined(LWS_WITH_RANGES) #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, if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
(unsigned char *)content_type, (unsigned char *)content_type,
strlen(content_type), &p, end)) strlen(content_type), &p, end))
return -1; return -1;
#if defined(LWS_WITH_RANGES)
if (ranges >= 2) { /* multipart byteranges */ if (ranges >= 2) { /* multipart byteranges */
strncpy(wsi->u.http.multipart_content_type, content_type, strncpy(wsi->u.http.multipart_content_type, content_type,
sizeof(wsi->u.http.multipart_content_type) - 1); sizeof(wsi->u.http.multipart_content_type) - 1);

View file

@ -854,6 +854,10 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
if (pollfd) if (pollfd)
our_fd = pollfd->fd; our_fd = pollfd->fd;
/*
* Phase 1: check every wsi on the timeout check list
*/
wsi = context->pt[tsi].timeout_list; wsi = context->pt[tsi].timeout_list;
while (wsi) { while (wsi) {
/* we have to take copies, because he may be deleted */ /* we have to take copies, because he may be deleted */
@ -868,7 +872,70 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
} }
wsi = wsi1; wsi = wsi1;
} }
/*
* Phase 2: double-check active ah timeouts independent of wsi
* timeout status
*/
for (n = 0; n < context->max_http_header_pool; n++)
if (pt->ah_pool[n].in_use && pt->ah_pool[n].wsi &&
pt->ah_pool[n].assigned &&
now - pt->ah_pool[n].assigned > 60) {
int len;
char buf[256];
const unsigned char *c;
/*
* a single ah session somehow got held for
* an unreasonable amount of time.
*
* Dump info on the connection...
*/
wsi = pt->ah_pool[n].wsi;
buf[0] = '\0';
lws_get_peer_simple(wsi, buf, sizeof(buf));
lwsl_notice("ah excessive hold: wsi %p\n"
" peer address: %s\n"
" ah rxpos %u, rxlen %u, pos %u\n",
wsi, buf, pt->ah_pool[n].rxpos,
pt->ah_pool[n].rxlen,
pt->ah_pool[n].pos);
m = 0;
do {
c = lws_token_to_string(m);
if (!c)
break;
len = lws_hdr_total_length(wsi, m);
if (!len || len > sizeof(buf) - 1) {
m++;
continue;
}
lws_hdr_copy(wsi, buf, sizeof buf, m);
buf[sizeof(buf) - 1] = '\0';
lwsl_notice(" %s = %s\n",
(const char *)c, buf);
m++;
} while (1);
/* ... and then drop the connection */
if (wsi->desc.sockfd == our_fd)
/* it was the guy we came to service! */
timed_out = 1;
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
}
#ifdef LWS_WITH_CGI #ifdef LWS_WITH_CGI
/*
* Phase 3: handle cgi timeouts
*/
lws_cgi_kill_terminated(pt); lws_cgi_kill_terminated(pt);
#endif #endif
#if 0 #if 0
@ -959,7 +1026,8 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
#endif #endif
// lwsl_debug("fd=%d, revents=%d, mode=%d, state=%d\n", pollfd->fd, pollfd->revents, (int)wsi->mode, (int)wsi->state); // 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) { if ((!(pollfd->revents & pollfd->events & LWS_POLLIN)) &&
(pollfd->revents & LWS_POLLHUP)) {
lwsl_debug("pollhup\n"); lwsl_debug("pollhup\n");
wsi->socket_is_permanently_unusable = 1; wsi->socket_is_permanently_unusable = 1;
goto close_and_handled; goto close_and_handled;

View file

@ -41,7 +41,7 @@ int lws_alloc_vfs_file(struct lws_context *context, const char *filename, uint8_
len = lws_vfs_get_length(fops_fd); len = lws_vfs_get_length(fops_fd);
*buf = malloc((size_t)len); *buf = malloc((size_t)len);
if (!buf) if (!*buf)
goto bail; goto bail;
if (lws_vfs_file_read(fops_fd, amount, *buf, len)) if (lws_vfs_file_read(fops_fd, amount, *buf, len))

View file

@ -1,5 +1,5 @@
Name: libwebsockets Name: libwebsockets
Version: 2.2.0 Version: 2.3.0
Release: 1%{?dist} Release: 1%{?dist}
Summary: Websocket Server and Client Library Summary: Websocket Server and Client Library
@ -49,13 +49,12 @@ rm -rf $RPM_BUILD_ROOT
%attr(755,root,root) %attr(755,root,root)
/usr/bin/libwebsockets-test-server /usr/bin/libwebsockets-test-server
/usr/bin/libwebsockets-test-server-extpoll /usr/bin/libwebsockets-test-server-extpoll
/usr/bin/libwebsockets-test-server-pthreads
/usr/bin/libwebsockets-test-client /usr/bin/libwebsockets-test-client
/usr/bin/libwebsockets-test-ping /usr/bin/libwebsockets-test-ping
/usr/bin/libwebsockets-test-echo /usr/bin/libwebsockets-test-echo
/usr/bin/libwebsockets-test-fraggle /usr/bin/libwebsockets-test-fraggle
/usr/bin/libwebsockets-test-fuzxy /usr/bin/libwebsockets-test-fuzxy
/%{_libdir}/libwebsockets.so.10 /%{_libdir}/libwebsockets.so.11
/%{_libdir}/libwebsockets.so /%{_libdir}/libwebsockets.so
/%{_libdir}/cmake/libwebsockets/LibwebsocketsConfig.cmake /%{_libdir}/cmake/libwebsockets/LibwebsocketsConfig.cmake
/%{_libdir}/cmake/libwebsockets/LibwebsocketsConfigVersion.cmake /%{_libdir}/cmake/libwebsockets/LibwebsocketsConfigVersion.cmake
@ -70,8 +69,12 @@ rm -rf $RPM_BUILD_ROOT
%attr(755,root,root) %attr(755,root,root)
/%{_libdir}/libwebsockets.a /%{_libdir}/libwebsockets.a
/%{_libdir}/pkgconfig/libwebsockets.pc /%{_libdir}/pkgconfig/libwebsockets.pc
/%{_libdir}/pkgconfig/libwebsockets_static.pc
%changelog %changelog
* Fri Jul 28 2017 Andy Green <andy@warmcat.com> 2.3.0-1
- MAJOR SONAMEBUMP APICHANGES Upstream 2.3.0 release
* Mon Mar 06 2017 Andy Green <andy@warmcat.com> 2.2.0-1 * Mon Mar 06 2017 Andy Green <andy@warmcat.com> 2.2.0-1
- MAJOR SONAMEBUMP APICHANGES Upstream 2.2.0 release - MAJOR SONAMEBUMP APICHANGES Upstream 2.2.0 release

View file

@ -58,11 +58,13 @@ static int pids[32];
#define LWSWS_CONFIG_STRING_SIZE (32 * 1024) #define LWSWS_CONFIG_STRING_SIZE (32 * 1024)
static const struct lws_extension exts[] = { static const struct lws_extension exts[] = {
#if !defined(LWS_NO_EXTENSIONS)
{ {
"permessage-deflate", "permessage-deflate",
lws_extension_callback_pm_deflate, lws_extension_callback_pm_deflate,
"permessage-deflate" "permessage-deflate"
}, },
#endif
{ NULL, NULL, NULL /* terminator */ } { NULL, NULL, NULL /* terminator */ }
}; };
@ -220,7 +222,7 @@ int main(int argc, char **argv)
break; break;
case 'h': case 'h':
fprintf(stderr, "Usage: lwsws [-c <config dir>] " fprintf(stderr, "Usage: lwsws [-c <config dir>] "
"[-d <log bitfield>] [-D] [--help]\n"); "[-d <log bitfield>] [--help]\n");
exit(1); exit(1);
} }
} }

View file

@ -474,7 +474,7 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
WSI_TOKEN_HOST) < 0) WSI_TOKEN_HOST) < 0)
return 1; return 1;
lws_snprintf(pss->onward, sizeof(pss->onward) - 1, lws_snprintf(pss->onward, sizeof(pss->onward) - 1,
"%s%s%s", oprot[lws_is_ssl(wsi)], "%s%s%s", oprot[!!lws_is_ssl(wsi)],
cookie, args->p); cookie, args->p);
lwsl_notice("redirecting to ourselves with cookie refresh\n"); lwsl_notice("redirecting to ourselves with cookie refresh\n");
/* we need a redirect to ourselves, session cookie is expired */ /* we need a redirect to ourselves, session cookie is expired */

View file

@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA* * MA 02110-1301 USA
* *
*/ */
@ -58,7 +58,6 @@ enum {
* while we haven't reported the result yet, we keep a linked-list of * while we haven't reported the result yet, we keep a linked-list of
* connection opens and their result. * connection opens and their result.
*/ */
struct pending_conn { struct pending_conn {
struct pending_conn *next; struct pending_conn *next;
char protocol[123]; char protocol[123];
@ -69,8 +68,9 @@ struct pending_conn {
unsigned char type; unsigned char type;
}; };
/* the parent, lws-meta connection */ /*
* the parent, lws-meta connection
*/
struct per_session_data__lws_meta { struct per_session_data__lws_meta {
struct lws *wsi[MAX_SUBCHANNELS + 1]; struct lws *wsi[MAX_SUBCHANNELS + 1];
char told_closing[MAX_SUBCHANNELS + 1]; char told_closing[MAX_SUBCHANNELS + 1];
@ -128,6 +128,7 @@ new_pending(struct per_session_data__lws_meta *pss)
if (pss->count_pending >= MAX_SUBCHANNELS * 2) { if (pss->count_pending >= MAX_SUBCHANNELS * 2) {
lwsl_notice("too many pending open subchannel\n"); lwsl_notice("too many pending open subchannel\n");
return NULL; return NULL;
} }
@ -136,6 +137,7 @@ new_pending(struct per_session_data__lws_meta *pss)
pend = malloc(sizeof(*pend)); pend = malloc(sizeof(*pend));
if (!pend) { if (!pend) {
lwsl_notice("OOM\n"); lwsl_notice("OOM\n");
return NULL; return NULL;
} }
@ -144,7 +146,6 @@ new_pending(struct per_session_data__lws_meta *pss)
return pend; return pend;
} }
static int static int
callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason, callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len) void *user, void *in, size_t len)
@ -188,7 +189,6 @@ callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
/* note which channel id */ /* note which channel id */
pend->ch = lws_get_channel_id(cwsi); pend->ch = lws_get_channel_id(cwsi);
if (lws_get_close_length(cwsi)) { if (lws_get_close_length(cwsi)) {
pend->len = lws_get_close_length(cwsi); pend->len = lws_get_close_length(cwsi);
memcpy(pend->protocol, lws_get_close_payload(cwsi), memcpy(pend->protocol, lws_get_close_payload(cwsi),
@ -224,19 +224,22 @@ callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
while (pend && p < end - 128) { while (pend && p < end - 128) {
switch (pend->type) { switch (pend->type) {
case PENDING_TYPE_OPEN_RESULT: case PENDING_TYPE_OPEN_RESULT:
lwsl_debug("open result %s %s\n", pend->cookie, pend->protocol); lwsl_debug("open result %s %s\n",
pend->cookie, pend->protocol);
*p++ = LWS_META_CMD_OPEN_RESULT; *p++ = LWS_META_CMD_OPEN_RESULT;
memcpy(p, pend->cookie, memcpy(p, pend->cookie,
strlen(pend->cookie) + 1); strlen(pend->cookie) + 1);
p += strlen(pend->cookie) + 1; p += strlen(pend->cookie) + 1;
*p++ = LWS_META_CHANNEL_OFFSET_TRANSPORT + pend->ch; *p++ = LWS_META_TRANSPORT_OFFSET +
pend->ch;
memcpy(p, pend->protocol, memcpy(p, pend->protocol,
strlen(pend->protocol) + 1); strlen(pend->protocol) + 1);
p += strlen(pend->protocol) + 1; p += strlen(pend->protocol) + 1;
break; break;
case PENDING_TYPE_CHILD_CLOSE: case PENDING_TYPE_CHILD_CLOSE:
*p++ = LWS_META_CMD_CLOSE_NOTIFY; *p++ = LWS_META_CMD_CLOSE_NOTIFY;
*p++ = LWS_META_CHANNEL_OFFSET_TRANSPORT + pend->ch; *p++ = LWS_META_TRANSPORT_OFFSET +
pend->ch;
for (n = 0; n < pend->len; n++) for (n = 0; n < pend->len; n++)
*p++ = pend->protocol[n]; *p++ = pend->protocol[n];
break; break;
@ -250,14 +253,15 @@ callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
} }
if (p != start) { if (p != start) {
if (lws_write(wsi, start, p - start, LWS_WRITE_BINARY) < 0) if (lws_write(wsi, start, p - start,
LWS_WRITE_BINARY) < 0)
return 1; return 1;
if (pend) /* still more */ if (pend) /* still more */
lws_callback_on_writable(wsi); lws_callback_on_writable(wsi);
break; break;
} }
/* PRIORITY 2: pick a child to get the writable callback */ /* PRIORITY 2: pick a child for the writable callback */
cwsi = NULL; cwsi = NULL;
for (n = 0; n < MAX_SUBCHANNELS; n++) { for (n = 0; n < MAX_SUBCHANNELS; n++) {
@ -269,7 +273,6 @@ callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
break; break;
} }
} }
} else } else
/* one child is in middle of message, stay with it */ /* one child is in middle of message, stay with it */
cwsi = pss->wsi[pss->active_subchannel_tx]; cwsi = pss->wsi[pss->active_subchannel_tx];
@ -289,7 +292,6 @@ callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
* at the start of a message, we may have one or more * at the start of a message, we may have one or more
* lws_meta command blocks. * lws_meta command blocks.
*/ */
while (pss->state != MP_IDLE && while (pss->state != MP_IDLE &&
(unsigned int)(bin - (unsigned char *)in) < len) { (unsigned int)(bin - (unsigned char *)in) < len) {
@ -328,7 +330,8 @@ callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
// open result is also illegal to receive // open result is also illegal to receive
default: default:
lwsl_notice("illegal lws_meta cmd 0x%x\n", bin[-1]); lwsl_notice("bad lws_meta cmd 0x%x\n",
bin[-1]);
return -1; return -1;
} }
@ -414,12 +417,13 @@ callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
break; break;
case MP_CLOSE_CHID: case MP_CLOSE_CHID:
pss->ch = (*bin++) - LWS_META_CHANNEL_OFFSET_TRANSPORT; pss->ch = (*bin++) - LWS_META_TRANSPORT_OFFSET;
pss->state = MP_CLOSE_LEN; pss->state = MP_CLOSE_LEN;
pss->pos = 0; pss->pos = 0;
break; break;
case MP_CLOSE_LEN: case MP_CLOSE_LEN:
pss->close_len = (*bin++) - LWS_META_CHANNEL_OFFSET_TRANSPORT; pss->close_len = (*bin++) -
LWS_META_TRANSPORT_OFFSET;
lwsl_debug("close len %d\n", pss->close_len); lwsl_debug("close len %d\n", pss->close_len);
pss->state = MP_CLOSE_CODEM; pss->state = MP_CLOSE_CODEM;
pss->pos = 0; pss->pos = 0;
@ -443,46 +447,46 @@ callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
if (--pss->close_len) if (--pss->close_len)
break; break;
pss->state = MP_CMD;
cwsi = lws_get_channel_wsi(pss, pss->ch); cwsi = lws_get_channel_wsi(pss, pss->ch);
if (!cwsi) if (!cwsi) {
lwsl_notice("received close (%d) for unknown ch %d\n", pss->which_close, pss->ch); lwsl_notice("close (%d) bad ch %d\n",
else { pss->which_close, pss->ch);
break;
if (pss->which_close == LWS_META_CMD_CLOSE_RQ) {
if (lws_get_protocol(cwsi)->callback(cwsi,
LWS_CALLBACK_WS_PEER_INITIATED_CLOSE,
lws_wsi_user(cwsi),
&pss->close, pss->pos))
return -1;
/*
* we need to echo back the close payload
* when we send the close notification
*/
lws_close_reason(cwsi,
pss->close_status_16,
&pss->close[2], pss->pos - 2);
}
/* so force him closed */
lws_set_timeout(cwsi,
PENDING_TIMEOUT_KILLED_BY_PARENT,
LWS_TO_KILL_SYNC);
} }
pss->state = MP_CMD; if (pss->which_close == LWS_META_CMD_CLOSE_RQ) {
if (lws_get_protocol(cwsi)->callback(
cwsi,
LWS_CALLBACK_WS_PEER_INITIATED_CLOSE,
lws_wsi_user(cwsi), &pss->close,
pss->pos))
return -1;
/*
* we need to echo back the close payload
* when we send the close notification
*/
lws_close_reason(cwsi,
pss->close_status_16,
&pss->close[2],
pss->pos - 2);
}
/* so force him closed */
lws_set_timeout(cwsi,
PENDING_TIMEOUT_KILLED_BY_PARENT,
LWS_TO_KILL_SYNC);
break; break;
case MP_WRITE_CHID: case MP_WRITE_CHID:
pss->active_subchannel_rx = (*bin++) - pss->active_subchannel_rx = (*bin++) -
LWS_META_CHANNEL_OFFSET_TRANSPORT; LWS_META_TRANSPORT_OFFSET;
pss->state = MP_IDLE; pss->state = MP_IDLE;
break; break;
} }
} }
len -= bin - (unsigned char *)in; len -= bin - (unsigned char *)in;
@ -492,22 +496,19 @@ callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
cwsi = lws_get_channel_wsi(pss, pss->active_subchannel_rx); cwsi = lws_get_channel_wsi(pss, pss->active_subchannel_rx);
if (!cwsi) { if (!cwsi) {
lwsl_notice("invalid ch %d\n", pss->active_subchannel_rx); lwsl_notice("bad ch %d\n", pss->active_subchannel_rx);
return -1; return -1;
} }
lwsl_debug("%s: RX len %d\n", __func__, (int)len); lwsl_debug("%s: RX len %d\n", __func__, (int)len);
if (lws_get_protocol(cwsi)->callback( if (lws_get_protocol(cwsi)->callback(cwsi,
cwsi, LWS_CALLBACK_RECEIVE,
LWS_CALLBACK_RECEIVE, lws_wsi_user(cwsi), bin, len))
lws_wsi_user(cwsi),
bin, len)) {
lws_set_timeout(cwsi, lws_set_timeout(cwsi,
PENDING_TIMEOUT_KILLED_BY_PARENT, PENDING_TIMEOUT_KILLED_BY_PARENT,
LWS_TO_KILL_SYNC); LWS_TO_KILL_SYNC);
}
if (lws_is_final_fragment(wsi)) { if (lws_is_final_fragment(wsi)) {
pss->active_subchannel_rx = 0; pss->active_subchannel_rx = 0;
@ -526,15 +527,17 @@ callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
if ((pas->wp & 7) == 4 /*LWS_WRITE_CLOSE */) { if ((pas->wp & 7) == 4 /*LWS_WRITE_CLOSE */) {
*p++ = LWS_META_CMD_CLOSE_NOTIFY; *p++ = LWS_META_CMD_CLOSE_NOTIFY;
*p++ = LWS_META_CHANNEL_OFFSET_TRANSPORT + *p++ = LWS_META_TRANSPORT_OFFSET +
lws_get_channel_id(pas->wsi); lws_get_channel_id(pas->wsi);
*p++ = pas->len - 2 + LWS_META_CHANNEL_OFFSET_TRANSPORT; *p++ = (unsigned char)pas->len +
LWS_META_TRANSPORT_OFFSET - 2;
*p++ = *bin++; *p++ = *bin++;
*p++ = *bin++; *p++ = *bin++;
for (n = 0; n < (int)pas->len - 2; n++) for (n = 0; n < (int)pas->len - 2; n++)
*p++ = bin[n]; *p++ = bin[n];
if (lws_write(wsi, start, p - start, LWS_WRITE_BINARY) < 0) if (lws_write(wsi, start, p - start,
LWS_WRITE_BINARY) < 0)
return 1; return 1;
pss->told_closing[lws_get_channel_id(pas->wsi)] = 1; pss->told_closing[lws_get_channel_id(pas->wsi)] = 1;
@ -553,10 +556,9 @@ callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
bin -= 2; bin -= 2;
bin[0] = LWS_META_CMD_WRITE; bin[0] = LWS_META_CMD_WRITE;
bin[1] = lws_get_channel_id(pas->wsi) + bin[1] = lws_get_channel_id(pas->wsi) +
LWS_META_CHANNEL_OFFSET_TRANSPORT; LWS_META_TRANSPORT_OFFSET;
if (lws_write(wsi, bin, pas->len + 2, pas->wp) < 0) if (lws_write(wsi, bin, pas->len + 2, pas->wp) < 0)
return 1; return 1;
} else } else
if (lws_write(wsi, bin, pas->len, pas->wp) < 0) if (lws_write(wsi, bin, pas->len, pas->wp) < 0)
return 1; return 1;
@ -579,6 +581,7 @@ callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
callback_lws_meta, \ callback_lws_meta, \
sizeof(struct per_session_data__lws_meta), \ sizeof(struct per_session_data__lws_meta), \
1024, /* rx buf size must be >= permessage-deflate rx size */ \ 1024, /* rx buf size must be >= permessage-deflate rx size */ \
0, NULL, 0 \
} }
#if !defined (LWS_PLUGIN_STATIC) #if !defined (LWS_PLUGIN_STATIC)

View file

@ -10,7 +10,9 @@ SHELL=/bin/bash
ESPPORT ?= $(CONFIG_ESPTOOLPY_PORT) ESPPORT ?= $(CONFIG_ESPTOOLPY_PORT)
jbi=$(COMPONENT_PATH)/../build/json-buildinfo LWS_BUILD_PATH=$(PROJECT_PATH)/build
jbi=$(LWS_BUILD_PATH)/json-buildinfo
FAC=$(CONFIG_LWS_IS_FACTORY_APPLICATION) FAC=$(CONFIG_LWS_IS_FACTORY_APPLICATION)
ifeq ($(FAC),) ifeq ($(FAC),)
@ -19,20 +21,20 @@ endif
export FAC export FAC
DIRNAME:=$(shell basename $$(pwd) | tr -d '\n') DIRNAME:=$(shell basename $$(pwd) | tr -d '\n')
$(COMPONENT_PATH)/../build/pack.img: $(APP_BIN) $(LWS_BUILD_PATH)/pack.img: $(APP_BIN)
GNUSTAT=stat ;\ GNUSTAT=stat ;\
if [ `which gstat 2>/dev/null` ] ; then GNUSTAT=gstat ; fi ;\ if [ `which gstat 2>/dev/null` ] ; then GNUSTAT=gstat ; fi ;\
DIRNAME=$$(basename $$(pwd) | tr -d '\n') ;\ DIRNAME=$$(basename $$(pwd) | tr -d '\n') ;\
genromfs -f $(COMPONENT_PATH)/../build/romfs.img -d $(COMPONENT_PATH)/../romfs-files ; \ genromfs -f $(LWS_BUILD_PATH)/romfs.img -d $(PROJECT_PATH)/romfs-files ; \
RLEN=$$($$GNUSTAT -c %s $(COMPONENT_PATH)/../build/romfs.img) ;\ RLEN=$$($$GNUSTAT -c %s $(LWS_BUILD_PATH)/romfs.img) ;\
LEN=$$($$GNUSTAT -c %s $(COMPONENT_PATH)/../build/$$DIRNAME.bin) ;\ LEN=$$($$GNUSTAT -c %s $(LWS_BUILD_PATH)/$$DIRNAME.bin) ;\
printf " Original length: 0x%06x (%8d)\n" $$LEN $$LEN ; \ printf " Original length: 0x%06x (%8d)\n" $$LEN $$LEN ; \
printf %02x $$(( $$RLEN % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\ printf %02x $$(( $$RLEN % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
printf %02x $$(( ( $$RLEN / 256 ) % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\ printf %02x $$(( ( $$RLEN / 256 ) % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
printf %02x $$(( ( $$RLEN / 65536 ) % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\ printf %02x $$(( ( $$RLEN / 65536 ) % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
printf %02x $$(( ( $$RLEN / 16777216 ) % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\ printf %02x $$(( ( $$RLEN / 16777216 ) % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
cat $(COMPONENT_PATH)/../build/romfs.img >>$(COMPONENT_PATH)/../build/$$DIRNAME.bin ; \ cat $(LWS_BUILD_PATH)/romfs.img >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ; \
LEN=$$($$GNUSTAT -c %s $(COMPONENT_PATH)/../build/$$DIRNAME.bin) ;\ LEN=$$($$GNUSTAT -c %s $(LWS_BUILD_PATH)/$$DIRNAME.bin) ;\
UNIXTIME=$$(date +%s | tr -d '\n') ; \ UNIXTIME=$$(date +%s | tr -d '\n') ; \
echo -n -e "{\r\n \"schema\": \"lws1\",\r\n \"model\": \"$(CONFIG_LWS_MODEL_NAME)\",\r\n \"builder\": \"" > $(jbi) ;\ echo -n -e "{\r\n \"schema\": \"lws1\",\r\n \"model\": \"$(CONFIG_LWS_MODEL_NAME)\",\r\n \"builder\": \"" > $(jbi) ;\
hostname | tr -d '\n' >> $(jbi) ;\ hostname | tr -d '\n' >> $(jbi) ;\
@ -50,14 +52,14 @@ $(COMPONENT_PATH)/../build/pack.img: $(APP_BIN)
echo -n -e "\",\r\n \"factory\": \"$(FAC)" >> $(jbi) ;\ echo -n -e "\",\r\n \"factory\": \"$(FAC)" >> $(jbi) ;\
echo -n -e "\"\r\n}" >> $(jbi) ;\ echo -n -e "\"\r\n}" >> $(jbi) ;\
JLEN=$$($$GNUSTAT -c %s $(jbi)) ;\ JLEN=$$($$GNUSTAT -c %s $(jbi)) ;\
printf %02x $$(( $$JLEN % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\ printf %02x $$(( $$JLEN % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
printf %02x $$(( ( $$JLEN / 256 ) % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\ printf %02x $$(( ( $$JLEN / 256 ) % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
printf %02x $$(( ( $$JLEN / 65536 ) % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\ printf %02x $$(( ( $$JLEN / 65536 ) % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
printf %02x $$(( ( $$JLEN / 16777216 ) % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\ printf %02x $$(( ( $$JLEN / 16777216 ) % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
cat $(jbi) >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\ cat $(jbi) >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
cp $(COMPONENT_PATH)/../build/$$DIRNAME.bin $(COMPONENT_PATH)/../build/pack.img ;\ cp $(LWS_BUILD_PATH)/$$DIRNAME.bin $(LWS_BUILD_PATH)/pack.img ;\
LEN=$$($$GNUSTAT -c %s $(COMPONENT_PATH)/../build/$$DIRNAME.bin) ;\ LEN=$$($$GNUSTAT -c %s $(LWS_BUILD_PATH)/$$DIRNAME.bin) ;\
cp $(COMPONENT_PATH)/../build/$$DIRNAME.bin $(COMPONENT_PATH)/../build/$$DIRNAME-$$UNIXTIME.bin ;\ cp $(LWS_BUILD_PATH)/$$DIRNAME.bin $(LWS_BUILD_PATH)/$$DIRNAME-$$UNIXTIME.bin ;\
printf " After ROMFS + Build info: 0x%06x (%8d)\n" $$LEN $$LEN printf " After ROMFS + Build info: 0x%06x (%8d)\n" $$LEN $$LEN
.PHONY: manifest .PHONY: manifest
@ -76,17 +78,17 @@ endif
cat $(F)/build/json-buildinfo >> build/manifest.json cat $(F)/build/json-buildinfo >> build/manifest.json
echo -n -e "\r\n}\r\n" >> build/manifest.json echo -n -e "\r\n}\r\n" >> build/manifest.json
all: $(COMPONENT_PATH)/../build/pack.img all: $(LWS_BUILD_PATH)/pack.img
flash: $(COMPONENT_PATH)/../build/pack.img flash: $(LWS_BUILD_PATH)/pack.img
flash_ota: $(COMPONENT_PATH)/../build/pack.img flash_ota: $(LWS_BUILD_PATH)/pack.img
DIRNAME=$$(basename $$(pwd) | tr -d '\n') ;\ DIRNAME=$$(basename $$(pwd) | tr -d '\n') ;\
$(IDF_PATH)/components/esptool_py/esptool/esptool.py \ $(IDF_PATH)/components/esptool_py/esptool/esptool.py \
--chip esp32 \ --chip esp32 \
--port $(ESPPORT) \ --port $(ESPPORT) \
--baud $(CONFIG_ESPTOOLPY_BAUD) \ --baud $(CONFIG_ESPTOOLPY_BAUD) \
write_flash 0x110000 $(COMPONENT_PATH)/../build/$$DIRNAME.bin write_flash 0x110000 $(LWS_BUILD_PATH)/$$DIRNAME.bin
erase_ota: erase_ota:
$(IDF_PATH)/components/esptool_py/esptool/esptool.py \ $(IDF_PATH)/components/esptool_py/esptool/esptool.py \

View file

@ -29,10 +29,10 @@ function check {
fi fi
if [ "$1" = "defaultplusforbidden" ] ; then if [ "$1" = "defaultplusforbidden" ] ; then
cat $INSTALLED/../share/libwebsockets-test-server/test.html > /tmp/plusforb cat $INSTALLED/../share/libwebsockets-test-server/test.html > /tmp/plusforb
echo -e -n "HTTP/1.1 403 Forbidden\x0d\x0aserver: libwebsockets\x0d\x0acontent-type: text/html\x0d\x0acontent-length: 38\x0d\x0a\x0d\x0a<html><body><h1>403</h1></body></html>" >> /tmp/plusforb echo -e -n "HTTP/1.1 403 Forbidden\x0d\x0acontent-type: text/html\x0d\x0acontent-length: 38\x0d\x0a\x0d\x0a<html><body><h1>403</h1></body></html>" >> /tmp/plusforb
diff /tmp/lwscap /tmp/plusforb > /dev/null diff /tmp/lwscap /tmp/plusforb > /dev/null
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo "FAIL: got something other than test.html back" echo "FAIL: got something other than test.html + forbidden back"
exit 1 exit 1
fi fi
fi fi
@ -101,7 +101,9 @@ killall libwebsockets-test-server 2>/dev/null
libwebsockets-test-server -d15 2>> $LOG & libwebsockets-test-server -d15 2>> $LOG &
CPID=$! CPID=$!
while [ -z "`grep Listening $LOG`" ] ; do echo "Started server on PID $CPID"
while [ -z "`grep ort\ 7681 $LOG`" ] ; do
sleep 0.5s sleep 0.5s
done done
check check
@ -220,7 +222,7 @@ echo -e "GET ...................................................................
check check
echo echo
echo "---- good request but http payload coming too (should be ignored and test.html served)" echo "---- good request but http payload coming too (test.html served then forbidden)"
echo -e "GET /test.html HTTP/1.1\x0d\x0a\x0d\x0aILLEGAL-PAYLOAD........................................" \ echo -e "GET /test.html HTTP/1.1\x0d\x0a\x0d\x0aILLEGAL-PAYLOAD........................................" \
"......................................................................................................................." \ "......................................................................................................................." \
"......................................................................................................................." \ "......................................................................................................................." \

View file

@ -536,7 +536,8 @@ int main(int argc, char **argv)
/* stats */ /* stats */
fprintf(stderr, "\n--- %s websocket ping statistics " if (global_rx_count && global_tx_count)
fprintf(stderr, "\n--- %s websocket ping statistics "
"using %d connections ---\n" "using %d connections ---\n"
"%lu packets transmitted, %lu received, " "%lu packets transmitted, %lu received, "
"%lu%% packet loss, time %ldms\n" "%lu%% packet loss, time %ldms\n"

View file

@ -524,7 +524,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
} }
#ifndef LWS_NO_CLIENT #ifndef LWS_NO_CLIENT
if (pss->reason_bf & 2) { if (pss->reason_bf & LWS_CB_REASON_AUX_BF__PROXY) {
char *px = buf + LWS_PRE; char *px = buf + LWS_PRE;
int lenx = sizeof(buf) - LWS_PRE; int lenx = sizeof(buf) - LWS_PRE;
/* /*
@ -535,7 +535,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
*/ */
pss->reason_bf &= ~2; pss->reason_bf &= ~LWS_CB_REASON_AUX_BF__PROXY;
wsi1 = lws_get_child(wsi); wsi1 = lws_get_child(wsi);
if (!wsi1) if (!wsi1)
break; break;
@ -674,7 +674,7 @@ bail:
if (!lws_get_parent(wsi)) if (!lws_get_parent(wsi))
break; break;
pss1 = lws_wsi_user(lws_get_parent(wsi)); pss1 = lws_wsi_user(lws_get_parent(wsi));
pss1->reason_bf |= 2; pss1->reason_bf |= LWS_CB_REASON_AUX_BF__PROXY;
lws_callback_on_writable(lws_get_parent(wsi)); lws_callback_on_writable(lws_get_parent(wsi));
break; break;
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:

View file

@ -1,7 +1,7 @@
/* /*
* libwebsockets-test-server - libwebsockets test implementation * libwebsockets-test-server - libwebsockets test implementation
* *
* Copyright (C) 2011-2016 Andy Green <andy@warmcat.com> * Copyright (C) 2011-2017 Andy Green <andy@warmcat.com>
* *
* This file is made available under the Creative Commons CC0 1.0 * This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication. * Universal Public Domain Dedication.
@ -34,6 +34,11 @@ char *resource_path = LOCAL_RESOURCE_PATH;
char crl_path[1024] = ""; char crl_path[1024] = "";
#endif #endif
#define LWS_PLUGIN_STATIC
#include "../plugins/protocol_lws_mirror.c"
#include "../plugins/protocol_lws_status.c"
#include "../plugins/protocol_lws_meta.c"
/* singlethreaded version --> no locks */ /* singlethreaded version --> no locks */
void test_server_lock(int care) void test_server_lock(int care)
@ -59,60 +64,53 @@ void test_server_unlock(int care)
*/ */
enum demo_protocols { enum demo_protocols {
/* always first */ /* always first */
PROTOCOL_HTTP = 0, PROTOCOL_HTTP = 0,
PROTOCOL_DUMB_INCREMENT, PROTOCOL_DUMB_INCREMENT,
PROTOCOL_LWS_MIRROR, PROTOCOL_LWS_MIRROR,
PROTOCOL_LWS_META,
/* always last */ /* always last */
DEMO_PROTOCOL_COUNT DEMO_PROTOCOL_COUNT
}; };
/* list of supported protocols and callbacks */ /* list of supported protocols and callbacks */
static struct lws_protocols protocols[] = { static struct lws_protocols protocols[] = {
/* first protocol must always be HTTP handler */ /* first protocol must always be HTTP handler */
{ {
"http-only", /* name */ "http-only", /* name */
callback_http, /* callback */ callback_http, /* callback */
sizeof (struct per_session_data__http), /* per_session_data_size */ sizeof (struct per_session_data__http), /* per_session_data_size */
0, /* max frame size / rx buffer */ 0, /* max frame size / rx buffer */
}, },
{ {
"dumb-increment-protocol", "dumb-increment-protocol",
callback_dumb_increment, callback_dumb_increment,
sizeof(struct per_session_data__dumb_increment), sizeof(struct per_session_data__dumb_increment),
10, 10,
}, },
{
"lws-mirror-protocol", LWS_PLUGIN_PROTOCOL_MIRROR,
callback_lws_mirror, LWS_PLUGIN_PROTOCOL_LWS_STATUS,
sizeof(struct per_session_data__lws_mirror), LWS_PLUGIN_PROTOCOL_LWS_META,
128, { NULL, NULL, 0, 0 } /* terminator */
},
{
"lws-status",
callback_lws_status,
sizeof(struct per_session_data__lws_status),
128,
},
{ NULL, NULL, 0, 0 } /* terminator */
}; };
static const struct lws_extension exts[] = { static const struct lws_extension exts[] = {
{ {
"permessage-deflate", "permessage-deflate",
lws_extension_callback_pm_deflate, lws_extension_callback_pm_deflate,
"permessage-deflate; client_no_context_takeover; client_max_window_bits" "permessage-deflate; client_no_context_takeover; client_max_window_bits"
}, },
{ {
"deflate-frame", "deflate-frame",
lws_extension_callback_pm_deflate, lws_extension_callback_pm_deflate,
"deflate_frame" "deflate_frame"
}, },
{ NULL, NULL, NULL /* terminator */ } { NULL, NULL, NULL /* terminator */ }
}; };
/* this shows how to override the lws file operations. You don't need /* this shows how to override the lws file operations. You don't need
@ -121,226 +119,227 @@ static const struct lws_extension exts[] = {
*/ */
static lws_fop_fd_t static lws_fop_fd_t
test_server_fops_open(const struct lws_plat_file_ops *fops, test_server_fops_open(const struct lws_plat_file_ops *fops,
const char *vfs_path, const char *vpath, const char *vfs_path, const char *vpath,
lws_fop_flags_t *flags) lws_fop_flags_t *flags)
{ {
lws_fop_fd_t n; lws_fop_fd_t n;
/* call through to original platform implementation */ /* call through to original platform implementation */
n = fops_plat.open(fops, vfs_path, vpath, flags); n = fops_plat.open(fops, vfs_path, vpath, flags);
lwsl_notice("%s: opening %s, ret %p\n", __func__, vfs_path, n); lwsl_notice("%s: opening %s, ret %p\n", __func__, vfs_path, n);
return n; return n;
} }
void signal_cb(evutil_socket_t sock_fd, short events, void *ctx) void signal_cb(evutil_socket_t sock_fd, short events, void *ctx)
{ {
lwsl_notice("Signal caught, exiting...\n"); struct event_base *event_base_loop = ctx;
force_exit = 1;
if (events & EV_SIGNAL) { lwsl_notice("Signal caught, exiting...\n");
struct event_base *event_base_loop = event_get_base((struct event *) ctx); force_exit = 1;
event_base_loopbreak(event_base_loop); if (events & EV_SIGNAL)
} event_base_loopbreak(event_base_loop);
} }
static void static void
ev_timeout_cb (evutil_socket_t sock_fd, short events, void *ctx) ev_timeout_cb (evutil_socket_t sock_fd, short events, void *ctx)
{ {
lws_callback_on_writable_all_protocol(context, lws_callback_on_writable_all_protocol(context,
&protocols[PROTOCOL_DUMB_INCREMENT]); &protocols[PROTOCOL_DUMB_INCREMENT]);
} }
static struct option options[] = { static struct option options[] = {
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "debug", required_argument, NULL, 'd' }, { "debug", required_argument, NULL, 'd' },
{ "port", required_argument, NULL, 'p' }, { "port", required_argument, NULL, 'p' },
{ "ssl", no_argument, NULL, 's' }, { "ssl", no_argument, NULL, 's' },
{ "allow-non-ssl", no_argument, NULL, 'a' }, { "allow-non-ssl", no_argument, NULL, 'a' },
{ "interface", required_argument, NULL, 'i' }, { "interface", required_argument, NULL, 'i' },
{ "closetest", no_argument, NULL, 'c' }, { "closetest", no_argument, NULL, 'c' },
{ "libevent", no_argument, NULL, 'e' }, { "libevent", no_argument, NULL, 'e' },
#ifndef LWS_NO_DAEMONIZE #ifndef LWS_NO_DAEMONIZE
{ "daemonize", no_argument, NULL, 'D' }, { "daemonize", no_argument, NULL, 'D' },
#endif #endif
{ "resource_path", required_argument, NULL, 'r' }, { "resource_path", required_argument, NULL, 'r' },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int sigs[] = { SIGINT, SIGKILL, SIGTERM, SIGSEGV, SIGFPE }; int sigs[] = { SIGINT, SIGKILL, SIGTERM, SIGSEGV, SIGFPE };
struct event *signals[ARRAY_SIZE(sigs)]; struct event *signals[ARRAY_SIZE(sigs)];
struct event_base *event_base_loop = event_base_new(); struct event_base *event_base_loop = event_base_new();
struct lws_context_creation_info info; struct lws_context_creation_info info;
char interface_name[128] = ""; char interface_name[128] = "";
const char *iface = NULL; const char *iface = NULL;
struct event *timeout_watcher; struct event *timeout_watcher;
char cert_path[1024]; char cert_path[1024];
char key_path[1024]; char key_path[1024];
int use_ssl = 0; int use_ssl = 0;
int opts = 0; int opts = 0;
int n = 0; int n = 0;
#ifndef _WIN32 #ifndef _WIN32
int syslog_options = LOG_PID | LOG_PERROR; int syslog_options = LOG_PID | LOG_PERROR;
#endif #endif
#ifndef LWS_NO_DAEMONIZE #ifndef LWS_NO_DAEMONIZE
int daemonize = 0; int daemonize = 0;
#endif #endif
/* /*
* take care to zero down the info struct, he contains random garbaage * take care to zero down the info struct, he contains random garbaage
* from the stack otherwise * from the stack otherwise
*/ */
memset(&info, 0, sizeof info); memset(&info, 0, sizeof info);
info.port = 7681; info.port = 7681;
while (n >= 0) { while (n >= 0) {
n = getopt_long(argc, argv, "eci:hsap:d:Dr:", options, NULL); n = getopt_long(argc, argv, "eci:hsap:d:Dr:", options, NULL);
if (n < 0) if (n < 0)
continue; continue;
switch (n) { switch (n) {
case 'e': case 'e':
opts |= LWS_SERVER_OPTION_LIBEVENT; opts |= LWS_SERVER_OPTION_LIBEVENT;
break; break;
#ifndef LWS_NO_DAEMONIZE #ifndef LWS_NO_DAEMONIZE
case 'D': case 'D':
daemonize = 1; daemonize = 1;
#ifndef _WIN32 #ifndef _WIN32
syslog_options &= ~LOG_PERROR; syslog_options &= ~LOG_PERROR;
#endif
break;
#endif #endif
case 'd': break;
debug_level = atoi(optarg); #endif
break; case 'd':
case 's': debug_level = atoi(optarg);
use_ssl = 1; break;
break; case 's':
case 'a': use_ssl = 1;
opts |= LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT; break;
break; case 'a':
case 'p': opts |= LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT;
info.port = atoi(optarg); break;
break; case 'p':
case 'i': info.port = atoi(optarg);
strncpy(interface_name, optarg, sizeof interface_name); break;
interface_name[(sizeof interface_name) - 1] = '\0'; case 'i':
iface = interface_name; strncpy(interface_name, optarg, sizeof interface_name);
break; interface_name[(sizeof interface_name) - 1] = '\0';
case 'c': iface = interface_name;
close_testing = 1; break;
fprintf(stderr, " Close testing mode -- closes on " case 'c':
"client after 50 dumb increments" close_testing = 1;
"and suppresses lws_mirror spam\n"); fprintf(stderr, " Close testing mode -- closes on "
break; "client after 50 dumb increments"
case 'r': "and suppresses lws_mirror spam\n");
resource_path = optarg; break;
printf("Setting resource path to \"%s\"\n", resource_path); case 'r':
break; resource_path = optarg;
case 'h': printf("Setting resource path to \"%s\"\n", resource_path);
fprintf(stderr, "Usage: test-server " break;
"[--port=<p>] [--ssl] " case 'h':
"[-d <log bitfield>] " fprintf(stderr, "Usage: test-server "
"[--resource_path <path>]\n"); "[--port=<p>] [--ssl] "
exit(1); "[-d <log bitfield>] "
} "[--resource_path <path>]\n");
} exit(1);
}
}
#if !defined(LWS_NO_DAEMONIZE) && !defined(WIN32) #if !defined(LWS_NO_DAEMONIZE) && !defined(WIN32)
/* /*
* normally lock path would be /var/lock/lwsts or similar, to * normally lock path would be /var/lock/lwsts or similar, to
* simplify getting started without having to take care about * simplify getting started without having to take care about
* permissions or running as root, set to /tmp/.lwsts-lock * permissions or running as root, set to /tmp/.lwsts-lock
*/ */
if (daemonize && lws_daemonize("/tmp/.lwsts-lock")) { if (daemonize && lws_daemonize("/tmp/.lwsts-lock")) {
fprintf(stderr, "Failed to daemonize\n"); fprintf(stderr, "Failed to daemonize\n");
return 1; return 1;
} }
#endif #endif
for (n = 0; n < ARRAY_SIZE(sigs); n++) { for (n = 0; n < ARRAY_SIZE(sigs); n++) {
signals[n] = evsignal_new(event_base_loop, sigs[n], signal_cb, event_self_cbarg()); signals[n] = evsignal_new(event_base_loop, sigs[n], signal_cb, event_base_loop);
evsignal_add(signals[n], NULL);
} evsignal_add(signals[n], NULL);
}
#ifndef _WIN32 #ifndef _WIN32
/* we will only try to log things according to our debug_level */ /* we will only try to log things according to our debug_level */
setlogmask(LOG_UPTO (LOG_DEBUG)); setlogmask(LOG_UPTO (LOG_DEBUG));
openlog("lwsts", syslog_options, LOG_DAEMON); openlog("lwsts", syslog_options, LOG_DAEMON);
#endif #endif
/* tell the library what debug level to emit and to send it to syslog */ /* tell the library what debug level to emit and to send it to syslog */
lws_set_log_level(debug_level, lwsl_emit_syslog); lws_set_log_level(debug_level, lwsl_emit_syslog);
lwsl_notice("libwebsockets test server libevent - license LGPL2.1+SLE\n"); lwsl_notice("libwebsockets test server libevent - license LGPL2.1+SLE\n");
lwsl_notice("(C) Copyright 2010-2016 Andy Green <andy@warmcat.com>\n"); lwsl_notice("(C) Copyright 2010-2016 Andy Green <andy@warmcat.com>\n");
printf("Using resource path \"%s\"\n", resource_path); printf("Using resource path \"%s\"\n", resource_path);
info.iface = iface; info.iface = iface;
info.protocols = protocols; info.protocols = protocols;
info.extensions = exts; info.extensions = exts;
info.ssl_cert_filepath = NULL; info.ssl_cert_filepath = NULL;
info.ssl_private_key_filepath = NULL; info.ssl_private_key_filepath = NULL;
if (use_ssl) { if (use_ssl) {
if (strlen(resource_path) > sizeof(cert_path) - 32) { if (strlen(resource_path) > sizeof(cert_path) - 32) {
lwsl_err("resource path too long\n"); lwsl_err("resource path too long\n");
return -1; return -1;
} }
sprintf(cert_path, "%s/libwebsockets-test-server.pem", sprintf(cert_path, "%s/libwebsockets-test-server.pem",
resource_path); resource_path);
if (strlen(resource_path) > sizeof(key_path) - 32) { if (strlen(resource_path) > sizeof(key_path) - 32) {
lwsl_err("resource path too long\n"); lwsl_err("resource path too long\n");
return -1; return -1;
} }
sprintf(key_path, "%s/libwebsockets-test-server.key.pem", sprintf(key_path, "%s/libwebsockets-test-server.key.pem",
resource_path); resource_path);
info.ssl_cert_filepath = cert_path; info.ssl_cert_filepath = cert_path;
info.ssl_private_key_filepath = key_path; info.ssl_private_key_filepath = key_path;
opts |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; opts |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
} }
info.gid = -1; info.gid = -1;
info.uid = -1; info.uid = -1;
info.max_http_header_pool = 1; info.max_http_header_pool = 1;
info.options = opts | LWS_SERVER_OPTION_LIBEVENT; info.options = opts | LWS_SERVER_OPTION_LIBEVENT;
context = lws_create_context(&info); context = lws_create_context(&info);
if (context == NULL) { if (context == NULL) {
lwsl_err("libwebsocket init failed\n"); lwsl_err("libwebsocket init failed\n");
return -1; return -1;
} }
/* /*
* this shows how to override the lws file operations. You don't need * this shows how to override the lws file operations. You don't need
* to do any of this unless you have a reason (eg, want to serve * to do any of this unless you have a reason (eg, want to serve
* compressed files without decompressing the whole archive) * compressed files without decompressing the whole archive)
*/ */
/* stash original platform fops */ /* stash original platform fops */
fops_plat = *(lws_get_fops(context)); fops_plat = *(lws_get_fops(context));
/* override the active fops */ /* override the active fops */
lws_get_fops(context)->open = test_server_fops_open; lws_get_fops(context)->open = test_server_fops_open;
// Don't use the default Signal Event Watcher & Handler // Don't use the default Signal Event Watcher & Handler
lws_event_sigint_cfg(context, 0, NULL); lws_event_sigint_cfg(context, 0, NULL);
// Initialize the LWS with libevent loop // Initialize the LWS with libevent loop
lws_event_initloop(context, event_base_loop, 0); lws_event_initloop(context, event_base_loop, 0);
timeout_watcher = evtimer_new(event_base_loop, ev_timeout_cb, NULL); timeout_watcher = event_new(event_base_loop, -1, EV_PERSIST, ev_timeout_cb, NULL);
struct timeval tv = {0, 50000}; struct timeval tv = {0, 50000};
evtimer_add(timeout_watcher, &tv); evtimer_add(timeout_watcher, &tv);
event_base_dispatch(event_base_loop); event_base_dispatch(event_base_loop);
lws_context_destroy(context); lws_context_destroy(context);
lwsl_notice("libwebsockets-test-server exited cleanly\n"); lwsl_notice("libwebsockets-test-server exited cleanly\n");
#ifndef _WIN32 #ifndef _WIN32
closelog(); closelog();
#endif #endif
return 0; return 0;
} }

View file

@ -50,6 +50,7 @@ void test_server_unlock(int care)
#include "../plugins/protocol_dumb_increment.c" #include "../plugins/protocol_dumb_increment.c"
#include "../plugins/protocol_lws_mirror.c" #include "../plugins/protocol_lws_mirror.c"
#include "../plugins/protocol_lws_status.c" #include "../plugins/protocol_lws_status.c"
#include "../plugins/protocol_lws_meta.c"
/* /*
* This demo server shows how to use libwebsockets for one or more * This demo server shows how to use libwebsockets for one or more
@ -73,6 +74,7 @@ enum demo_protocols {
PROTOCOL_DUMB_INCREMENT, PROTOCOL_DUMB_INCREMENT,
PROTOCOL_LWS_MIRROR, PROTOCOL_LWS_MIRROR,
PROTOCOL_LWS_STATUS, PROTOCOL_LWS_STATUS,
PROTOCOL_LWS_META,
/* always last */ /* always last */
DEMO_PROTOCOL_COUNT DEMO_PROTOCOL_COUNT
@ -92,6 +94,7 @@ static struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT, LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT,
LWS_PLUGIN_PROTOCOL_MIRROR, LWS_PLUGIN_PROTOCOL_MIRROR,
LWS_PLUGIN_PROTOCOL_LWS_STATUS, LWS_PLUGIN_PROTOCOL_LWS_STATUS,
LWS_PLUGIN_PROTOCOL_LWS_META,
{ NULL, NULL, 0, 0 } /* terminator */ { NULL, NULL, 0, 0 } /* terminator */
}; };
@ -456,6 +459,9 @@ int main(int argc, char **argv)
lwsl_notice("uv loop close rc %s\n", lwsl_notice("uv loop close rc %s\n",
e ? uv_strerror(e) : "ok"); e ? uv_strerror(e) : "ok");
/* PHASE 4: finalize context destruction */
lws_context_destroy2(context);
} else } else
#endif #endif
{ {