Compare commits
54 commits
Author | SHA1 | Date | |
---|---|---|---|
7f6db4fe8d | |||
![]() |
debb7aa043 | ||
![]() |
ca045d4a8e | ||
![]() |
4ce725903d | ||
![]() |
a2943ca41d | ||
![]() |
04134742f9 | ||
![]() |
2e5110e731 | ||
![]() |
afc9c0ac26 | ||
![]() |
5b23b8c99f | ||
![]() |
b66e8e1898 | ||
![]() |
0bb3646256 | ||
![]() |
c60b2413a4 | ||
![]() |
58195fbc1e | ||
![]() |
c2abf59c68 | ||
![]() |
4b24369d64 | ||
![]() |
872e8d7e9d | ||
![]() |
5da9ce2f06 | ||
![]() |
b93c057472 | ||
![]() |
5a38d88fdd | ||
![]() |
a9f74f2dbe | ||
![]() |
219a367a4c | ||
![]() |
93a5b586a3 | ||
![]() |
040b408029 | ||
![]() |
16ef37ef5d | ||
![]() |
e6bd6296bd | ||
![]() |
4a9c23e9ec | ||
![]() |
c6233ce403 | ||
![]() |
7849c5a8ad | ||
![]() |
414f114b8f | ||
![]() |
855f7e8712 | ||
![]() |
9f31e94e09 | ||
![]() |
855453d1ae | ||
![]() |
d86641ed3a | ||
![]() |
41c15511eb | ||
![]() |
d766c99861 | ||
![]() |
ba45f7cf9f | ||
![]() |
19a320a578 | ||
![]() |
61e58885f4 | ||
![]() |
3562e441e3 | ||
![]() |
003bd7dcee | ||
![]() |
75bbb3b2c0 | ||
![]() |
8ccc64679f | ||
![]() |
6c09952065 | ||
![]() |
09f3947b4c | ||
![]() |
941e93ea33 | ||
![]() |
c9da1ffa2e | ||
![]() |
ad15082563 | ||
![]() |
2d313bdc02 | ||
![]() |
3526fde154 | ||
![]() |
bd1dd7efd4 | ||
![]() |
1690581cd2 | ||
![]() |
3c360d5192 | ||
![]() |
8a4881a142 | ||
![]() |
6f11c1361a |
43 changed files with 2214 additions and 447 deletions
|
@ -11,7 +11,6 @@ env:
|
|||
- LWS_METHOD=noext CMAKE_ARGS="-DLWS_WITHOUT_EXTENSIONS=ON"
|
||||
- LWS_METHOD=libev CMAKE_ARGS="-DLWS_WITH_LIBEV=ON"
|
||||
- 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=nodaemon CMAKE_ARGS="-DLWS_WITHOUT_DAEMONIZE=ON"
|
||||
- LWS_METHOD=cgi CMAKE_ARGS="-DLWS_WITH_CGI=ON"
|
||||
|
|
|
@ -9,12 +9,12 @@ project(libwebsockets C)
|
|||
set(PACKAGE "libwebsockets")
|
||||
set(CPACK_PACKAGE_NAME "${PACKAGE}")
|
||||
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 "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
set(CPACK_PACKAGE_VENDOR "andy@warmcat.com")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${PACKAGE_VERSION}")
|
||||
set(SOVERSION "10")
|
||||
set(SOVERSION "11")
|
||||
if(NOT CPACK_GENERATOR)
|
||||
if(UNIX)
|
||||
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_IPV6 "Compile with support for ipv6" 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_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)
|
||||
|
@ -1443,6 +1443,8 @@ if (NOT LWS_WITHOUT_TESTAPPS)
|
|||
endmacro()
|
||||
|
||||
|
||||
create_plugin(protocol_lws_meta
|
||||
"plugins/protocol_lws_meta.c" "" "")
|
||||
create_plugin(protocol_dumb_increment
|
||||
"plugins/protocol_dumb_increment.c" "" "")
|
||||
create_plugin(protocol_lws_mirror
|
||||
|
|
192
README.lws-meta.md
Normal file
192
README.lws-meta.md
Normal file
|
@ -0,0 +1,192 @@
|
|||
# lws-meta protocol
|
||||
|
||||
lws-meta is a lightweight ws subprotocol that accepts other ws connections
|
||||
to the same server inside it and multiplexes their access to the connection.
|
||||
|
||||
```
|
||||
Client Server
|
||||
|
||||
conn1: \ / :conn1
|
||||
conn2: = mux ------ lws-meta ws protocol ----- mux = :conn2
|
||||
conn3: / \ :conn3
|
||||
```
|
||||
|
||||
You may have n client ws connections back to the server, but you now
|
||||
only have one tcp connection (and one SSL wrapper if using SSL) instead
|
||||
of n of those.
|
||||
|
||||
If you currently make multiple ws connections back to the server, so you
|
||||
can have different protocols active in one webpage, this if for you.
|
||||
|
||||
- The subprotocol code for the connections inside a lws-meta connection
|
||||
need zero changes from being a normal ws connection. It is unaware
|
||||
it is inside an lws-meta parent connection.
|
||||
|
||||
- The traffic on the lws-meta connection is indistinguishable from
|
||||
standard ws traffic, so intermediaries won't object to it
|
||||
|
||||
- The multiplexing is done in the protocol, **not by an extension**. So
|
||||
it's compatible with all browsers.
|
||||
|
||||
- Javascript helper code is provided to very simply use lws-meta
|
||||
protocol instead of direct connections. The lws test server has
|
||||
been converted to use this by default.
|
||||
|
||||
# Converting your server
|
||||
|
||||
1) include the provided lws-meta plugin (plugins/protocl_lws_meta.c) as an
|
||||
active protocol for your server. You can do that using runtime plugins, or
|
||||
include the plugin sources into your server at build-time. The lws test
|
||||
server uses the latter approach.
|
||||
|
||||
That's all you need to do on the server side.
|
||||
|
||||
# Converting your browser JS
|
||||
|
||||
1) import lws-common.js
|
||||
|
||||
2) Instantiate a parent lws-meta connection object
|
||||
|
||||
```
|
||||
var lws_meta = new lws_meta_ws();
|
||||
```
|
||||
|
||||
3) Connect the lws-meta object to your server
|
||||
|
||||
```
|
||||
lws_meta.new_parent(get_appropriate_ws_url("?mirror=" + mirror_name));
|
||||
```
|
||||
|
||||
4) Convert your actual ws connections to go via the lws_meta object
|
||||
|
||||
```
|
||||
var my_ws = lws_meta.new_ws("", "dumb-increment-protocol");
|
||||
```
|
||||
|
||||
The first arg is the URL path, the second arg is the ws protocol you want.
|
||||
|
||||
That's it. my_ws will get `onopen()`, `onmessage()` etc calls as before.
|
||||
|
||||
# lws-meta wire protocol
|
||||
|
||||
lws-meta works by adding some bytes at the start of a message indicating
|
||||
which channel the message applies to.
|
||||
|
||||
Channel messages are atomic on the wire. The reason is if we tried to
|
||||
intersperse other channel fragments between one channels message fragments,
|
||||
an intermediary would observe violations of the ws framing rule about
|
||||
having to start a message with TEXT or BINARY, and use only CONTINUATION
|
||||
for the subsequent fragments. Eg
|
||||
|
||||
```
|
||||
[ ch1 TEXT NOFIN ] [ ch2 BINARY FIN ] [ ch1 CONTINUATION FIN ]
|
||||
```
|
||||
|
||||
is illegal to an observer that doesn't understand lws-meta headers in the
|
||||
packet payloads. So to avoid this situation, only complete messages may
|
||||
be sent from one subchannel in each direction at a time.
|
||||
|
||||
Consequently, only the first fragment of each message is modified to
|
||||
have the extra two bytes identifying the subchannel it is aimed at, since
|
||||
the rest of the message from the same subchannel is defined to follow.
|
||||
|
||||
If it makes latencies, modify the protocol sending large messages to
|
||||
send smaller messages, so the transmission of messages from other channels
|
||||
can be sent inbetween the smaller messages.
|
||||
|
||||
## lws-meta commands
|
||||
|
||||
1) CSTRING indicates a string terminated by 0x00 byte
|
||||
|
||||
2) Channel IDs are sent with 0x20 added to them, to guarantee valid UTF-8
|
||||
|
||||
### 0x41: RX: LWS_META_CMD_OPEN_SUBCHANNEL
|
||||
|
||||
- CSTRING: protocol name
|
||||
- CSTRING: url
|
||||
- CSTRING: cookie (7 bytes max)
|
||||
|
||||
Client is requesting to open a new channel with the given protocol name,
|
||||
at the given url. The cookie (eg, channel name) is only used in
|
||||
LWS_META_CMD_OPEN_RESULT, when the channel id is assigned, so it is
|
||||
applied to the right channel.
|
||||
|
||||
### 0x42: TX: LWS_META_CMD_OPEN_RESULT
|
||||
|
||||
- CSTRING cookie
|
||||
- BYTE channel id (0 indicates failed)
|
||||
- CSTRING: selected protocol name
|
||||
|
||||
The server is informing the client of the results of a previous
|
||||
open request. The cookie the client sent to identify the request
|
||||
is returned along with a channel id to be used subsequently. If
|
||||
the channel ID is 0 (after subtracting the transport offset of
|
||||
0x20) then the open request has failed.
|
||||
|
||||
### 0x43: TX: LWS_META_CMD_CLOSE_NOTIFY
|
||||
|
||||
- BYTE channel id
|
||||
- BYTE: payload length + 0x20
|
||||
- BYTE: close code MSB
|
||||
- BYTE: close code LSB
|
||||
- PAYLOAD: payload (< 123 bytes)
|
||||
|
||||
Server notifies the client that a child has closed, for whatever reason.
|
||||
|
||||
### 0x44: RX: LWS_META_CMD_CLOSE_RQ
|
||||
- BYTE: channel id
|
||||
- BYTE: payload length + 0x20
|
||||
- BYTE: close code MSB
|
||||
- BYTE: close code LSB
|
||||
- PAYLOAD: payload (< 123 bytes)
|
||||
|
||||
The client requests to close a child connection
|
||||
|
||||
### 0x45: TX: LWS_META_CMD_WRITE
|
||||
|
||||
- BYTE: channel id
|
||||
|
||||
Normal write of payload n from lws-meta perspective is actually
|
||||
LWS_META_CMD_WRITE, channel id, then (n - 2) bytes of payload
|
||||
|
||||
The command only appears at the start of a message, continuations do
|
||||
not have the command.
|
||||
|
||||
## Protocol Notes
|
||||
|
||||
- Once the subchannel is up, overhead is only +2 bytes per message
|
||||
|
||||
- Close reasons are supported in both directions
|
||||
|
||||
- Ping and Pong are only supported at the lws-meta level, using normal ws ping and pong packets.
|
||||
|
||||
- Only the final close of the tcp lws-meta connection itself goes out as
|
||||
a normal ws close frame. Subchannels close is done in a normal TEXT
|
||||
message using LWS_META_CMD_CLOSE_RQ and then the close packet payload.
|
||||
This is so intermediaries do not mistake subchannel closures for the
|
||||
tcp / ws link going down.
|
||||
|
||||
Messages that start with LWS_META_CMD_OPEN_SUBCHANNEL only contain those
|
||||
commands but may contain any number of them for the whole duration of the
|
||||
message. The lws-meta js support collects child open requests made before
|
||||
the parent lws-meta connection is open, and dumps them all in a single
|
||||
message when it does open.
|
||||
|
||||
Messages that start with LWS_META_CMD_OPEN_RESULT or LWS_META_CMD_CLOSE_NOTIFY
|
||||
only contain those two commands, but they may contain any number of them
|
||||
for the whole duration of the message.
|
||||
|
||||
|
||||
# Current Implemention Limitations
|
||||
|
||||
- only server side is supported in lws. The client side JS for
|
||||
a browser is supported.
|
||||
|
||||
- max number of child connections per parent at the moment is 8
|
||||
|
||||
- child connection URL paramter when opening the connection is
|
||||
ignored
|
||||
|
||||
- there is no ah attached when the child connections are
|
||||
established inside the lws-meta parent. So header access
|
||||
functions will fail.
|
|
@ -576,3 +576,26 @@ Prepare the log directory like this
|
|||
sudo mkdir /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.
|
||||
|
||||
|
||||
|
|
|
@ -8,14 +8,13 @@ libwebsockets
|
|||
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
|
||||
|
||||
- factory https://github.com/warmcat/lws-esp32-factory and
|
||||
- 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
|
||||
servers. For support, visit
|
||||
|
|
|
@ -22,8 +22,8 @@ install:
|
|||
- mkdir c:\assets\libuv
|
||||
- 7z x -oc:\assets\libuv win-libuv.zip
|
||||
# - appveyor DownloadFile https://slproweb.com/download/Win32OpenSSL-1_0_2h.exe
|
||||
- appveyor DownloadFile https://libwebsockets.org:444/Win32OpenSSL-1_0_2h.exe
|
||||
- Win32OpenSSL-1_0_2h.exe /silent /verysilent /sp- /suppressmsgboxes
|
||||
# - appveyor DownloadFile https://libwebsockets.org:444/Win32OpenSSL-1_0_2L.exe
|
||||
# - Win32OpenSSL-1_0_2L.exe /silent /verysilent /sp- /suppressmsgboxes
|
||||
- appveyor DownloadFile https://libwebsockets.org:444/nsis-3.0rc1-setup.exe
|
||||
- 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
|
||||
|
@ -51,8 +51,8 @@ artifacts:
|
|||
name: lws.zip
|
||||
type: Zip
|
||||
|
||||
cache:
|
||||
- C:\OpenSSL-Win32
|
||||
#cache:
|
||||
# - C:\OpenSSL-Win32
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
|
|
@ -6,7 +6,7 @@ N=1
|
|||
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
|
||||
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
|
||||
while [ $C -gt 8 ] ; do
|
||||
|
|
37
changelog
37
changelog
|
@ -1,6 +1,43 @@
|
|||
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
|
||||
======
|
||||
|
||||
|
|
|
@ -111,6 +111,14 @@ lws_client_connect_2(struct lws *wsi)
|
|||
#ifdef LWS_USE_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));
|
||||
|
||||
sa46.sa6.sin6_family = AF_INET6;
|
||||
|
@ -213,15 +221,11 @@ lws_client_connect_2(struct lws *wsi)
|
|||
#endif
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (wsi->ipv6) {
|
||||
sa46.sa6.sin6_port = htons(port);
|
||||
if (wsi->ipv6)
|
||||
wsi->desc.sockfd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
} else
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sa46.sa4.sin_port = htons(port);
|
||||
wsi->desc.sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
}
|
||||
|
||||
if (!lws_socket_is_valid(wsi->desc.sockfd)) {
|
||||
lwsl_warn("Unable to open socket\n");
|
||||
|
@ -276,11 +280,15 @@ lws_client_connect_2(struct lws *wsi)
|
|||
}
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (wsi->ipv6)
|
||||
if (wsi->ipv6) {
|
||||
sa46.sa6.sin6_port = htons(port);
|
||||
n = sizeof(struct sockaddr_in6);
|
||||
else
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
sa46.sa4.sin_port = htons(port);
|
||||
n = sizeof(struct sockaddr);
|
||||
}
|
||||
|
||||
if (connect(wsi->desc.sockfd, (const struct sockaddr *)&sa46, n) == -1 ||
|
||||
LWS_ERRNO == LWS_EISCONN) {
|
||||
|
@ -454,15 +462,6 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
|
|||
}
|
||||
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);
|
||||
if (p)
|
||||
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)
|
||||
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);
|
||||
|
||||
/* close the connection by hand */
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
lws_ssl_close(wsi);
|
||||
#endif
|
||||
|
||||
#ifdef LWS_USE_LIBUV
|
||||
if (LWS_LIBUV_ENABLED(wsi->context)) {
|
||||
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);
|
||||
|
||||
#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->state = LWSS_CLIENT_UNCONNECTED;
|
||||
wsi->protocol = NULL;
|
||||
|
|
|
@ -573,7 +573,7 @@ lws_http_transaction_completed_client(struct lws *wsi)
|
|||
|
||||
/* we don't support chained client connections yet */
|
||||
return 1;
|
||||
|
||||
#if 0
|
||||
/* otherwise set ourselves up ready to go again */
|
||||
wsi->state = LWSS_CLIENT_HTTP_ESTABLISHED;
|
||||
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);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN unsigned int
|
||||
|
@ -630,6 +631,8 @@ lws_client_interpret_server_handshake(struct lws *wsi)
|
|||
int more = 1;
|
||||
void *v;
|
||||
#endif
|
||||
if (wsi->u.hdr.stash)
|
||||
lws_free_set_NULL(wsi->u.hdr.stash);
|
||||
|
||||
ah = wsi->u.hdr.ah;
|
||||
if (!wsi->do_ws) {
|
||||
|
|
|
@ -237,22 +237,36 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
#endif
|
||||
return -1;
|
||||
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:
|
||||
#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)
|
||||
return -1;
|
||||
|
||||
if (wsi->reason_bf & 8)
|
||||
wsi->reason_bf &= ~8;
|
||||
if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_HEADERS)
|
||||
wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__CGI_HEADERS;
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
#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;
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
wsi->reason_bf &= ~2;
|
||||
wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__PROXY;
|
||||
if (!lws_get_child(wsi))
|
||||
break;
|
||||
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));
|
||||
if (!lws_get_parent(wsi))
|
||||
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));
|
||||
break;
|
||||
|
||||
|
@ -351,7 +364,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
/* TBD stdin rx flow control */
|
||||
break;
|
||||
case LWS_STDOUT:
|
||||
wsi->reason_bf |= 1;
|
||||
wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI;
|
||||
/* when writing to MASTER would not block */
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
|
@ -369,6 +382,11 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
break;
|
||||
|
||||
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;
|
||||
|
||||
case LWS_CALLBACK_CGI_STDIN_DATA: /* POST body for stdin */
|
||||
|
@ -470,6 +488,11 @@ lws_create_vhost(struct lws_context *context,
|
|||
else
|
||||
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
|
||||
* ones that came from plugins
|
||||
|
@ -524,7 +547,7 @@ lws_create_vhost(struct lws_context *context,
|
|||
vh->protocols = lwsp;
|
||||
else {
|
||||
vh->protocols = info->protocols;
|
||||
free(lwsp);
|
||||
lws_free(lwsp);
|
||||
}
|
||||
|
||||
vh->same_vh_protocol_list = (struct lws **)
|
||||
|
|
|
@ -94,13 +94,16 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
|
|||
|
||||
case LWS_EXT_CB_OPTION_SET:
|
||||
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);
|
||||
if (oa->start)
|
||||
priv->args[oa->option_index] = atoi(oa->start);
|
||||
else
|
||||
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);
|
||||
break;
|
||||
|
||||
|
@ -325,16 +328,18 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
|
|||
|
||||
case LWS_EXT_CB_PAYLOAD_TX:
|
||||
|
||||
if (!priv->tx_init)
|
||||
if (deflateInit2(&priv->tx, priv->args[PMD_COMP_LEVEL],
|
||||
if (!priv->tx_init) {
|
||||
n = deflateInit2(&priv->tx, priv->args[PMD_COMP_LEVEL],
|
||||
Z_DEFLATED,
|
||||
-priv->args[PMD_CLIENT_MAX_WINDOW_BITS +
|
||||
!wsi->vhost->listen_port],
|
||||
-priv->args[PMD_SERVER_MAX_WINDOW_BITS +
|
||||
(wsi->vhost->listen_port <= 0)],
|
||||
priv->args[PMD_MEM_LEVEL],
|
||||
Z_DEFAULT_STRATEGY) != Z_OK) {
|
||||
lwsl_ext("inflateInit2 failed\n");
|
||||
Z_DEFAULT_STRATEGY);
|
||||
if (n != Z_OK) {
|
||||
lwsl_ext("inflateInit2 failed %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
priv->tx_init = 1;
|
||||
if (!priv->buf_tx_deflated)
|
||||
priv->buf_tx_deflated = lws_malloc(LWS_PRE + 7 + 5 +
|
||||
|
@ -436,7 +441,9 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
|
|||
break;
|
||||
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);
|
||||
priv->tx_init = 0;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi,
|
|||
oa.option_index = n;
|
||||
lwsl_ext("hit %d\n", oa.option_index);
|
||||
leap = LEAPS_SEEK_VAL;
|
||||
if (len ==1)
|
||||
if (len == 1)
|
||||
goto set_arg;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -238,7 +238,7 @@ lws_return_http_status(struct lws *wsi, unsigned int code,
|
|||
&p, end))
|
||||
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);
|
||||
|
||||
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,
|
||||
|
|
|
@ -776,7 +776,8 @@ lwsws_get_config_d(void *user, const char *d, const char * const *paths,
|
|||
|
||||
bail:
|
||||
uv_fs_req_cleanup(&req);
|
||||
uv_loop_close(&loop);
|
||||
while (uv_loop_close(&loop))
|
||||
;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -39,12 +39,15 @@ lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx)
|
|||
if (revents & EV_TIMEOUT)
|
||||
return;
|
||||
|
||||
/* !!! EV_CLOSED doesn't exist in libevent2 */
|
||||
#if LIBEVENT_VERSION_NUMBER < 0x02000000
|
||||
if (revents & EV_CLOSED)
|
||||
{
|
||||
event_del(lws_io->event_watcher);
|
||||
event_free(lws_io->event_watcher);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
eventfd.fd = sock_fd;
|
||||
eventfd.events = 0;
|
||||
|
|
|
@ -65,9 +65,14 @@ static const char * const log_level_names[] = {
|
|||
void
|
||||
lws_free_wsi(struct lws *wsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt;
|
||||
int n;
|
||||
|
||||
if (!wsi)
|
||||
return;
|
||||
|
||||
pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
|
||||
/* Protocol user data may be allocated either internally by lws
|
||||
* or by specified the user.
|
||||
* 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... */
|
||||
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_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--;
|
||||
lwsl_debug("%s: %p, remaining wsi %d\n", __func__, wsi,
|
||||
wsi->context->count_wsi_allocated);
|
||||
|
@ -116,6 +140,13 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
|
|||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
time_t now;
|
||||
|
||||
if (secs == LWS_TO_KILL_SYNC) {
|
||||
lws_remove_from_timeout_list(wsi);
|
||||
lwsl_debug("synchronously killing %p\n", wsi);
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return;
|
||||
}
|
||||
|
||||
lws_pt_lock(pt);
|
||||
|
||||
time(&now);
|
||||
|
@ -157,6 +188,12 @@ lws_remove_child_from_any_parent(struct lws *wsi)
|
|||
if (*pwsi == wsi) {
|
||||
lwsl_info("%s: detach %p from parent %p\n",
|
||||
__func__, wsi, wsi->parent);
|
||||
|
||||
if (wsi->parent->protocol)
|
||||
wsi->parent->protocol->callback(wsi,
|
||||
LWS_CALLBACK_CHILD_CLOSING,
|
||||
wsi->parent->user_space, wsi, 0);
|
||||
|
||||
*pwsi = wsi->sibling_list;
|
||||
seen = 1;
|
||||
break;
|
||||
|
@ -219,6 +256,33 @@ lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p)
|
|||
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
|
||||
lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
|
||||
{
|
||||
|
@ -228,6 +292,8 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
|
|||
struct lws_tokens eff_buf;
|
||||
int n, m, ret;
|
||||
|
||||
lwsl_debug("%s: %p\n", __func__, wsi);
|
||||
|
||||
if (!wsi)
|
||||
return;
|
||||
|
||||
|
@ -280,35 +346,38 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
|
|||
#ifdef LWS_WITH_CGI
|
||||
if (wsi->mode == LWSCM_CGI) {
|
||||
/* 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 */
|
||||
wsi->parent->cgi->stdwsi[(int)wsi->cgi_channel] = NULL;
|
||||
}
|
||||
wsi->socket_is_permanently_unusable = 1;
|
||||
|
||||
lwsl_debug("------ %s: detected cgi fdhandler wsi %p\n", __func__, wsi);
|
||||
goto just_kill_connection;
|
||||
}
|
||||
|
||||
if (wsi->cgi) {
|
||||
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);
|
||||
}
|
||||
if (wsi->cgi)
|
||||
lws_cgi_remove_and_kill(wsi);
|
||||
#endif
|
||||
|
||||
#if !defined(LWS_NO_CLIENT)
|
||||
if (wsi->mode == LWSCM_HTTP_CLIENT ||
|
||||
wsi->mode == LWSCM_WSCL_WAITING_CONNECT ||
|
||||
wsi->mode == LWSCM_WSCL_WAITING_PROXY_REPLY ||
|
||||
wsi->mode == LWSCM_WSCL_ISSUE_HANDSHAKE ||
|
||||
wsi->mode == LWSCM_WSCL_ISSUE_HANDSHAKE2 ||
|
||||
wsi->mode == LWSCM_WSCL_WAITING_SSL ||
|
||||
wsi->mode == LWSCM_WSCL_WAITING_SERVER_REPLY ||
|
||||
wsi->mode == LWSCM_WSCL_WAITING_EXTENSION_CONNECT ||
|
||||
wsi->mode == LWSCM_WSCL_WAITING_SOCKS_GREETING_REPLY ||
|
||||
wsi->mode == LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY ||
|
||||
wsi->mode == LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY)
|
||||
if (wsi->u.hdr.stash)
|
||||
lws_free_set_NULL(wsi->u.hdr.stash);
|
||||
#endif
|
||||
|
||||
if (wsi->mode == LWSCM_RAW) {
|
||||
|
@ -568,6 +637,8 @@ just_kill_connection:
|
|||
/* checking return redundant since we anyway close */
|
||||
if (wsi->desc.sockfd != LWS_SOCK_INVALID)
|
||||
remove_wsi_socket_from_fds(wsi);
|
||||
else
|
||||
lws_same_vh_protocol_remove(wsi);
|
||||
|
||||
#if defined(LWS_WITH_ESP8266)
|
||||
espconn_disconnect(wsi->desc.sockfd);
|
||||
|
@ -670,17 +741,18 @@ async_close:
|
|||
wsi->socket_is_permanently_unusable = 1;
|
||||
|
||||
#ifdef LWS_USE_LIBUV
|
||||
if (LWS_LIBUV_ENABLED(context)) {
|
||||
if (wsi->listener) {
|
||||
lwsl_debug("%s: stopping listner libuv poll\n", __func__);
|
||||
uv_poll_stop(&wsi->w_read.uv_watcher);
|
||||
}
|
||||
lwsl_debug("%s: lws_libuv_closehandle: wsi %p\n", __func__, wsi);
|
||||
/* libuv has to do his own close handle processing asynchronously */
|
||||
lws_libuv_closehandle(wsi);
|
||||
if (!wsi->parent_carries_io)
|
||||
if (LWS_LIBUV_ENABLED(context)) {
|
||||
if (wsi->listener) {
|
||||
lwsl_debug("%s: stopping listner libuv poll\n", __func__);
|
||||
uv_poll_stop(&wsi->w_read.uv_watcher);
|
||||
}
|
||||
lwsl_debug("%s: lws_libuv_closehandle: wsi %p\n", __func__, wsi);
|
||||
/* libuv has to do his own close handle processing asynchronously */
|
||||
lws_libuv_closehandle(wsi);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
lws_close_free_wsi_final(wsi);
|
||||
|
@ -711,12 +783,13 @@ lws_close_free_wsi_final(struct lws *wsi)
|
|||
|
||||
#ifdef LWS_WITH_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");
|
||||
|
||||
if (wsi->cgi->pipe_fds[n / 2][n & 1] >= 0)
|
||||
close(wsi->cgi->pipe_fds[n / 2][n & 1]);
|
||||
if (wsi->cgi->pipe_fds[n][!!(n == 0)] >= 0)
|
||||
close(wsi->cgi->pipe_fds[n][!!(n == 0)]);
|
||||
}
|
||||
|
||||
lws_free(wsi->cgi);
|
||||
|
@ -767,8 +840,7 @@ lws_get_addresses(struct lws_vhost *vh, void *ads, char *name,
|
|||
struct addrinfo ai, *res;
|
||||
struct sockaddr_in addr4;
|
||||
|
||||
if (rip)
|
||||
rip[0] = '\0';
|
||||
rip[0] = '\0';
|
||||
name[0] = '\0';
|
||||
addr4.sin_family = AF_UNSPEC;
|
||||
|
||||
|
@ -803,8 +875,6 @@ lws_get_addresses(struct lws_vhost *vh, void *ads, char *name,
|
|||
name, name_len, NULL, 0, 0))
|
||||
return -1;
|
||||
#endif
|
||||
if (!rip)
|
||||
return 0;
|
||||
|
||||
if (getaddrinfo(name, NULL, &ai, &result))
|
||||
return -1;
|
||||
|
@ -856,6 +926,9 @@ lws_get_peer_simple(struct lws *wsi, char *name, int namelen)
|
|||
int af = AF_INET;
|
||||
void *p, *q;
|
||||
|
||||
if (wsi->parent_carries_io)
|
||||
wsi = wsi->parent;
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(wsi->vhost)) {
|
||||
len = sizeof(sin6);
|
||||
|
@ -998,8 +1071,9 @@ lws_callback_all_protocol(struct lws_context *context,
|
|||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_callback_all_protocol_vhost(struct lws_vhost *vh,
|
||||
const struct lws_protocols *protocol, int reason)
|
||||
lws_callback_all_protocol_vhost_args(struct lws_vhost *vh,
|
||||
const struct lws_protocols *protocol, int reason,
|
||||
void *argp, size_t len)
|
||||
{
|
||||
struct lws_context *context = vh->context;
|
||||
struct lws_context_per_thread *pt = &context->pt[0];
|
||||
|
@ -1011,9 +1085,10 @@ lws_callback_all_protocol_vhost(struct lws_vhost *vh,
|
|||
wsi = wsi_from_fd(context, pt->fds[n].fd);
|
||||
if (!wsi)
|
||||
continue;
|
||||
if (wsi->vhost == vh && wsi->protocol == protocol)
|
||||
protocol->callback(wsi, reason, wsi->user_space,
|
||||
NULL, 0);
|
||||
if (wsi->vhost == vh && (wsi->protocol == protocol ||
|
||||
!protocol))
|
||||
wsi->protocol->callback(wsi, reason,
|
||||
wsi->user_space, argp, len);
|
||||
}
|
||||
pt++;
|
||||
}
|
||||
|
@ -1021,6 +1096,13 @@ lws_callback_all_protocol_vhost(struct lws_vhost *vh,
|
|||
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_callback_vhost_protocols(struct lws *wsi, int reason, void *in, int len)
|
||||
{
|
||||
|
@ -1407,6 +1489,12 @@ lws_is_final_fragment(struct lws *wsi)
|
|||
return wsi->u.ws.final && !wsi->u.ws.rx_packet_length && !wsi->u.ws.rx_draining_ext;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_is_first_fragment(struct lws *wsi)
|
||||
{
|
||||
return wsi->u.ws.first_fragment;
|
||||
}
|
||||
|
||||
LWS_VISIBLE unsigned char
|
||||
lws_get_reserved_bits(struct lws *wsi)
|
||||
{
|
||||
|
@ -1650,6 +1738,48 @@ lws_get_child(const struct lws *wsi)
|
|||
return wsi->child_list;
|
||||
}
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_set_parent_carries_io(struct lws *wsi)
|
||||
{
|
||||
wsi->parent_carries_io = 1;
|
||||
}
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void *
|
||||
lws_get_opaque_parent_data(const struct lws *wsi)
|
||||
{
|
||||
return wsi->opaque_parent_data;
|
||||
}
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_set_opaque_parent_data(struct lws *wsi, void *data)
|
||||
{
|
||||
wsi->opaque_parent_data = data;
|
||||
}
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_get_child_pending_on_writable(const struct lws *wsi)
|
||||
{
|
||||
return wsi->parent_pending_cb_on_writable;
|
||||
}
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_clear_child_pending_on_writable(struct lws *wsi)
|
||||
{
|
||||
wsi->parent_pending_cb_on_writable = 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_get_close_length(struct lws *wsi)
|
||||
{
|
||||
return wsi->u.ws.close_in_ping_buffer_len;
|
||||
}
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN unsigned char *
|
||||
lws_get_close_payload(struct lws *wsi)
|
||||
{
|
||||
return &wsi->u.ws.ping_payload_buf[LWS_PRE];
|
||||
}
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_close_reason(struct lws *wsi, enum lws_close_status status,
|
||||
unsigned char *buf, size_t len)
|
||||
|
@ -2516,6 +2646,8 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
p++;
|
||||
}
|
||||
}
|
||||
env_array[n++] = "PATH=/bin:/usr/bin:/usr/local/bin:/var/www/cgi-bin";
|
||||
|
||||
env_array[n++] = p;
|
||||
p += lws_snprintf(p, end - p, "SCRIPT_PATH=%s", exec_array[0]) + 1;
|
||||
|
||||
|
@ -2530,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++] = "PATH=/bin:/usr/bin:/usr/local/bin:/var/www/cgi-bin";
|
||||
env_array[n] = NULL;
|
||||
|
||||
#if 0
|
||||
|
@ -2565,6 +2696,10 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
/* we are the parent process */
|
||||
wsi->context->count_cgi_spawned++;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2647,11 +2782,11 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
|
|||
return -1;
|
||||
|
||||
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
|
||||
* handled separately
|
||||
*/
|
||||
|
||||
switch (wsi->hdr_state) {
|
||||
|
||||
case LHCS_RESPONSE:
|
||||
|
@ -2659,6 +2794,12 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
|
|||
wsi->cgi->response_code);
|
||||
if (lws_add_http_header_status(wsi, wsi->cgi->response_code, &p, end))
|
||||
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,
|
||||
(unsigned char *)"close", 5, &p, end))
|
||||
return 1;
|
||||
|
@ -2675,7 +2816,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
|
|||
}
|
||||
|
||||
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);
|
||||
/* back to the loop for writeability again */
|
||||
return 0;
|
||||
|
@ -2700,7 +2841,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
|
|||
lws_free_set_NULL(wsi->cgi->headers_buf);
|
||||
lwsl_debug("freed cgi headers\n");
|
||||
} else {
|
||||
wsi->reason_bf |= 8;
|
||||
wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_HEADERS;
|
||||
lws_callback_on_writable(wsi);
|
||||
}
|
||||
|
||||
|
@ -2856,14 +2997,24 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi)
|
|||
|
||||
/* payload processing */
|
||||
|
||||
m = !wsi->cgi->explicitly_chunked && !wsi->cgi->content_length;
|
||||
|
||||
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) {
|
||||
lwsl_debug("%s: stdout read says %d\n", __func__, n);
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
//lwsl_notice("write %d\n", m);
|
||||
if (m < 0) {
|
||||
|
@ -2994,7 +3145,7 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt)
|
|||
lwsl_debug("%s: found PID %d on cgi list\n",
|
||||
__func__, n);
|
||||
|
||||
if (!cgi->content_length && cgi->explicitly_chunked) {
|
||||
if (!cgi->content_length) {
|
||||
/*
|
||||
* well, if he sends chunked... give him 5s after the
|
||||
* cgi terminated to send buffered
|
||||
|
@ -3097,7 +3248,8 @@ lws_set_extension_option(struct lws *wsi, const char *ext_name,
|
|||
int
|
||||
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;
|
||||
|
||||
if (!wsi->access_log_pending)
|
||||
|
@ -3109,9 +3261,12 @@ lws_access_log(struct lws *wsi)
|
|||
if (!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.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 (write(wsi->vhost->log_fd, ass, l) != l)
|
||||
|
@ -3127,6 +3282,10 @@ lws_access_log(struct lws *wsi)
|
|||
lws_free(wsi->access_log.user_agent);
|
||||
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;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -33,12 +33,11 @@ extern "C" {
|
|||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#if defined(LWS_HAS_INTPTR_T)
|
||||
#include <stdint.h>
|
||||
#define lws_intptr_t intptr_t
|
||||
#else
|
||||
typedef unsigned long long lws_intptr_t;
|
||||
#endif
|
||||
#include "lws_config.h"
|
||||
|
||||
/*
|
||||
* CARE: everything using cmake defines needs to be below here
|
||||
*/
|
||||
|
||||
#if defined(LWS_WITH_ESP8266)
|
||||
struct sockaddr_in;
|
||||
|
@ -47,7 +46,12 @@ struct sockaddr_in;
|
|||
#define LWS_POSIX 1
|
||||
#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)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
|
@ -632,6 +636,7 @@ struct lws_esp32_image {
|
|||
};
|
||||
|
||||
extern struct lws_esp32 lws_esp32;
|
||||
struct lws_vhost;
|
||||
|
||||
extern esp_err_t
|
||||
lws_esp32_event_passthru(void *ctx, system_event_t *event);
|
||||
|
@ -645,7 +650,7 @@ struct lws_context_creation_info;
|
|||
extern void
|
||||
lws_esp32_set_creation_defaults(struct lws_context_creation_info *info);
|
||||
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
|
||||
lws_esp32_wlan_nvs_get(int retry);
|
||||
extern esp_err_t
|
||||
|
@ -823,6 +828,38 @@ struct lws_context;
|
|||
/* needed even with extensions disabled for create context */
|
||||
struct lws_extension;
|
||||
|
||||
/*! \defgroup lwsmeta lws-meta
|
||||
*
|
||||
* ##lws-meta protocol
|
||||
*
|
||||
* The protocol wraps other muxed connections inside one tcp connection.
|
||||
*
|
||||
* Commands are assigned from 0x41 up (so they are valid unicode)
|
||||
*/
|
||||
///@{
|
||||
|
||||
enum lws_meta_commands {
|
||||
LWS_META_CMD_OPEN_SUBCHANNEL = 'A',
|
||||
/**< Client requests to open new subchannel
|
||||
*/
|
||||
LWS_META_CMD_OPEN_RESULT,
|
||||
/**< Result of client request to open new subchannel */
|
||||
LWS_META_CMD_CLOSE_NOTIFY,
|
||||
/**< Notification of subchannel closure */
|
||||
LWS_META_CMD_CLOSE_RQ,
|
||||
/**< client requests to close a subchannel */
|
||||
LWS_META_CMD_WRITE,
|
||||
/**< connection writes something to specific channel index */
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
};
|
||||
|
||||
/* channel numbers are transported offset by 0x20 so they are valid unicode */
|
||||
|
||||
#define LWS_META_TRANSPORT_OFFSET 0x20
|
||||
|
||||
///@}
|
||||
|
||||
/*! \defgroup usercb User Callback
|
||||
*
|
||||
* ##User protocol callback
|
||||
|
@ -1252,6 +1289,16 @@ enum lws_callback_reasons {
|
|||
* using the vhost. @in is a pointer to a
|
||||
* struct lws_ssl_info containing information about the
|
||||
* event*/
|
||||
LWS_CALLBACK_CHILD_WRITE_VIA_PARENT = 68,
|
||||
/**< Child has been marked with parent_carries_io attribute, so
|
||||
* lws_write directs the to this callback at the parent,
|
||||
* @in is a struct lws_write_passthru containing the args
|
||||
* the lws_write() was called with.
|
||||
*/
|
||||
LWS_CALLBACK_CHILD_CLOSING = 69,
|
||||
/**< Sent to parent to notify them a child is closing / being
|
||||
* destroyed. @in is the child wsi.
|
||||
*/
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
|
||||
|
@ -1279,6 +1326,11 @@ enum lws_callback_reasons {
|
|||
typedef int
|
||||
lws_callback_function(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
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
|
||||
|
@ -2069,6 +2121,9 @@ struct lws_context_creation_info {
|
|||
* the form SSL_CB_ALERT, defined in openssl/ssl.h. The default of
|
||||
* 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 */
|
||||
};
|
||||
|
@ -2783,6 +2838,9 @@ lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi)
|
|||
/* Backwards compatibility */
|
||||
#define lws_plat_service_tsi lws_service_tsi
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd);
|
||||
|
||||
///@}
|
||||
|
||||
/*! \defgroup http HTTP
|
||||
|
@ -3621,10 +3679,24 @@ enum pending_timeout {
|
|||
PENDING_TIMEOUT_KILLED_BY_SSL_INFO = 22,
|
||||
PENDING_TIMEOUT_KILLED_BY_PARENT = 23,
|
||||
PENDING_TIMEOUT_CLOSE_SEND = 24,
|
||||
PENDING_TIMEOUT_HOLDING_AH = 25,
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
};
|
||||
|
||||
#define LWS_TO_KILL_ASYNC -1
|
||||
/**< If LWS_TO_KILL_ASYNC is given as the timeout sec in a lws_set_timeout()
|
||||
* call, then the connection is marked to be killed at the next timeout
|
||||
* check. This is how you should force-close the wsi being serviced if
|
||||
* you are doing it outside the callback (where you should close by nonzero
|
||||
* return).
|
||||
*/
|
||||
#define LWS_TO_KILL_SYNC -2
|
||||
/**< If LWS_TO_KILL_SYNC is given as the timeout sec in a lws_set_timeout()
|
||||
* call, then the connection is closed before returning (which may delete
|
||||
* the wsi). This should only be used where the wsi being closed is not the
|
||||
* wsi currently being serviced.
|
||||
*/
|
||||
/**
|
||||
* lws_set_timeout() - marks the wsi as subject to a timeout
|
||||
*
|
||||
|
@ -3632,7 +3704,10 @@ enum pending_timeout {
|
|||
*
|
||||
* \param wsi: Websocket connection instance
|
||||
* \param reason: timeout reason
|
||||
* \param secs: how many seconds
|
||||
* \param secs: how many seconds. You may set to LWS_TO_KILL_ASYNC to
|
||||
* force the connection to timeout at the next opportunity, or
|
||||
* LWS_TO_KILL_SYNC to close it synchronously if you know the
|
||||
* wsi is not the one currently being serviced.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs);
|
||||
|
@ -3657,7 +3732,8 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs);
|
|||
#endif
|
||||
#define _LWS_PAD(n) (((n) % _LWS_PAD_SIZE) ? \
|
||||
((n) + (_LWS_PAD_SIZE - ((n) % _LWS_PAD_SIZE))) : (n))
|
||||
#define LWS_PRE _LWS_PAD(4 + 10)
|
||||
/* last 2 is for lws-meta */
|
||||
#define LWS_PRE _LWS_PAD(4 + 10 + 2)
|
||||
/* used prior to 1.7 and retained for backward compatibility */
|
||||
#define LWS_SEND_BUFFER_PRE_PADDING LWS_PRE
|
||||
#define LWS_SEND_BUFFER_POST_PADDING 0
|
||||
|
@ -3709,6 +3785,15 @@ enum lws_write_protocol {
|
|||
* decode the content if used */
|
||||
};
|
||||
|
||||
/* used with LWS_CALLBACK_CHILD_WRITE_VIA_PARENT */
|
||||
|
||||
struct lws_write_passthru {
|
||||
struct lws *wsi;
|
||||
unsigned char *buf;
|
||||
size_t len;
|
||||
enum lws_write_protocol wp;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* lws_write() - Apply protocol then write data to client
|
||||
|
@ -3841,7 +3926,7 @@ lws_callback_on_writable(struct lws *wsi);
|
|||
|
||||
/**
|
||||
* lws_callback_on_writable_all_protocol() - Request a callback for all
|
||||
* connections on same vhost using the given protocol when it
|
||||
* connections using the given protocol when it
|
||||
* becomes possible to write to each socket without
|
||||
* blocking in turn.
|
||||
*
|
||||
|
@ -3858,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
|
||||
* all connections using the given protocol when it
|
||||
* becomes possible to write to each socket without
|
||||
* all connections on same vhost using the given protocol
|
||||
* when it becomes possible to write to each socket without
|
||||
* blocking in turn.
|
||||
*
|
||||
* \param vhost: Only consider connections on this lws_vhost
|
||||
|
@ -3895,10 +3980,11 @@ lws_callback_all_protocol(struct lws_context *context,
|
|||
|
||||
/**
|
||||
* 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 protocol: Which protocol to match
|
||||
* \param protocol: Which protocol to match. NULL means all.
|
||||
* \param reason: Callback reason index
|
||||
*
|
||||
* - Which: connections using this protocol on GIVEN VHOST ONLY
|
||||
|
@ -3907,7 +3993,27 @@ lws_callback_all_protocol(struct lws_context *context,
|
|||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
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
|
||||
|
@ -4053,7 +4159,11 @@ typedef enum {
|
|||
LWS_ADOPT_RAW_FILE_DESC = 0, /* convenience constant */
|
||||
LWS_ADOPT_HTTP = 1, /* flag: absent implies RAW */
|
||||
LWS_ADOPT_SOCKET = 2, /* flag: absent implies file descr */
|
||||
LWS_ADOPT_ALLOW_SSL = 4 /* flag: if set requires LWS_ADOPT_SOCKET */
|
||||
LWS_ADOPT_ALLOW_SSL = 4, /* flag: if set requires LWS_ADOPT_SOCKET */
|
||||
LWS_ADOPT_WS_PARENTIO = 8, /* flag: ws mode parent handles IO
|
||||
* if given must be only flag
|
||||
* wsi put directly into ws mode
|
||||
*/
|
||||
} lws_adoption_type;
|
||||
|
||||
typedef union {
|
||||
|
@ -4411,6 +4521,32 @@ lws_get_parent(const struct lws *wsi);
|
|||
LWS_VISIBLE LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
|
||||
lws_get_child(const struct lws *wsi);
|
||||
|
||||
/**
|
||||
* lws_parent_carries_io() - mark wsi as needing to send messages via parent
|
||||
*
|
||||
* \param wsi: child lws connection
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_set_parent_carries_io(struct lws *wsi);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void *
|
||||
lws_get_opaque_parent_data(const struct lws *wsi);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_set_opaque_parent_data(struct lws *wsi, void *data);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_get_child_pending_on_writable(const struct lws *wsi);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_clear_child_pending_on_writable(struct lws *wsi);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_get_close_length(struct lws *wsi);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN unsigned char *
|
||||
lws_get_close_payload(struct lws *wsi);
|
||||
|
||||
/*
|
||||
* \deprecated DEPRECATED Note: this is not normally needed as a user api.
|
||||
|
@ -4448,11 +4584,20 @@ lws_send_pipe_choked(struct lws *wsi);
|
|||
|
||||
/**
|
||||
* lws_is_final_fragment() - tests if last part of ws message
|
||||
*
|
||||
* \param wsi: lws connection
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_is_final_fragment(struct lws *wsi);
|
||||
|
||||
/**
|
||||
* lws_is_first_fragment() - tests if first part of ws message
|
||||
*
|
||||
* \param wsi: lws connection
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_is_first_fragment(struct lws *wsi);
|
||||
|
||||
/**
|
||||
* lws_get_reserved_bits() - access reserved bits of ws frame
|
||||
* \param wsi: lws connection
|
||||
|
|
|
@ -1613,7 +1613,12 @@ lws_esp32_get_image_info(const esp_partition_t *part, struct lws_esp32_image *i,
|
|||
}
|
||||
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));
|
||||
i->json = i->romfs + i->romfs_len + 4;
|
||||
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 *
|
||||
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();
|
||||
struct lws_context *context;
|
||||
|
@ -1683,6 +1688,9 @@ lws_esp32_init(struct lws_context_creation_info *info)
|
|||
else
|
||||
lws_init_vhost_client_ssl(info, vhost);
|
||||
|
||||
if (pvh)
|
||||
*pvh = vhost;
|
||||
|
||||
lws_protocol_init(context);
|
||||
|
||||
return context;
|
||||
|
|
|
@ -256,7 +256,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd)
|
|||
}
|
||||
|
||||
#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);
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, vhost->iface,
|
||||
strlen(vhost->iface)) < 0) {
|
||||
|
|
|
@ -218,6 +218,9 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
|
|||
/* if something closed, retry this slot */
|
||||
if (n)
|
||||
i--;
|
||||
|
||||
if (wsi->trunc_len)
|
||||
WSASetEvent(pt->events[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
33
lib/output.c
33
lib/output.c
|
@ -250,6 +250,23 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len,
|
|||
int pre = 0, n;
|
||||
size_t orig_len = len;
|
||||
|
||||
if (wsi->parent_carries_io) {
|
||||
struct lws_write_passthru pas;
|
||||
|
||||
pas.buf = buf;
|
||||
pas.len = len;
|
||||
pas.wp = wp;
|
||||
pas.wsi = wsi;
|
||||
|
||||
if (wsi->parent->protocol->callback(wsi->parent,
|
||||
LWS_CALLBACK_CHILD_WRITE_VIA_PARENT,
|
||||
wsi->parent->user_space,
|
||||
(void *)&pas, 0))
|
||||
return 1;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_API_LWS_WRITE, 1);
|
||||
|
||||
if ((int)len < 0) {
|
||||
|
@ -269,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) {
|
||||
/* remove us from the 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;
|
||||
/* remove us from context draining ext list */
|
||||
while (*w) {
|
||||
|
@ -332,11 +350,13 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len,
|
|||
case LWS_WRITE_CLOSE:
|
||||
break;
|
||||
default:
|
||||
lwsl_debug("LWS_EXT_CB_PAYLOAD_TX\n");
|
||||
n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_TX, &eff_buf, wp);
|
||||
if (n < 0)
|
||||
return -1;
|
||||
|
||||
if (n && eff_buf.token_len) {
|
||||
lwsl_debug("drain len %d\n", (int)eff_buf.token_len);
|
||||
/* extension requires further draining */
|
||||
wsi->u.ws.tx_draining_ext = 1;
|
||||
wsi->u.ws.tx_draining_ext_list = pt->tx_draining_ext_list;
|
||||
|
@ -370,8 +390,8 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len,
|
|||
*/
|
||||
if ((char *)buf != eff_buf.token) {
|
||||
/*
|
||||
* ext might eat it, but no have anything to issue yet
|
||||
* in that case we have to follow his lead, but stash and
|
||||
* ext might eat it, but not have anything to issue yet.
|
||||
* In that case we have to follow his lead, but stash and
|
||||
* replace the write type that was lost here the first time.
|
||||
*/
|
||||
if (len && !eff_buf.token_len) {
|
||||
|
@ -390,6 +410,13 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len,
|
|||
buf = (unsigned char *)eff_buf.token;
|
||||
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) {
|
||||
case 13:
|
||||
if (masked7) {
|
||||
|
|
|
@ -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 */
|
||||
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
|
||||
* processing), apply and free it.
|
||||
|
@ -385,6 +389,9 @@ lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, int frag_idx)
|
|||
{
|
||||
int n;
|
||||
|
||||
if (!wsi->u.hdr.ah)
|
||||
return 0;
|
||||
|
||||
n = wsi->u.hdr.ah->frag_index[h];
|
||||
if (!n)
|
||||
return 0;
|
||||
|
@ -402,6 +409,9 @@ LWS_VISIBLE int lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h)
|
|||
int n;
|
||||
int len = 0;
|
||||
|
||||
if (!wsi->u.hdr.ah)
|
||||
return 0;
|
||||
|
||||
n = wsi->u.hdr.ah->frag_index[h];
|
||||
if (!n)
|
||||
return 0;
|
||||
|
@ -417,7 +427,12 @@ LWS_VISIBLE int lws_hdr_copy_fragment(struct lws *wsi, char *dst, int len,
|
|||
enum lws_token_indexes h, int frag_idx)
|
||||
{
|
||||
int n = 0;
|
||||
int f = wsi->u.hdr.ah->frag_index[h];
|
||||
int f;
|
||||
|
||||
if (!wsi->u.hdr.ah)
|
||||
return -1;
|
||||
|
||||
f = wsi->u.hdr.ah->frag_index[h];
|
||||
|
||||
if (!f)
|
||||
return -1;
|
||||
|
@ -448,6 +463,9 @@ LWS_VISIBLE int lws_hdr_copy(struct lws *wsi, char *dst, int len,
|
|||
if (toklen >= len)
|
||||
return -1;
|
||||
|
||||
if (!wsi->u.hdr.ah)
|
||||
return -1;
|
||||
|
||||
n = wsi->u.hdr.ah->frag_index[h];
|
||||
if (!n)
|
||||
return 0;
|
||||
|
@ -1145,6 +1163,7 @@ handle_first:
|
|||
wsi->u.ws.rsv_first_msg = (c & 0x70);
|
||||
wsi->u.ws.frame_is_binary =
|
||||
wsi->u.ws.opcode == LWSWSOPC_BINARY_FRAME;
|
||||
wsi->u.ws.first_fragment = 1;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
|
@ -1492,6 +1511,7 @@ drain_extension:
|
|||
/* eff_buf may be pointing somewhere completely different now,
|
||||
* it's the output
|
||||
*/
|
||||
wsi->u.ws.first_fragment = 0;
|
||||
if (n < 0) {
|
||||
/*
|
||||
* we may rely on this to get RX, just drop connection
|
||||
|
|
19
lib/pollfd.c
19
lib/pollfd.c
|
@ -236,6 +236,11 @@ remove_wsi_socket_from_fds(struct lws *wsi)
|
|||
#endif
|
||||
int m, ret = 0;
|
||||
|
||||
if (wsi->parent_carries_io) {
|
||||
lws_same_vh_protocol_remove(wsi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(LWS_WITH_ESP8266)
|
||||
if (wsi->desc.sockfd > context->max_fds) {
|
||||
lwsl_err("fd %d too high (%d)\n", wsi->desc.sockfd, context->max_fds);
|
||||
|
@ -348,6 +353,16 @@ lws_callback_on_writable(struct lws *wsi)
|
|||
if (wsi->socket_is_permanently_unusable)
|
||||
return 0;
|
||||
|
||||
if (wsi->parent_carries_io) {
|
||||
int n = lws_callback_on_writable(wsi->parent);
|
||||
|
||||
if (n < 0)
|
||||
return n;
|
||||
|
||||
wsi->parent_pending_cb_on_writable = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_WRITEABLE_CB_REQ, 1);
|
||||
#if defined(LWS_WITH_STATS)
|
||||
|
@ -434,8 +449,8 @@ lws_same_vh_protocol_insert(struct lws *wsi, int n)
|
|||
// wsi->same_vh_protocol_prev);
|
||||
|
||||
if (wsi->same_vh_protocol_prev || wsi->same_vh_protocol_next) {
|
||||
lwsl_err("Attempted to attach wsi twice to same vh prot\n");
|
||||
assert(0);
|
||||
lws_same_vh_protocol_remove(wsi);
|
||||
lwsl_notice("Attempted to attach wsi twice to same vh prot\n");
|
||||
}
|
||||
|
||||
wsi->same_vh_protocol_prev = /* guy who points to us */
|
||||
|
|
|
@ -891,6 +891,7 @@ struct lws_vhost {
|
|||
int ka_probes;
|
||||
int ka_interval;
|
||||
int keepalive_timeout;
|
||||
int timeout_secs_ah_idle;
|
||||
int ssl_info_event_mask;
|
||||
#ifdef LWS_WITH_ACCESS_LOG
|
||||
int log_fd;
|
||||
|
@ -1484,10 +1485,13 @@ struct _lws_websocket_related {
|
|||
unsigned int rx_draining_ext:1;
|
||||
unsigned int tx_draining_ext:1;
|
||||
unsigned int send_check_ping:1;
|
||||
unsigned int first_fragment:1;
|
||||
};
|
||||
|
||||
#ifdef LWS_WITH_CGI
|
||||
|
||||
#define LWS_HTTP_CHUNK_HDR_SIZE 16
|
||||
|
||||
enum {
|
||||
SIGNIFICANT_HDR_CONTENT_LENGTH,
|
||||
SIGNIFICANT_HDR_LOCATION,
|
||||
|
@ -1541,6 +1545,7 @@ struct lws_rewrite;
|
|||
struct lws_access_log {
|
||||
char *header_log;
|
||||
char *user_agent;
|
||||
char *referrer;
|
||||
unsigned long sent;
|
||||
int response;
|
||||
};
|
||||
|
@ -1588,6 +1593,7 @@ struct lws {
|
|||
struct lws_access_log access_log;
|
||||
#endif
|
||||
void *user_space;
|
||||
void *opaque_parent_data;
|
||||
/* rxflow handling */
|
||||
unsigned char *rxflow_buffer;
|
||||
/* truncated send handling */
|
||||
|
@ -1651,6 +1657,8 @@ struct lws {
|
|||
unsigned int told_user_closed:1;
|
||||
unsigned int waiting_to_send_close_frame:1;
|
||||
unsigned int ipv6:1;
|
||||
unsigned int parent_carries_io:1;
|
||||
unsigned int parent_pending_cb_on_writable:1;
|
||||
|
||||
#if defined(LWS_WITH_ESP8266)
|
||||
unsigned int pending_send_completion:3;
|
||||
|
|
174
lib/server.c
174
lib/server.c
|
@ -689,6 +689,17 @@ lws_unauthorised_basic_auth(struct lws *wsi)
|
|||
|
||||
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) {
|
||||
if (p[0] == '/' && p[1] == '/') {
|
||||
char *p1 = p;
|
||||
|
@ -777,7 +788,7 @@ lws_http_action(struct lws *wsi)
|
|||
|
||||
/* we insist on absolute paths */
|
||||
|
||||
if (uri_ptr[0] != '/') {
|
||||
if (!uri_ptr || uri_ptr[0] != '/') {
|
||||
lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
|
||||
|
||||
goto bail_nuke_ah;
|
||||
|
@ -895,7 +906,7 @@ lws_http_action(struct lws *wsi)
|
|||
const char *pa, *me;
|
||||
struct tm *tmp;
|
||||
time_t t = time(NULL);
|
||||
int l = 256;
|
||||
int l = 256, m;
|
||||
|
||||
if (wsi->access_log_pending)
|
||||
lws_access_log(wsi);
|
||||
|
@ -913,10 +924,7 @@ lws_http_action(struct lws *wsi)
|
|||
if (!pa)
|
||||
pa = "(unknown)";
|
||||
|
||||
if (meth >= 0)
|
||||
me = method_names[meth];
|
||||
else
|
||||
me = "unknown";
|
||||
me = method_names[meth];
|
||||
|
||||
lws_snprintf(wsi->access_log.header_log, l,
|
||||
"%s - - [%s] \"%s %s %s\"",
|
||||
|
@ -931,6 +939,23 @@ lws_http_action(struct lws *wsi)
|
|||
l + 1, WSI_TOKEN_HTTP_USER_AGENT);
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
@ -997,10 +1022,13 @@ lws_http_action(struct lws *wsi)
|
|||
hit->origin);
|
||||
else
|
||||
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),
|
||||
uri_ptr);
|
||||
|
||||
lwsl_notice("%s\n", end);
|
||||
lws_clean_url((char *)end);
|
||||
lwsl_notice("%s\n", end);
|
||||
|
||||
n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
|
||||
end, n, &p, end);
|
||||
|
@ -1284,6 +1312,57 @@ transaction_result_n:
|
|||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
lws_server_init_wsi_for_ws(struct lws *wsi)
|
||||
{
|
||||
int n;
|
||||
|
||||
wsi->state = LWSS_ESTABLISHED;
|
||||
lws_restart_ws_ping_pong_timer(wsi);
|
||||
|
||||
/*
|
||||
* create the frame buffer for this connection according to the
|
||||
* size mentioned in the protocol definition. If 0 there, use
|
||||
* a big default for compatibility
|
||||
*/
|
||||
|
||||
n = wsi->protocol->rx_buffer_size;
|
||||
if (!n)
|
||||
n = wsi->context->pt_serv_buf_size;
|
||||
n += LWS_PRE;
|
||||
wsi->u.ws.rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */);
|
||||
if (!wsi->u.ws.rx_ubuf) {
|
||||
lwsl_err("Out of Mem allocating rx buffer %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
wsi->u.ws.rx_ubuf_alloc = n;
|
||||
lwsl_debug("Allocating RX buffer %d\n", n);
|
||||
|
||||
#if LWS_POSIX && !defined(LWS_WITH_ESP32)
|
||||
if (!wsi->parent_carries_io)
|
||||
if (setsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_SNDBUF,
|
||||
(const char *)&n, sizeof n)) {
|
||||
lwsl_warn("Failed to set SNDBUF to %d", n);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* notify user code that we're ready to roll */
|
||||
|
||||
if (wsi->protocol->callback)
|
||||
if (wsi->protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED,
|
||||
wsi->user_space,
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
wsi->ssl,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
0))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
||||
{
|
||||
|
@ -1652,49 +1731,10 @@ upgrade_ws:
|
|||
wsi->u.hdr = hdr;
|
||||
lws_pt_unlock(pt);
|
||||
|
||||
lws_restart_ws_ping_pong_timer(wsi);
|
||||
|
||||
/*
|
||||
* create the frame buffer for this connection according to the
|
||||
* size mentioned in the protocol definition. If 0 there, use
|
||||
* a big default for compatibility
|
||||
*/
|
||||
|
||||
n = wsi->protocol->rx_buffer_size;
|
||||
if (!n)
|
||||
n = context->pt_serv_buf_size;
|
||||
n += LWS_PRE;
|
||||
wsi->u.ws.rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */);
|
||||
if (!wsi->u.ws.rx_ubuf) {
|
||||
lwsl_err("Out of Mem allocating rx buffer %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
wsi->u.ws.rx_ubuf_alloc = n;
|
||||
lwsl_debug("Allocating RX buffer %d\n", n);
|
||||
#if LWS_POSIX && !defined(LWS_WITH_ESP32)
|
||||
if (setsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_SNDBUF,
|
||||
(const char *)&n, sizeof n)) {
|
||||
lwsl_warn("Failed to set SNDBUF to %d", n);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
lws_server_init_wsi_for_ws(wsi);
|
||||
lwsl_parser("accepted v%02d connection\n",
|
||||
wsi->ietf_spec_revision);
|
||||
|
||||
/* notify user code that we're ready to roll */
|
||||
|
||||
if (wsi->protocol->callback)
|
||||
if (wsi->protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED,
|
||||
wsi->user_space,
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
wsi->ssl,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
0))
|
||||
return 1;
|
||||
|
||||
/* !!! drop ah unreservedly after ESTABLISHED */
|
||||
if (!wsi->more_rx_waiting) {
|
||||
lws_header_table_force_to_detachable_state(wsi);
|
||||
|
@ -1782,6 +1822,8 @@ lws_create_new_server_wsi(struct lws_vhost *vhost)
|
|||
new_wsi->user_space = NULL;
|
||||
new_wsi->ietf_spec_revision = 0;
|
||||
new_wsi->desc.sockfd = LWS_SOCK_INVALID;
|
||||
new_wsi->position_in_fds_table = -1;
|
||||
|
||||
vhost->context->count_wsi_allocated++;
|
||||
|
||||
/*
|
||||
|
@ -1864,8 +1906,17 @@ lws_http_transaction_completed(struct lws *wsi)
|
|||
return 1;
|
||||
}
|
||||
#endif
|
||||
} else
|
||||
} else {
|
||||
lws_header_table_reset(wsi, 1);
|
||||
/*
|
||||
* If we kept the ah, we should restrict the amount
|
||||
* of time we are willing to keep it. Otherwise it
|
||||
* will be bound the whole time the connection remains
|
||||
* open.
|
||||
*/
|
||||
lws_set_timeout(wsi, PENDING_TIMEOUT_HOLDING_AH,
|
||||
wsi->vhost->keepalive_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're (re)starting on headers, need other implied init */
|
||||
|
@ -1889,7 +1940,7 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
|
|||
int n, ssl = 0;
|
||||
|
||||
if (!new_wsi) {
|
||||
if (type & LWS_ADOPT_SOCKET)
|
||||
if (type & LWS_ADOPT_SOCKET && !(type & LWS_ADOPT_WS_PARENTIO))
|
||||
compatible_close(fd.sockfd);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1900,6 +1951,9 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
|
|||
new_wsi->parent = parent;
|
||||
new_wsi->sibling_list = parent->child_list;
|
||||
parent->child_list = new_wsi;
|
||||
|
||||
if (type & LWS_ADOPT_WS_PARENTIO)
|
||||
new_wsi->parent_carries_io = 1;
|
||||
}
|
||||
|
||||
new_wsi->desc = fd;
|
||||
|
@ -1916,6 +1970,15 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
|
|||
lwsl_notice("OOM trying to get user_space\n");
|
||||
goto bail;
|
||||
}
|
||||
if (type & LWS_ADOPT_WS_PARENTIO) {
|
||||
new_wsi->desc.sockfd = LWS_SOCK_INVALID;
|
||||
lwsl_debug("binding to %s\n", new_wsi->protocol->name);
|
||||
lws_bind_protocol(new_wsi, new_wsi->protocol);
|
||||
lws_union_transition(new_wsi, LWSCM_WS_SERVING);
|
||||
lws_server_init_wsi_for_ws(new_wsi);
|
||||
|
||||
return new_wsi;
|
||||
}
|
||||
} else
|
||||
if (type & LWS_ADOPT_HTTP) /* he will transition later */
|
||||
new_wsi->protocol =
|
||||
|
@ -2003,11 +2066,10 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
|
|||
goto fail;
|
||||
|
||||
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");
|
||||
} else {
|
||||
lwsl_notice("%s: waiting for ah\n", __func__);
|
||||
}
|
||||
else
|
||||
lwsl_info("%s: waiting for ah\n", __func__);
|
||||
}
|
||||
|
||||
return new_wsi;
|
||||
|
@ -2583,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");
|
||||
}
|
||||
|
||||
if (
|
||||
#if defined(LWS_WITH_RANGES)
|
||||
if (ranges < 2 && content_type && content_type[0])
|
||||
ranges < 2 &&
|
||||
#endif
|
||||
content_type && content_type[0])
|
||||
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
|
||||
(unsigned char *)content_type,
|
||||
strlen(content_type), &p, end))
|
||||
return -1;
|
||||
|
||||
#if defined(LWS_WITH_RANGES)
|
||||
if (ranges >= 2) { /* multipart byteranges */
|
||||
strncpy(wsi->u.http.multipart_content_type, content_type,
|
||||
sizeof(wsi->u.http.multipart_content_type) - 1);
|
||||
|
|
|
@ -329,6 +329,13 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
|
|||
user_service:
|
||||
/* one shot */
|
||||
|
||||
if (wsi->parent_carries_io) {
|
||||
wsi->handling_pollout = 0;
|
||||
wsi->leave_pollout_active = 0;
|
||||
|
||||
return lws_calllback_as_writeable(wsi);
|
||||
}
|
||||
|
||||
if (pollfd) {
|
||||
int eff = wsi->leave_pollout_active;
|
||||
|
||||
|
@ -847,6 +854,10 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
|
|||
if (pollfd)
|
||||
our_fd = pollfd->fd;
|
||||
|
||||
/*
|
||||
* Phase 1: check every wsi on the timeout check list
|
||||
*/
|
||||
|
||||
wsi = context->pt[tsi].timeout_list;
|
||||
while (wsi) {
|
||||
/* we have to take copies, because he may be deleted */
|
||||
|
@ -861,7 +872,70 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
|
|||
}
|
||||
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
|
||||
/*
|
||||
* Phase 3: handle cgi timeouts
|
||||
*/
|
||||
lws_cgi_kill_terminated(pt);
|
||||
#endif
|
||||
#if 0
|
||||
|
@ -952,7 +1026,8 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
|
|||
#endif
|
||||
|
||||
// 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");
|
||||
wsi->socket_is_permanently_unusable = 1;
|
||||
goto close_and_handled;
|
||||
|
|
|
@ -41,7 +41,7 @@ int lws_alloc_vfs_file(struct lws_context *context, const char *filename, uint8_
|
|||
len = lws_vfs_get_length(fops_fd);
|
||||
|
||||
*buf = malloc((size_t)len);
|
||||
if (!buf)
|
||||
if (!*buf)
|
||||
goto bail;
|
||||
|
||||
if (lws_vfs_file_read(fops_fd, amount, *buf, len))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Name: libwebsockets
|
||||
Version: 2.2.0
|
||||
Version: 2.3.0
|
||||
Release: 1%{?dist}
|
||||
Summary: Websocket Server and Client Library
|
||||
|
||||
|
@ -49,13 +49,12 @@ rm -rf $RPM_BUILD_ROOT
|
|||
%attr(755,root,root)
|
||||
/usr/bin/libwebsockets-test-server
|
||||
/usr/bin/libwebsockets-test-server-extpoll
|
||||
/usr/bin/libwebsockets-test-server-pthreads
|
||||
/usr/bin/libwebsockets-test-client
|
||||
/usr/bin/libwebsockets-test-ping
|
||||
/usr/bin/libwebsockets-test-echo
|
||||
/usr/bin/libwebsockets-test-fraggle
|
||||
/usr/bin/libwebsockets-test-fuzxy
|
||||
/%{_libdir}/libwebsockets.so.10
|
||||
/%{_libdir}/libwebsockets.so.11
|
||||
/%{_libdir}/libwebsockets.so
|
||||
/%{_libdir}/cmake/libwebsockets/LibwebsocketsConfig.cmake
|
||||
/%{_libdir}/cmake/libwebsockets/LibwebsocketsConfigVersion.cmake
|
||||
|
@ -70,8 +69,12 @@ rm -rf $RPM_BUILD_ROOT
|
|||
%attr(755,root,root)
|
||||
/%{_libdir}/libwebsockets.a
|
||||
/%{_libdir}/pkgconfig/libwebsockets.pc
|
||||
/%{_libdir}/pkgconfig/libwebsockets_static.pc
|
||||
|
||||
%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
|
||||
- MAJOR SONAMEBUMP APICHANGES Upstream 2.2.0 release
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
# vhost-specific config options for the protocol
|
||||
#
|
||||
"ws-protocols": [{
|
||||
"lws-meta": {
|
||||
"status": "ok"
|
||||
},
|
||||
"dumb-increment-protocol": {
|
||||
"status": "ok"
|
||||
},
|
||||
|
|
|
@ -58,11 +58,13 @@ static int pids[32];
|
|||
#define LWSWS_CONFIG_STRING_SIZE (32 * 1024)
|
||||
|
||||
static const struct lws_extension exts[] = {
|
||||
#if !defined(LWS_NO_EXTENSIONS)
|
||||
{
|
||||
"permessage-deflate",
|
||||
lws_extension_callback_pm_deflate,
|
||||
"permessage-deflate"
|
||||
},
|
||||
#endif
|
||||
{ NULL, NULL, NULL /* terminator */ }
|
||||
};
|
||||
|
||||
|
@ -220,7 +222,7 @@ int main(int argc, char **argv)
|
|||
break;
|
||||
case 'h':
|
||||
fprintf(stderr, "Usage: lwsws [-c <config dir>] "
|
||||
"[-d <log bitfield>] [-D] [--help]\n");
|
||||
"[-d <log bitfield>] [--help]\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -474,7 +474,7 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
WSI_TOKEN_HOST) < 0)
|
||||
return 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);
|
||||
lwsl_notice("redirecting to ourselves with cookie refresh\n");
|
||||
/* we need a redirect to ourselves, session cookie is expired */
|
||||
|
|
616
plugins/protocol_lws_meta.c
Normal file
616
plugins/protocol_lws_meta.c
Normal file
|
@ -0,0 +1,616 @@
|
|||
/*
|
||||
* lws meta protocol handler
|
||||
*
|
||||
* Copyright (C) 2017 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined (LWS_PLUGIN_STATIC)
|
||||
#define LWS_DLL
|
||||
#define LWS_INTERNAL
|
||||
#include "../lib/libwebsockets.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_SUBCHANNELS 8
|
||||
|
||||
enum lws_meta_parser_state {
|
||||
MP_IDLE, /* in body of message */
|
||||
|
||||
MP_CMD, /* await cmd */
|
||||
|
||||
MP_OPEN_SUBCHANNEL_PROTOCOL,
|
||||
MP_OPEN_SUBCHANNEL_URL,
|
||||
MP_OPEN_SUBCHANNEL_COOKIE,
|
||||
|
||||
MP_CLOSE_CHID,
|
||||
MP_CLOSE_LEN,
|
||||
MP_CLOSE_CODEM,
|
||||
MP_CLOSE_CODEL,
|
||||
MP_CLOSE_PAYLOAD,
|
||||
|
||||
MP_WRITE_CHID,
|
||||
};
|
||||
|
||||
enum {
|
||||
PENDING_TYPE_OPEN_RESULT = 0,
|
||||
PENDING_TYPE_CHILD_CLOSE
|
||||
};
|
||||
|
||||
/*
|
||||
* while we haven't reported the result yet, we keep a linked-list of
|
||||
* connection opens and their result.
|
||||
*/
|
||||
struct pending_conn {
|
||||
struct pending_conn *next;
|
||||
char protocol[123];
|
||||
char cookie[8];
|
||||
int ch;
|
||||
int len;
|
||||
|
||||
unsigned char type;
|
||||
};
|
||||
|
||||
/*
|
||||
* the parent, lws-meta connection
|
||||
*/
|
||||
struct per_session_data__lws_meta {
|
||||
struct lws *wsi[MAX_SUBCHANNELS + 1];
|
||||
char told_closing[MAX_SUBCHANNELS + 1];
|
||||
struct pending_conn *first;
|
||||
struct pending_conn *pend;
|
||||
char suburl[64];
|
||||
unsigned char close[126];
|
||||
int active_subchannel_tx, active_subchannel_rx;
|
||||
enum lws_meta_parser_state state;
|
||||
int pos;
|
||||
int count_pending;
|
||||
int round_robin;
|
||||
int close_status_16;
|
||||
int close_len;
|
||||
int which_close;
|
||||
int ch;
|
||||
};
|
||||
|
||||
static int
|
||||
lws_find_free_channel(struct per_session_data__lws_meta *pss)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 1; n <= MAX_SUBCHANNELS; n++)
|
||||
if (pss->wsi[n] == NULL)
|
||||
return n;
|
||||
|
||||
return 0; /* none free */
|
||||
}
|
||||
|
||||
static struct lws *
|
||||
lws_get_channel_wsi(struct per_session_data__lws_meta *pss, int ch)
|
||||
{
|
||||
if (!ch)
|
||||
return 0;
|
||||
return pss->wsi[ch];
|
||||
}
|
||||
|
||||
static int
|
||||
lws_get_channel_id(struct lws *wsi)
|
||||
{
|
||||
return (lws_intptr_t)lws_get_opaque_parent_data(wsi);
|
||||
}
|
||||
|
||||
static void
|
||||
lws_set_channel_id(struct lws *wsi, int id)
|
||||
{
|
||||
lws_set_opaque_parent_data(wsi, (void *)(lws_intptr_t)id);
|
||||
}
|
||||
|
||||
static struct pending_conn *
|
||||
new_pending(struct per_session_data__lws_meta *pss)
|
||||
{
|
||||
struct pending_conn *pend;
|
||||
|
||||
if (pss->count_pending >= MAX_SUBCHANNELS * 2) {
|
||||
lwsl_notice("too many pending open subchannel\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pss->count_pending++;
|
||||
|
||||
pend = malloc(sizeof(*pend));
|
||||
if (!pend) {
|
||||
lwsl_notice("OOM\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(pend, 0, sizeof(*pend));
|
||||
|
||||
return pend;
|
||||
}
|
||||
|
||||
static int
|
||||
callback_lws_meta(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct per_session_data__lws_meta *pss =
|
||||
(struct per_session_data__lws_meta *)user;
|
||||
struct lws_write_passthru *pas;
|
||||
struct pending_conn *pend, *pend1;
|
||||
struct lws *cwsi;
|
||||
lws_sock_file_fd_type fd;
|
||||
unsigned char *bin, buf[LWS_PRE + 512], *start = &buf[LWS_PRE],
|
||||
*end = &buf[sizeof(buf) - 1], *p = start;
|
||||
int n, m;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
lwsl_info("%s: LWS_CALLBACK_ESTABLISHED\n", __func__);
|
||||
pss->state = MP_CMD;
|
||||
pss->pos = 0;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CHILD_CLOSING:
|
||||
cwsi = (struct lws *)in;
|
||||
|
||||
/* remove it from our tracking */
|
||||
pss->wsi[lws_get_channel_id(cwsi)] = NULL;
|
||||
|
||||
if (pss->told_closing[lws_get_channel_id(cwsi)]) {
|
||||
pss->told_closing[lws_get_channel_id(cwsi)] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pend = new_pending(pss);
|
||||
if (!pend)
|
||||
return -1;
|
||||
|
||||
/* note which channel id */
|
||||
pend->ch = lws_get_channel_id(cwsi);
|
||||
|
||||
if (lws_get_close_length(cwsi)) {
|
||||
pend->len = lws_get_close_length(cwsi);
|
||||
memcpy(pend->protocol, lws_get_close_payload(cwsi),
|
||||
pend->len);
|
||||
}
|
||||
|
||||
pend->type = PENDING_TYPE_CHILD_CLOSE;
|
||||
pend->next = pss->first;
|
||||
pss->first = pend;
|
||||
|
||||
/*
|
||||
* nothing else will complete from this wsi, so abandon
|
||||
* tracking in-process messages from this wsi.
|
||||
*/
|
||||
|
||||
if (pss->active_subchannel_tx == pend->ch)
|
||||
pss->active_subchannel_tx = 0;
|
||||
|
||||
if (pss->active_subchannel_rx == pend->ch)
|
||||
pss->active_subchannel_rx = 0;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
|
||||
if (!pss->active_subchannel_tx) {
|
||||
|
||||
/* not in the middle of a message...
|
||||
*
|
||||
* PRIORITY 1: pending open and close notifications
|
||||
*/
|
||||
|
||||
pend = pss->first;
|
||||
while (pend && p < end - 128) {
|
||||
switch (pend->type) {
|
||||
case PENDING_TYPE_OPEN_RESULT:
|
||||
lwsl_debug("open result %s %s\n",
|
||||
pend->cookie, pend->protocol);
|
||||
*p++ = LWS_META_CMD_OPEN_RESULT;
|
||||
memcpy(p, pend->cookie,
|
||||
strlen(pend->cookie) + 1);
|
||||
p += strlen(pend->cookie) + 1;
|
||||
*p++ = LWS_META_TRANSPORT_OFFSET +
|
||||
pend->ch;
|
||||
memcpy(p, pend->protocol,
|
||||
strlen(pend->protocol) + 1);
|
||||
p += strlen(pend->protocol) + 1;
|
||||
break;
|
||||
case PENDING_TYPE_CHILD_CLOSE:
|
||||
*p++ = LWS_META_CMD_CLOSE_NOTIFY;
|
||||
*p++ = LWS_META_TRANSPORT_OFFSET +
|
||||
pend->ch;
|
||||
for (n = 0; n < pend->len; n++)
|
||||
*p++ = pend->protocol[n];
|
||||
break;
|
||||
}
|
||||
|
||||
pss->count_pending--;
|
||||
pend1 = pend;
|
||||
pend = pend->next;
|
||||
free(pend1);
|
||||
pss->first = pend;
|
||||
}
|
||||
|
||||
if (p != start) {
|
||||
if (lws_write(wsi, start, p - start,
|
||||
LWS_WRITE_BINARY) < 0)
|
||||
return 1;
|
||||
if (pend) /* still more */
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
}
|
||||
|
||||
/* PRIORITY 2: pick a child for the writable callback */
|
||||
|
||||
cwsi = NULL;
|
||||
for (n = 0; n < MAX_SUBCHANNELS; n++) {
|
||||
m = ((pss->round_robin + n) % MAX_SUBCHANNELS) + 1;
|
||||
if (pss->wsi[m] &&
|
||||
lws_get_child_pending_on_writable(pss->wsi[m])) {
|
||||
pss->round_robin = m;
|
||||
cwsi = pss->wsi[m];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
/* one child is in middle of message, stay with it */
|
||||
cwsi = pss->wsi[pss->active_subchannel_tx];
|
||||
|
||||
if (!cwsi)
|
||||
break;
|
||||
|
||||
lws_clear_child_pending_on_writable(cwsi);
|
||||
if (lws_handle_POLLOUT_event(cwsi, NULL))
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
bin = (unsigned char *)in;
|
||||
|
||||
/*
|
||||
* at the start of a message, we may have one or more
|
||||
* lws_meta command blocks.
|
||||
*/
|
||||
while (pss->state != MP_IDLE &&
|
||||
(unsigned int)(bin - (unsigned char *)in) < len) {
|
||||
|
||||
switch (pss->state) {
|
||||
case MP_IDLE: /* in body of message */
|
||||
|
||||
if (!lws_is_first_fragment(wsi))
|
||||
break;
|
||||
|
||||
pss->state = MP_CMD;
|
||||
|
||||
/* fallthru */
|
||||
|
||||
case MP_CMD: /* await cmd */
|
||||
|
||||
pss->pos = 0;
|
||||
|
||||
switch (*bin++) {
|
||||
case LWS_META_CMD_OPEN_SUBCHANNEL:
|
||||
|
||||
pss->pend = new_pending(pss);
|
||||
if (!pss->pend)
|
||||
return -1;
|
||||
|
||||
pss->state = MP_OPEN_SUBCHANNEL_PROTOCOL;
|
||||
|
||||
break;
|
||||
case LWS_META_CMD_CLOSE_NOTIFY:
|
||||
case LWS_META_CMD_CLOSE_RQ:
|
||||
pss->which_close = bin[-1];
|
||||
pss->state = MP_CLOSE_CHID;
|
||||
break;
|
||||
case LWS_META_CMD_WRITE:
|
||||
pss->state = MP_WRITE_CHID;
|
||||
break;
|
||||
|
||||
// open result is also illegal to receive
|
||||
default:
|
||||
lwsl_notice("bad lws_meta cmd 0x%x\n",
|
||||
bin[-1]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MP_OPEN_SUBCHANNEL_PROTOCOL:
|
||||
pss->pend->protocol[pss->pos++] = *bin++;
|
||||
if (pss->pos == sizeof(pss->pend->protocol) - 1) {
|
||||
lwsl_notice("protocol name too long\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bin[-1] != '\0')
|
||||
break;
|
||||
|
||||
pss->state = MP_OPEN_SUBCHANNEL_URL;
|
||||
pss->pos = 0;
|
||||
break;
|
||||
|
||||
case MP_OPEN_SUBCHANNEL_URL:
|
||||
pss->suburl[pss->pos++] = *bin++;
|
||||
if (pss->pos == sizeof(pss->suburl) - 1) {
|
||||
lwsl_notice("suburl too long\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bin[-1] != '\0')
|
||||
break;
|
||||
|
||||
pss->state = MP_OPEN_SUBCHANNEL_COOKIE;
|
||||
pss->pos = 0;
|
||||
break;
|
||||
|
||||
case MP_OPEN_SUBCHANNEL_COOKIE:
|
||||
pss->pend->cookie[pss->pos++] = *bin++;
|
||||
if (pss->pos == sizeof(pss->pend->cookie) - 1) {
|
||||
lwsl_notice("cookie too long\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bin[-1] != '\0')
|
||||
break;
|
||||
|
||||
lwsl_debug("%s: %s / %s / %s\n", __func__,
|
||||
pss->pend->protocol,
|
||||
pss->suburl,
|
||||
pss->pend->cookie);
|
||||
|
||||
pss->pend->ch = lws_find_free_channel(pss);
|
||||
if (pss->pend->ch) {
|
||||
|
||||
fd.sockfd = 0; // not going to be used
|
||||
|
||||
cwsi = lws_adopt_descriptor_vhost(
|
||||
lws_get_vhost(wsi),
|
||||
LWS_ADOPT_WS_PARENTIO,
|
||||
fd, pss->pend->protocol,
|
||||
wsi);
|
||||
|
||||
if (!cwsi) {
|
||||
lwsl_notice("open failed\n");
|
||||
pss->pend->ch = 0;
|
||||
} else {
|
||||
pss->wsi[pss->pend->ch] = cwsi;
|
||||
lws_set_channel_id(cwsi,
|
||||
pss->pend->ch);
|
||||
lwsl_debug("cwsi %p on parent %p open OK %s\n",
|
||||
cwsi, wsi, pss->pend->protocol);
|
||||
}
|
||||
|
||||
} else
|
||||
lwsl_notice("no free subchannels\n");
|
||||
|
||||
pss->pend->type = PENDING_TYPE_OPEN_RESULT;
|
||||
pss->pend->next = pss->first;
|
||||
pss->first = pss->pend;
|
||||
|
||||
lws_callback_on_writable(wsi);
|
||||
|
||||
pss->state = MP_CMD;
|
||||
pss->pos = 0;
|
||||
break;
|
||||
|
||||
case MP_CLOSE_CHID:
|
||||
pss->ch = (*bin++) - LWS_META_TRANSPORT_OFFSET;
|
||||
pss->state = MP_CLOSE_LEN;
|
||||
pss->pos = 0;
|
||||
break;
|
||||
case MP_CLOSE_LEN:
|
||||
pss->close_len = (*bin++) -
|
||||
LWS_META_TRANSPORT_OFFSET;
|
||||
lwsl_debug("close len %d\n", pss->close_len);
|
||||
pss->state = MP_CLOSE_CODEM;
|
||||
pss->pos = 0;
|
||||
break;
|
||||
case MP_CLOSE_CODEM:
|
||||
pss->close[pss->pos++] = *bin;
|
||||
pss->close_status_16 = (*bin++) * 256;
|
||||
pss->state = MP_CLOSE_CODEL;
|
||||
break;
|
||||
case MP_CLOSE_CODEL:
|
||||
pss->close[pss->pos++] = *bin;
|
||||
pss->close_status_16 |= *bin++;
|
||||
pss->state = MP_CLOSE_PAYLOAD;
|
||||
break;
|
||||
case MP_CLOSE_PAYLOAD:
|
||||
pss->close[pss->pos++] = *bin++;
|
||||
if (pss->pos == sizeof(pss->close) - 1) {
|
||||
lwsl_notice("close payload too long\n");
|
||||
return -1;
|
||||
}
|
||||
if (--pss->close_len)
|
||||
break;
|
||||
|
||||
pss->state = MP_CMD;
|
||||
|
||||
cwsi = lws_get_channel_wsi(pss, pss->ch);
|
||||
if (!cwsi) {
|
||||
lwsl_notice("close (%d) bad ch %d\n",
|
||||
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);
|
||||
break;
|
||||
|
||||
case MP_WRITE_CHID:
|
||||
pss->active_subchannel_rx = (*bin++) -
|
||||
LWS_META_TRANSPORT_OFFSET;
|
||||
pss->state = MP_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
len -= bin - (unsigned char *)in;
|
||||
|
||||
if (!len)
|
||||
break;
|
||||
|
||||
cwsi = lws_get_channel_wsi(pss, pss->active_subchannel_rx);
|
||||
if (!cwsi) {
|
||||
lwsl_notice("bad ch %d\n", pss->active_subchannel_rx);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
lwsl_debug("%s: RX len %d\n", __func__, (int)len);
|
||||
|
||||
if (lws_get_protocol(cwsi)->callback(cwsi,
|
||||
LWS_CALLBACK_RECEIVE,
|
||||
lws_wsi_user(cwsi), bin, len))
|
||||
lws_set_timeout(cwsi,
|
||||
PENDING_TIMEOUT_KILLED_BY_PARENT,
|
||||
LWS_TO_KILL_SYNC);
|
||||
|
||||
if (lws_is_final_fragment(wsi)) {
|
||||
pss->active_subchannel_rx = 0;
|
||||
pss->state = MP_CMD;
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
* child wrote something via lws_write.... which passed it up to us to
|
||||
* deal with, because we are the parent. Prepend two bytes for
|
||||
* lws-meta command and channel index, and send it out on parent
|
||||
*/
|
||||
case LWS_CALLBACK_CHILD_WRITE_VIA_PARENT:
|
||||
pas = in;
|
||||
bin = ((unsigned char *)pas->buf);
|
||||
|
||||
if ((pas->wp & 7) == 4 /*LWS_WRITE_CLOSE */) {
|
||||
*p++ = LWS_META_CMD_CLOSE_NOTIFY;
|
||||
*p++ = LWS_META_TRANSPORT_OFFSET +
|
||||
lws_get_channel_id(pas->wsi);
|
||||
*p++ = (unsigned char)pas->len +
|
||||
LWS_META_TRANSPORT_OFFSET - 2;
|
||||
*p++ = *bin++;
|
||||
*p++ = *bin++;
|
||||
for (n = 0; n < (int)pas->len - 2; n++)
|
||||
*p++ = bin[n];
|
||||
|
||||
if (lws_write(wsi, start, p - start,
|
||||
LWS_WRITE_BINARY) < 0)
|
||||
return 1;
|
||||
|
||||
pss->told_closing[lws_get_channel_id(pas->wsi)] = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((pas->wp & 7) == LWS_WRITE_TEXT ||
|
||||
(pas->wp & 7) == LWS_WRITE_BINARY) {
|
||||
|
||||
if (pas->wp & LWS_WRITE_NO_FIN)
|
||||
pss->active_subchannel_tx =
|
||||
lws_get_channel_id(pas->wsi);
|
||||
|
||||
/* start of message, prepend the subchannel id */
|
||||
|
||||
bin -= 2;
|
||||
bin[0] = LWS_META_CMD_WRITE;
|
||||
bin[1] = lws_get_channel_id(pas->wsi) +
|
||||
LWS_META_TRANSPORT_OFFSET;
|
||||
if (lws_write(wsi, bin, pas->len + 2, pas->wp) < 0)
|
||||
return 1;
|
||||
} else
|
||||
if (lws_write(wsi, bin, pas->len, pas->wp) < 0)
|
||||
return 1;
|
||||
|
||||
/* track EOM */
|
||||
|
||||
if (!(pas->wp & LWS_WRITE_NO_FIN))
|
||||
pss->active_subchannel_tx = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LWS_PLUGIN_PROTOCOL_LWS_META { \
|
||||
"lws-meta", \
|
||||
callback_lws_meta, \
|
||||
sizeof(struct per_session_data__lws_meta), \
|
||||
1024, /* rx buf size must be >= permessage-deflate rx size */ \
|
||||
0, NULL, 0 \
|
||||
}
|
||||
|
||||
#if !defined (LWS_PLUGIN_STATIC)
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
LWS_PLUGIN_PROTOCOL_LWS_META
|
||||
};
|
||||
|
||||
LWS_EXTERN LWS_VISIBLE int
|
||||
init_protocol_lws_meta(struct lws_context *context,
|
||||
struct lws_plugin_capability *c)
|
||||
{
|
||||
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
|
||||
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
|
||||
c->api_magic);
|
||||
return 1;
|
||||
}
|
||||
|
||||
c->protocols = protocols;
|
||||
c->count_protocols = ARRAY_SIZE(protocols);
|
||||
c->extensions = NULL;
|
||||
c->count_extensions = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_EXTERN LWS_VISIBLE int
|
||||
destroy_protocol_lws_meta(struct lws_context *context)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -10,7 +10,9 @@ SHELL=/bin/bash
|
|||
|
||||
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)
|
||||
ifeq ($(FAC),)
|
||||
|
@ -19,20 +21,20 @@ endif
|
|||
export FAC
|
||||
DIRNAME:=$(shell basename $$(pwd) | tr -d '\n')
|
||||
|
||||
$(COMPONENT_PATH)/../build/pack.img: $(APP_BIN)
|
||||
$(LWS_BUILD_PATH)/pack.img: $(APP_BIN)
|
||||
GNUSTAT=stat ;\
|
||||
if [ `which gstat 2>/dev/null` ] ; then GNUSTAT=gstat ; fi ;\
|
||||
DIRNAME=$$(basename $$(pwd) | tr -d '\n') ;\
|
||||
genromfs -f $(COMPONENT_PATH)/../build/romfs.img -d $(COMPONENT_PATH)/../romfs-files ; \
|
||||
RLEN=$$($$GNUSTAT -c %s $(COMPONENT_PATH)/../build/romfs.img) ;\
|
||||
LEN=$$($$GNUSTAT -c %s $(COMPONENT_PATH)/../build/$$DIRNAME.bin) ;\
|
||||
genromfs -f $(LWS_BUILD_PATH)/romfs.img -d $(PROJECT_PATH)/romfs-files ; \
|
||||
RLEN=$$($$GNUSTAT -c %s $(LWS_BUILD_PATH)/romfs.img) ;\
|
||||
LEN=$$($$GNUSTAT -c %s $(LWS_BUILD_PATH)/$$DIRNAME.bin) ;\
|
||||
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 ) % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\
|
||||
printf %02x $$(( ( $$RLEN / 65536 ) % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\
|
||||
printf %02x $$(( ( $$RLEN / 16777216 ) % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\
|
||||
cat $(COMPONENT_PATH)/../build/romfs.img >>$(COMPONENT_PATH)/../build/$$DIRNAME.bin ; \
|
||||
LEN=$$($$GNUSTAT -c %s $(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 >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
|
||||
printf %02x $$(( ( $$RLEN / 65536 ) % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
|
||||
printf %02x $$(( ( $$RLEN / 16777216 ) % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
|
||||
cat $(LWS_BUILD_PATH)/romfs.img >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ; \
|
||||
LEN=$$($$GNUSTAT -c %s $(LWS_BUILD_PATH)/$$DIRNAME.bin) ;\
|
||||
UNIXTIME=$$(date +%s | tr -d '\n') ; \
|
||||
echo -n -e "{\r\n \"schema\": \"lws1\",\r\n \"model\": \"$(CONFIG_LWS_MODEL_NAME)\",\r\n \"builder\": \"" > $(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}" >> $(jbi) ;\
|
||||
JLEN=$$($$GNUSTAT -c %s $(jbi)) ;\
|
||||
printf %02x $$(( $$JLEN % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\
|
||||
printf %02x $$(( ( $$JLEN / 256 ) % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\
|
||||
printf %02x $$(( ( $$JLEN / 65536 ) % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\
|
||||
printf %02x $$(( ( $$JLEN / 16777216 ) % 256 )) | xxd -r -p >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\
|
||||
cat $(jbi) >> $(COMPONENT_PATH)/../build/$$DIRNAME.bin ;\
|
||||
cp $(COMPONENT_PATH)/../build/$$DIRNAME.bin $(COMPONENT_PATH)/../build/pack.img ;\
|
||||
LEN=$$($$GNUSTAT -c %s $(COMPONENT_PATH)/../build/$$DIRNAME.bin) ;\
|
||||
cp $(COMPONENT_PATH)/../build/$$DIRNAME.bin $(COMPONENT_PATH)/../build/$$DIRNAME-$$UNIXTIME.bin ;\
|
||||
printf %02x $$(( $$JLEN % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
|
||||
printf %02x $$(( ( $$JLEN / 256 ) % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
|
||||
printf %02x $$(( ( $$JLEN / 65536 ) % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
|
||||
printf %02x $$(( ( $$JLEN / 16777216 ) % 256 )) | xxd -r -p >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
|
||||
cat $(jbi) >> $(LWS_BUILD_PATH)/$$DIRNAME.bin ;\
|
||||
cp $(LWS_BUILD_PATH)/$$DIRNAME.bin $(LWS_BUILD_PATH)/pack.img ;\
|
||||
LEN=$$($$GNUSTAT -c %s $(LWS_BUILD_PATH)/$$DIRNAME.bin) ;\
|
||||
cp $(LWS_BUILD_PATH)/$$DIRNAME.bin $(LWS_BUILD_PATH)/$$DIRNAME-$$UNIXTIME.bin ;\
|
||||
printf " After ROMFS + Build info: 0x%06x (%8d)\n" $$LEN $$LEN
|
||||
|
||||
.PHONY: manifest
|
||||
|
@ -76,17 +78,17 @@ endif
|
|||
cat $(F)/build/json-buildinfo >> 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') ;\
|
||||
$(IDF_PATH)/components/esptool_py/esptool/esptool.py \
|
||||
--chip esp32 \
|
||||
--port $(ESPPORT) \
|
||||
--baud $(CONFIG_ESPTOOLPY_BAUD) \
|
||||
write_flash 0x110000 $(COMPONENT_PATH)/../build/$$DIRNAME.bin
|
||||
write_flash 0x110000 $(LWS_BUILD_PATH)/$$DIRNAME.bin
|
||||
|
||||
erase_ota:
|
||||
$(IDF_PATH)/components/esptool_py/esptool/esptool.py \
|
||||
|
|
|
@ -29,10 +29,10 @@ function check {
|
|||
fi
|
||||
if [ "$1" = "defaultplusforbidden" ] ; then
|
||||
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
|
||||
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
|
||||
fi
|
||||
fi
|
||||
|
@ -101,7 +101,9 @@ killall libwebsockets-test-server 2>/dev/null
|
|||
libwebsockets-test-server -d15 2>> $LOG &
|
||||
CPID=$!
|
||||
|
||||
while [ -z "`grep Listening $LOG`" ] ; do
|
||||
echo "Started server on PID $CPID"
|
||||
|
||||
while [ -z "`grep ort\ 7681 $LOG`" ] ; do
|
||||
sleep 0.5s
|
||||
done
|
||||
check
|
||||
|
@ -220,7 +222,7 @@ echo -e "GET ...................................................................
|
|||
check
|
||||
|
||||
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........................................" \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
|
|
|
@ -108,6 +108,285 @@ function removeEvent( obj, type, fn ) {
|
|||
* end of grayOut related stuff
|
||||
*/
|
||||
|
||||
/*
|
||||
* lws-meta helpers
|
||||
*/
|
||||
|
||||
var lws_meta_cmd = {
|
||||
OPEN_SUBCHANNEL: 0x41,
|
||||
/**< Client requests to open new subchannel
|
||||
*/
|
||||
OPEN_RESULT: 0x42,
|
||||
/**< Result of client request to open new subchannel */
|
||||
CLOSE_NOT: 0x43,
|
||||
CLOSE_RQ: 0x44,
|
||||
/**< client requests to close a subchannel */
|
||||
WRITE: 0x45,
|
||||
/**< connection writes something to specific channel index */
|
||||
RX: 0x46,
|
||||
};
|
||||
|
||||
function new_ws(urlpath, protocol)
|
||||
{
|
||||
if (typeof MozWebSocket != "undefined")
|
||||
return new MozWebSocket(urlpath, protocol);
|
||||
|
||||
return new WebSocket(urlpath, protocol);
|
||||
}
|
||||
|
||||
function lws_meta_ws() {
|
||||
var real;
|
||||
|
||||
var channel_id_to_child;
|
||||
var pending_children;
|
||||
var active_children;
|
||||
}
|
||||
|
||||
function lws_meta_ws_child() {
|
||||
var onopen;
|
||||
var onmessage;
|
||||
var onclose;
|
||||
|
||||
var channel_id;
|
||||
|
||||
var subprotocol;
|
||||
var suburl;
|
||||
var cookie;
|
||||
|
||||
var extensions;
|
||||
|
||||
var parent;
|
||||
}
|
||||
|
||||
lws_meta_ws_child.prototype.send = function(data)
|
||||
{
|
||||
|
||||
if (typeof data == "string") {
|
||||
data = String.fromCharCode(lws_meta_cmd.WRITE) +
|
||||
String.fromCharCode(this.channel_id) +
|
||||
data;
|
||||
|
||||
return this.parent.real.send(data);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
var ab = new Uint8Array(data.length + 2);
|
||||
|
||||
ab[0] = lws_meta_cmd.WRITE;
|
||||
ab[1] = this.channel_id;
|
||||
ab.set(data, 2);
|
||||
|
||||
return this.parent.real.send(ab);
|
||||
}
|
||||
}
|
||||
|
||||
lws_meta_ws_child.prototype.close = function(close_code, close_string)
|
||||
{
|
||||
var pkt = new Uint8Array(129), m = 0, pkt1;
|
||||
|
||||
pkt[m++] = lws_meta_cmd.CLOSE_RQ;
|
||||
pkt[m++] = this.channel_id;
|
||||
|
||||
pkt[m++] = close_string.length + 0x20;
|
||||
|
||||
pkt[m++] = close_code / 256;
|
||||
pkt[m++] = close_code % 256;
|
||||
|
||||
for (i = 0; i < close_string.length; i++)
|
||||
pkt[m++] = close_string.charCodeAt(i);
|
||||
|
||||
pkt1 = new Uint8Array(m);
|
||||
for (n = 0; n < m; n++)
|
||||
pkt1[n] = pkt[n];
|
||||
|
||||
this.parent.real.send(pkt1.buffer);
|
||||
}
|
||||
|
||||
/* make a real ws connection using lws_meta*/
|
||||
lws_meta_ws.prototype.new_parent = function(urlpath)
|
||||
{
|
||||
var n, i, m = 0, pkt1;
|
||||
|
||||
this.ordinal = 1;
|
||||
this.pending_children = [];
|
||||
this.active_children = [];
|
||||
this.real = new_ws(urlpath, "lws-meta");
|
||||
|
||||
this.real.binaryType = 'arraybuffer';
|
||||
this.real.myparent = this;
|
||||
|
||||
this.real.onopen = function() {
|
||||
pkt = new Uint8Array(1024);
|
||||
var n, i, m = 0, pkt1;
|
||||
console.log("real open - pending children " + this.myparent.pending_children.length);
|
||||
for (n = 0; n < this.myparent.pending_children.length; n++) {
|
||||
|
||||
var p = this.myparent.pending_children[n];
|
||||
|
||||
pkt[m++] = lws_meta_cmd.OPEN_SUBCHANNEL;
|
||||
for (i = 0; i < p.subprotocol.length; i++)
|
||||
pkt[m++] = p.subprotocol.charCodeAt(i);
|
||||
pkt[m++] = 0;
|
||||
for (i = 0; i < p.suburl.length; i++)
|
||||
pkt[m++] = p.suburl.charCodeAt(i);
|
||||
pkt[m++] = 0;
|
||||
for (i = 0; i < p.cookie.length; i++)
|
||||
pkt[m++] = p.cookie.charCodeAt(i);
|
||||
pkt[m++] = 0;
|
||||
}
|
||||
|
||||
pkt1 = new Uint8Array(m);
|
||||
for (n = 0; n < m; n++)
|
||||
pkt1[n] = pkt[n];
|
||||
|
||||
console.log(this.myparent.pending_children[0].subprotocol);
|
||||
console.log(pkt1);
|
||||
|
||||
this.send(pkt1.buffer);
|
||||
}
|
||||
|
||||
|
||||
this.real.onmessage = function(msg) {
|
||||
|
||||
if (typeof msg.data != "string") {
|
||||
var ba = new Uint8Array(msg.data), n = 0;
|
||||
|
||||
while (n < ba.length) {
|
||||
|
||||
switch (ba[n++]) {
|
||||
case lws_meta_cmd.OPEN_RESULT:
|
||||
{
|
||||
var m = 0, cookie = "", protocol = "", ch = 0;
|
||||
var ws = this.myparent;
|
||||
/* cookie NUL
|
||||
* channel index + 0x20
|
||||
* protocol NUL
|
||||
*/
|
||||
while (ba[n])
|
||||
cookie = cookie + String.fromCharCode(ba[n++]);
|
||||
n++;
|
||||
ch = ba[n++];
|
||||
|
||||
while (ba[n])
|
||||
protocol = protocol + String.fromCharCode(ba[n++]);
|
||||
|
||||
console.log("open result " + cookie + " " + protocol + " " + ch + " pending len " + ws.pending_children.length);
|
||||
|
||||
for (m = 0; m < ws.pending_children.length; m++) {
|
||||
if (ws.pending_children[m].cookie == cookie) {
|
||||
var newchild = ws.pending_children[m];
|
||||
|
||||
/* found it */
|
||||
ws.pending_children[m].channel_id = ch;
|
||||
/* add to active children array */
|
||||
ws.active_children.push(ws.pending_children[m]);
|
||||
/* remove from pending children array */
|
||||
ws.pending_children.splice(m, 1);
|
||||
|
||||
newchild.parent = ws;
|
||||
newchild.extensions = this.extensions;
|
||||
|
||||
newchild.onopen();
|
||||
|
||||
console.log("made active " + cookie);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case lws_meta_cmd.CLOSE_NOT:
|
||||
{
|
||||
var code = 0, str = "", ch = 0, m, le;
|
||||
var ba = new Uint8Array(msg.data);
|
||||
/*
|
||||
* BYTE: channel
|
||||
* BYTE: MSB status code
|
||||
* BYTE: LSB status code
|
||||
* BYTES: rest of message is close status string
|
||||
*/
|
||||
|
||||
ch = ba[n++];
|
||||
le = ba[n++] - 0x20;
|
||||
code = ba[n++] * 256;
|
||||
code += ba[n++];
|
||||
|
||||
while (le--)
|
||||
str += String.fromCharCode(ba[n++]);
|
||||
|
||||
console.log("channel id " + ch + " code " + code + " str " + str + " len " + str.length);
|
||||
|
||||
for (m = 0; m < this.myparent.active_children.length; m++)
|
||||
if (this.myparent.active_children[m].channel_id == ch) {
|
||||
var child = this.myparent.active_children[m];
|
||||
var ms = new CloseEvent("close", { code:code, reason:str } );
|
||||
|
||||
/* reply with close ack */
|
||||
this.send(msg.data);
|
||||
|
||||
if (child.onclose)
|
||||
child.onclose(ms);
|
||||
|
||||
this.myparent.active_children.splice(m, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
} // switch
|
||||
}
|
||||
} else {
|
||||
if (msg.data.charCodeAt(0) == lws_meta_cmd.WRITE ) {
|
||||
var ch = msg.data.charCodeAt(1), m, ms;
|
||||
var ws = this.myparent, ms;
|
||||
|
||||
for (m = 0; m < ws.active_children.length; m++) {
|
||||
if (ws.active_children[m].channel_id == ch) {
|
||||
ms = new MessageEvent("WebSocket", { data: msg.data.substr(2, msg.data.length - 2) } );
|
||||
if (ws.active_children[m].onmessage)
|
||||
ws.active_children[m].onmessage(ms);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.real.onclose = function() {
|
||||
var ws = this.myparent, m;
|
||||
for (m = 0; m < ws.active_children.length; m++) {
|
||||
var child = ws.active_children[m];
|
||||
var ms = new CloseEvent("close", { code:1000, reason:"parent closed" } );
|
||||
|
||||
if (child.onclose)
|
||||
child.onclose(ms);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* make a child connection using existing lws_meta real ws connection */
|
||||
lws_meta_ws.prototype.new_ws = function(suburl, protocol)
|
||||
{
|
||||
var ch = new lws_meta_ws_child();
|
||||
|
||||
ch.suburl = suburl;
|
||||
ch.subprotocol = protocol;
|
||||
ch.cookie = "C" + this.ordinal++;
|
||||
|
||||
this.pending_children.push(ch);
|
||||
|
||||
if (this.real.readyState == 1)
|
||||
this.real.onopen();
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* end of lws-meta helpers
|
||||
*/
|
||||
|
||||
function lws_san(s)
|
||||
{
|
||||
|
|
|
@ -536,7 +536,8 @@ int main(int argc, char **argv)
|
|||
|
||||
/* 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"
|
||||
"%lu packets transmitted, %lu received, "
|
||||
"%lu%% packet loss, time %ldms\n"
|
||||
|
|
|
@ -524,7 +524,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|||
}
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
if (pss->reason_bf & 2) {
|
||||
if (pss->reason_bf & LWS_CB_REASON_AUX_BF__PROXY) {
|
||||
char *px = 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);
|
||||
if (!wsi1)
|
||||
break;
|
||||
|
@ -674,7 +674,7 @@ bail:
|
|||
if (!lws_get_parent(wsi))
|
||||
break;
|
||||
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));
|
||||
break;
|
||||
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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
|
||||
* Universal Public Domain Dedication.
|
||||
|
@ -34,6 +34,11 @@ char *resource_path = LOCAL_RESOURCE_PATH;
|
|||
char crl_path[1024] = "";
|
||||
#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 */
|
||||
|
||||
void test_server_lock(int care)
|
||||
|
@ -59,60 +64,53 @@ void test_server_unlock(int care)
|
|||
*/
|
||||
|
||||
enum demo_protocols {
|
||||
/* always first */
|
||||
PROTOCOL_HTTP = 0,
|
||||
/* always first */
|
||||
PROTOCOL_HTTP = 0,
|
||||
|
||||
PROTOCOL_DUMB_INCREMENT,
|
||||
PROTOCOL_LWS_MIRROR,
|
||||
PROTOCOL_DUMB_INCREMENT,
|
||||
PROTOCOL_LWS_MIRROR,
|
||||
PROTOCOL_LWS_META,
|
||||
|
||||
/* always last */
|
||||
DEMO_PROTOCOL_COUNT
|
||||
/* always last */
|
||||
DEMO_PROTOCOL_COUNT
|
||||
};
|
||||
|
||||
/* list of supported protocols and callbacks */
|
||||
|
||||
static struct lws_protocols protocols[] = {
|
||||
/* first protocol must always be HTTP handler */
|
||||
/* first protocol must always be HTTP handler */
|
||||
|
||||
{
|
||||
"http-only", /* name */
|
||||
callback_http, /* callback */
|
||||
sizeof (struct per_session_data__http), /* per_session_data_size */
|
||||
0, /* max frame size / rx buffer */
|
||||
},
|
||||
{
|
||||
"dumb-increment-protocol",
|
||||
callback_dumb_increment,
|
||||
sizeof(struct per_session_data__dumb_increment),
|
||||
10,
|
||||
},
|
||||
{
|
||||
"lws-mirror-protocol",
|
||||
callback_lws_mirror,
|
||||
sizeof(struct per_session_data__lws_mirror),
|
||||
128,
|
||||
},
|
||||
{
|
||||
"lws-status",
|
||||
callback_lws_status,
|
||||
sizeof(struct per_session_data__lws_status),
|
||||
128,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
{
|
||||
"http-only", /* name */
|
||||
callback_http, /* callback */
|
||||
sizeof (struct per_session_data__http), /* per_session_data_size */
|
||||
0, /* max frame size / rx buffer */
|
||||
},
|
||||
{
|
||||
"dumb-increment-protocol",
|
||||
callback_dumb_increment,
|
||||
sizeof(struct per_session_data__dumb_increment),
|
||||
10,
|
||||
},
|
||||
|
||||
LWS_PLUGIN_PROTOCOL_MIRROR,
|
||||
LWS_PLUGIN_PROTOCOL_LWS_STATUS,
|
||||
LWS_PLUGIN_PROTOCOL_LWS_META,
|
||||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
static const struct lws_extension exts[] = {
|
||||
{
|
||||
"permessage-deflate",
|
||||
lws_extension_callback_pm_deflate,
|
||||
"permessage-deflate; client_no_context_takeover; client_max_window_bits"
|
||||
},
|
||||
{
|
||||
"deflate-frame",
|
||||
lws_extension_callback_pm_deflate,
|
||||
"deflate_frame"
|
||||
},
|
||||
{ NULL, NULL, NULL /* terminator */ }
|
||||
{
|
||||
"permessage-deflate",
|
||||
lws_extension_callback_pm_deflate,
|
||||
"permessage-deflate; client_no_context_takeover; client_max_window_bits"
|
||||
},
|
||||
{
|
||||
"deflate-frame",
|
||||
lws_extension_callback_pm_deflate,
|
||||
"deflate_frame"
|
||||
},
|
||||
{ NULL, NULL, NULL /* terminator */ }
|
||||
};
|
||||
|
||||
/* 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
|
||||
test_server_fops_open(const struct lws_plat_file_ops *fops,
|
||||
const char *vfs_path, const char *vpath,
|
||||
lws_fop_flags_t *flags)
|
||||
const char *vfs_path, const char *vpath,
|
||||
lws_fop_flags_t *flags)
|
||||
{
|
||||
lws_fop_fd_t n;
|
||||
lws_fop_fd_t n;
|
||||
|
||||
/* call through to original platform implementation */
|
||||
n = fops_plat.open(fops, vfs_path, vpath, flags);
|
||||
/* call through to original platform implementation */
|
||||
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)
|
||||
{
|
||||
lwsl_notice("Signal caught, exiting...\n");
|
||||
force_exit = 1;
|
||||
if (events & EV_SIGNAL) {
|
||||
struct event_base *event_base_loop = event_get_base((struct event *) ctx);
|
||||
event_base_loopbreak(event_base_loop);
|
||||
}
|
||||
struct event_base *event_base_loop = ctx;
|
||||
|
||||
lwsl_notice("Signal caught, exiting...\n");
|
||||
force_exit = 1;
|
||||
if (events & EV_SIGNAL)
|
||||
event_base_loopbreak(event_base_loop);
|
||||
}
|
||||
|
||||
static void
|
||||
ev_timeout_cb (evutil_socket_t sock_fd, short events, void *ctx)
|
||||
{
|
||||
lws_callback_on_writable_all_protocol(context,
|
||||
&protocols[PROTOCOL_DUMB_INCREMENT]);
|
||||
lws_callback_on_writable_all_protocol(context,
|
||||
&protocols[PROTOCOL_DUMB_INCREMENT]);
|
||||
}
|
||||
|
||||
static struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "debug", required_argument, NULL, 'd' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "ssl", no_argument, NULL, 's' },
|
||||
{ "allow-non-ssl", no_argument, NULL, 'a' },
|
||||
{ "interface", required_argument, NULL, 'i' },
|
||||
{ "closetest", no_argument, NULL, 'c' },
|
||||
{ "libevent", no_argument, NULL, 'e' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "debug", required_argument, NULL, 'd' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "ssl", no_argument, NULL, 's' },
|
||||
{ "allow-non-ssl", no_argument, NULL, 'a' },
|
||||
{ "interface", required_argument, NULL, 'i' },
|
||||
{ "closetest", no_argument, NULL, 'c' },
|
||||
{ "libevent", no_argument, NULL, 'e' },
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
{ "daemonize", no_argument, NULL, 'D' },
|
||||
{ "daemonize", no_argument, NULL, 'D' },
|
||||
#endif
|
||||
{ "resource_path", required_argument, NULL, 'r' },
|
||||
{ NULL, 0, 0, 0 }
|
||||
{ "resource_path", required_argument, NULL, 'r' },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int sigs[] = { SIGINT, SIGKILL, SIGTERM, SIGSEGV, SIGFPE };
|
||||
struct event *signals[ARRAY_SIZE(sigs)];
|
||||
struct event_base *event_base_loop = event_base_new();
|
||||
struct lws_context_creation_info info;
|
||||
char interface_name[128] = "";
|
||||
const char *iface = NULL;
|
||||
struct event *timeout_watcher;
|
||||
char cert_path[1024];
|
||||
char key_path[1024];
|
||||
int use_ssl = 0;
|
||||
int opts = 0;
|
||||
int n = 0;
|
||||
int sigs[] = { SIGINT, SIGKILL, SIGTERM, SIGSEGV, SIGFPE };
|
||||
struct event *signals[ARRAY_SIZE(sigs)];
|
||||
struct event_base *event_base_loop = event_base_new();
|
||||
struct lws_context_creation_info info;
|
||||
char interface_name[128] = "";
|
||||
const char *iface = NULL;
|
||||
struct event *timeout_watcher;
|
||||
char cert_path[1024];
|
||||
char key_path[1024];
|
||||
int use_ssl = 0;
|
||||
int opts = 0;
|
||||
int n = 0;
|
||||
#ifndef _WIN32
|
||||
int syslog_options = LOG_PID | LOG_PERROR;
|
||||
int syslog_options = LOG_PID | LOG_PERROR;
|
||||
#endif
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
int daemonize = 0;
|
||||
int daemonize = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* take care to zero down the info struct, he contains random garbaage
|
||||
* from the stack otherwise
|
||||
*/
|
||||
memset(&info, 0, sizeof info);
|
||||
info.port = 7681;
|
||||
/*
|
||||
* take care to zero down the info struct, he contains random garbaage
|
||||
* from the stack otherwise
|
||||
*/
|
||||
memset(&info, 0, sizeof info);
|
||||
info.port = 7681;
|
||||
|
||||
while (n >= 0) {
|
||||
n = getopt_long(argc, argv, "eci:hsap:d:Dr:", options, NULL);
|
||||
if (n < 0)
|
||||
continue;
|
||||
switch (n) {
|
||||
case 'e':
|
||||
opts |= LWS_SERVER_OPTION_LIBEVENT;
|
||||
break;
|
||||
while (n >= 0) {
|
||||
n = getopt_long(argc, argv, "eci:hsap:d:Dr:", options, NULL);
|
||||
if (n < 0)
|
||||
continue;
|
||||
switch (n) {
|
||||
case 'e':
|
||||
opts |= LWS_SERVER_OPTION_LIBEVENT;
|
||||
break;
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
case 'D':
|
||||
daemonize = 1;
|
||||
#ifndef _WIN32
|
||||
syslog_options &= ~LOG_PERROR;
|
||||
#endif
|
||||
break;
|
||||
case 'D':
|
||||
daemonize = 1;
|
||||
#ifndef _WIN32
|
||||
syslog_options &= ~LOG_PERROR;
|
||||
#endif
|
||||
case 'd':
|
||||
debug_level = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
use_ssl = 1;
|
||||
break;
|
||||
case 'a':
|
||||
opts |= LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT;
|
||||
break;
|
||||
case 'p':
|
||||
info.port = atoi(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
strncpy(interface_name, optarg, sizeof interface_name);
|
||||
interface_name[(sizeof interface_name) - 1] = '\0';
|
||||
iface = interface_name;
|
||||
break;
|
||||
case 'c':
|
||||
close_testing = 1;
|
||||
fprintf(stderr, " Close testing mode -- closes on "
|
||||
"client after 50 dumb increments"
|
||||
"and suppresses lws_mirror spam\n");
|
||||
break;
|
||||
case 'r':
|
||||
resource_path = optarg;
|
||||
printf("Setting resource path to \"%s\"\n", resource_path);
|
||||
break;
|
||||
case 'h':
|
||||
fprintf(stderr, "Usage: test-server "
|
||||
"[--port=<p>] [--ssl] "
|
||||
"[-d <log bitfield>] "
|
||||
"[--resource_path <path>]\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 'd':
|
||||
debug_level = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
use_ssl = 1;
|
||||
break;
|
||||
case 'a':
|
||||
opts |= LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT;
|
||||
break;
|
||||
case 'p':
|
||||
info.port = atoi(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
strncpy(interface_name, optarg, sizeof interface_name);
|
||||
interface_name[(sizeof interface_name) - 1] = '\0';
|
||||
iface = interface_name;
|
||||
break;
|
||||
case 'c':
|
||||
close_testing = 1;
|
||||
fprintf(stderr, " Close testing mode -- closes on "
|
||||
"client after 50 dumb increments"
|
||||
"and suppresses lws_mirror spam\n");
|
||||
break;
|
||||
case 'r':
|
||||
resource_path = optarg;
|
||||
printf("Setting resource path to \"%s\"\n", resource_path);
|
||||
break;
|
||||
case 'h':
|
||||
fprintf(stderr, "Usage: test-server "
|
||||
"[--port=<p>] [--ssl] "
|
||||
"[-d <log bitfield>] "
|
||||
"[--resource_path <path>]\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(LWS_NO_DAEMONIZE) && !defined(WIN32)
|
||||
/*
|
||||
* normally lock path would be /var/lock/lwsts or similar, to
|
||||
* simplify getting started without having to take care about
|
||||
* permissions or running as root, set to /tmp/.lwsts-lock
|
||||
*/
|
||||
if (daemonize && lws_daemonize("/tmp/.lwsts-lock")) {
|
||||
fprintf(stderr, "Failed to daemonize\n");
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* normally lock path would be /var/lock/lwsts or similar, to
|
||||
* simplify getting started without having to take care about
|
||||
* permissions or running as root, set to /tmp/.lwsts-lock
|
||||
*/
|
||||
if (daemonize && lws_daemonize("/tmp/.lwsts-lock")) {
|
||||
fprintf(stderr, "Failed to daemonize\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(sigs); n++) {
|
||||
signals[n] = evsignal_new(event_base_loop, sigs[n], signal_cb, event_self_cbarg());
|
||||
evsignal_add(signals[n], NULL);
|
||||
}
|
||||
for (n = 0; n < ARRAY_SIZE(sigs); n++) {
|
||||
signals[n] = evsignal_new(event_base_loop, sigs[n], signal_cb, event_base_loop);
|
||||
|
||||
evsignal_add(signals[n], NULL);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
/* we will only try to log things according to our debug_level */
|
||||
setlogmask(LOG_UPTO (LOG_DEBUG));
|
||||
openlog("lwsts", syslog_options, LOG_DAEMON);
|
||||
/* we will only try to log things according to our debug_level */
|
||||
setlogmask(LOG_UPTO (LOG_DEBUG));
|
||||
openlog("lwsts", syslog_options, LOG_DAEMON);
|
||||
#endif
|
||||
|
||||
/* tell the library what debug level to emit and to send it to syslog */
|
||||
lws_set_log_level(debug_level, lwsl_emit_syslog);
|
||||
/* tell the library what debug level to emit and to send it to syslog */
|
||||
lws_set_log_level(debug_level, lwsl_emit_syslog);
|
||||
|
||||
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("libwebsockets test server libevent - license LGPL2.1+SLE\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.protocols = protocols;
|
||||
info.extensions = exts;
|
||||
info.iface = iface;
|
||||
info.protocols = protocols;
|
||||
info.extensions = exts;
|
||||
|
||||
info.ssl_cert_filepath = NULL;
|
||||
info.ssl_private_key_filepath = NULL;
|
||||
info.ssl_cert_filepath = NULL;
|
||||
info.ssl_private_key_filepath = NULL;
|
||||
|
||||
if (use_ssl) {
|
||||
if (strlen(resource_path) > sizeof(cert_path) - 32) {
|
||||
lwsl_err("resource path too long\n");
|
||||
return -1;
|
||||
}
|
||||
sprintf(cert_path, "%s/libwebsockets-test-server.pem",
|
||||
resource_path);
|
||||
if (strlen(resource_path) > sizeof(key_path) - 32) {
|
||||
lwsl_err("resource path too long\n");
|
||||
return -1;
|
||||
}
|
||||
sprintf(key_path, "%s/libwebsockets-test-server.key.pem",
|
||||
resource_path);
|
||||
if (use_ssl) {
|
||||
if (strlen(resource_path) > sizeof(cert_path) - 32) {
|
||||
lwsl_err("resource path too long\n");
|
||||
return -1;
|
||||
}
|
||||
sprintf(cert_path, "%s/libwebsockets-test-server.pem",
|
||||
resource_path);
|
||||
if (strlen(resource_path) > sizeof(key_path) - 32) {
|
||||
lwsl_err("resource path too long\n");
|
||||
return -1;
|
||||
}
|
||||
sprintf(key_path, "%s/libwebsockets-test-server.key.pem",
|
||||
resource_path);
|
||||
|
||||
info.ssl_cert_filepath = cert_path;
|
||||
info.ssl_private_key_filepath = key_path;
|
||||
info.ssl_cert_filepath = cert_path;
|
||||
info.ssl_private_key_filepath = key_path;
|
||||
|
||||
opts |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
}
|
||||
info.gid = -1;
|
||||
info.uid = -1;
|
||||
info.max_http_header_pool = 1;
|
||||
info.options = opts | LWS_SERVER_OPTION_LIBEVENT;
|
||||
opts |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||
}
|
||||
info.gid = -1;
|
||||
info.uid = -1;
|
||||
info.max_http_header_pool = 1;
|
||||
info.options = opts | LWS_SERVER_OPTION_LIBEVENT;
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (context == NULL) {
|
||||
lwsl_err("libwebsocket init failed\n");
|
||||
return -1;
|
||||
}
|
||||
context = lws_create_context(&info);
|
||||
if (context == NULL) {
|
||||
lwsl_err("libwebsocket init failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* compressed files without decompressing the whole archive)
|
||||
*/
|
||||
/* stash original platform fops */
|
||||
fops_plat = *(lws_get_fops(context));
|
||||
/* override the active fops */
|
||||
lws_get_fops(context)->open = test_server_fops_open;
|
||||
/*
|
||||
* 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
|
||||
* compressed files without decompressing the whole archive)
|
||||
*/
|
||||
/* stash original platform fops */
|
||||
fops_plat = *(lws_get_fops(context));
|
||||
/* override the active fops */
|
||||
lws_get_fops(context)->open = test_server_fops_open;
|
||||
|
||||
// Don't use the default Signal Event Watcher & Handler
|
||||
lws_event_sigint_cfg(context, 0, NULL);
|
||||
// Initialize the LWS with libevent loop
|
||||
lws_event_initloop(context, event_base_loop, 0);
|
||||
// Don't use the default Signal Event Watcher & Handler
|
||||
lws_event_sigint_cfg(context, 0, NULL);
|
||||
// Initialize the LWS with libevent loop
|
||||
lws_event_initloop(context, event_base_loop, 0);
|
||||
|
||||
timeout_watcher = evtimer_new(event_base_loop, ev_timeout_cb, NULL);
|
||||
struct timeval tv = {0, 50000};
|
||||
evtimer_add(timeout_watcher, &tv);
|
||||
event_base_dispatch(event_base_loop);
|
||||
timeout_watcher = event_new(event_base_loop, -1, EV_PERSIST, ev_timeout_cb, NULL);
|
||||
struct timeval tv = {0, 50000};
|
||||
evtimer_add(timeout_watcher, &tv);
|
||||
event_base_dispatch(event_base_loop);
|
||||
|
||||
lws_context_destroy(context);
|
||||
lwsl_notice("libwebsockets-test-server exited cleanly\n");
|
||||
lws_context_destroy(context);
|
||||
lwsl_notice("libwebsockets-test-server exited cleanly\n");
|
||||
|
||||
#ifndef _WIN32
|
||||
closelog();
|
||||
closelog();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ void test_server_unlock(int care)
|
|||
#include "../plugins/protocol_dumb_increment.c"
|
||||
#include "../plugins/protocol_lws_mirror.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
|
||||
|
@ -73,6 +74,7 @@ enum demo_protocols {
|
|||
PROTOCOL_DUMB_INCREMENT,
|
||||
PROTOCOL_LWS_MIRROR,
|
||||
PROTOCOL_LWS_STATUS,
|
||||
PROTOCOL_LWS_META,
|
||||
|
||||
/* always last */
|
||||
DEMO_PROTOCOL_COUNT
|
||||
|
@ -92,6 +94,7 @@ static struct lws_protocols protocols[] = {
|
|||
LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT,
|
||||
LWS_PLUGIN_PROTOCOL_MIRROR,
|
||||
LWS_PLUGIN_PROTOCOL_LWS_STATUS,
|
||||
LWS_PLUGIN_PROTOCOL_LWS_META,
|
||||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
|
@ -456,6 +459,9 @@ int main(int argc, char **argv)
|
|||
lwsl_notice("uv loop close rc %s\n",
|
||||
e ? uv_strerror(e) : "ok");
|
||||
|
||||
/* PHASE 4: finalize context destruction */
|
||||
|
||||
lws_context_destroy2(context);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
|
|
@ -226,8 +226,15 @@ static const struct lws_protocol_vhost_options pvo_opt4 = {
|
|||
* linked-list. We can also give the plugin per-vhost options here.
|
||||
*/
|
||||
|
||||
static const struct lws_protocol_vhost_options pvo_4 = {
|
||||
static const struct lws_protocol_vhost_options pvo_5 = {
|
||||
NULL,
|
||||
NULL,
|
||||
"lws-meta",
|
||||
"" /* ignored, just matches the protocol name above */
|
||||
};
|
||||
|
||||
static const struct lws_protocol_vhost_options pvo_4 = {
|
||||
&pvo_5,
|
||||
&pvo_opt4, /* set us as the protocol who gets raw connections */
|
||||
"protocol-lws-raw-test",
|
||||
"" /* ignored, just matches the protocol name above */
|
||||
|
|
|
@ -68,6 +68,7 @@ char crl_path[1024] = "";
|
|||
#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 */
|
||||
|
||||
|
@ -104,6 +105,8 @@ enum demo_protocols {
|
|||
PROTOCOL_LWS_MIRROR,
|
||||
PROTOCOL_LWS_STATUS,
|
||||
|
||||
PROTOCOL_LWS_META,
|
||||
|
||||
/* always last */
|
||||
DEMO_PROTOCOL_COUNT
|
||||
};
|
||||
|
@ -130,6 +133,8 @@ static struct lws_protocols protocols[] = {
|
|||
},
|
||||
LWS_PLUGIN_PROTOCOL_MIRROR,
|
||||
LWS_PLUGIN_PROTOCOL_LWS_STATUS,
|
||||
|
||||
LWS_PLUGIN_PROTOCOL_LWS_META,
|
||||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
|
|
|
@ -533,21 +533,31 @@ if (params.mirror)
|
|||
mirror_name = params.mirror;
|
||||
|
||||
console.log(mirror_name);
|
||||
|
||||
|
||||
function new_ws(urlpath, protocol)
|
||||
{
|
||||
if (typeof MozWebSocket != "undefined")
|
||||
return new MozWebSocket(urlpath, protocol);
|
||||
/*
|
||||
* if using lws-meta to carry the other ws connections, declare the
|
||||
* parent connection object and start its connection to the server.
|
||||
*
|
||||
* These helpers are defined in lws-common.js
|
||||
*/
|
||||
|
||||
return new WebSocket(get_appropriate_ws_url(urlpath), protocol);
|
||||
}
|
||||
|
||||
var lws_meta = new lws_meta_ws();
|
||||
lws_meta.new_parent(get_appropriate_ws_url("?mirror=" + mirror_name));
|
||||
|
||||
|
||||
document.getElementById("number").textContent = get_appropriate_ws_url(mirror_name);
|
||||
|
||||
/* dumb increment protocol */
|
||||
|
||||
/*
|
||||
* to connect via an lws-meta connection, start the connection using
|
||||
* lws_meta.new_ws(). To connect by independent connection, start
|
||||
* the connection using just new_ws()
|
||||
*/
|
||||
|
||||
var socket_di = new_ws("", "dumb-increment-protocol");
|
||||
var socket_di = lws_meta.new_ws("", "dumb-increment-protocol");
|
||||
|
||||
try {
|
||||
socket_di.onopen = function() {
|
||||
|
@ -571,8 +581,8 @@ document.getElementById("number").textContent = get_appropriate_ws_url(mirror_na
|
|||
|
||||
var socket_status, jso, s;
|
||||
|
||||
socket_status = new_ws(get_appropriate_ws_url(""), "lws-status");
|
||||
|
||||
socket_status = lws_meta.new_ws(get_appropriate_ws_url(""), "lws-status");
|
||||
|
||||
try {
|
||||
socket_status.onopen = function() {
|
||||
|
@ -585,6 +595,8 @@ document.getElementById("number").textContent = get_appropriate_ws_url(mirror_na
|
|||
socket_status.onmessage =function got_packet(msg) {
|
||||
var s;
|
||||
|
||||
console.log(msg.data);
|
||||
|
||||
jso = JSON.parse(msg.data);
|
||||
|
||||
document.getElementById("servinfo").innerHTML =
|
||||
|
@ -637,7 +649,9 @@ var socket_ot;
|
|||
|
||||
function ot_open() {
|
||||
|
||||
socket_ot = new_ws(get_appropriate_ws_url(""), "dumb-increment-protocol");
|
||||
socket_ot = lws_meta.new_ws(get_appropriate_ws_url(""), "dumb-increment-protocol");
|
||||
|
||||
console.log("ot_open");
|
||||
|
||||
try {
|
||||
socket_ot.onopen = function() {
|
||||
|
@ -646,6 +660,7 @@ function ot_open() {
|
|||
document.getElementById("ot_open_btn").disabled = true;
|
||||
document.getElementById("ot_close_btn").disabled = false;
|
||||
document.getElementById("ot_req_close_btn").disabled = false;
|
||||
console.log("ot_open.onopen");
|
||||
}
|
||||
|
||||
socket_ot.onclose = function(e){
|
||||
|
@ -680,7 +695,7 @@ function ot_req_close() {
|
|||
var socket_lm;
|
||||
var color = "#000000";
|
||||
|
||||
socket_lm = new_ws(get_appropriate_ws_url("?mirror=" + mirror_name),
|
||||
socket_lm = lws_meta.new_ws(get_appropriate_ws_url("?mirror=" + mirror_name),
|
||||
"lws-mirror-protocol");
|
||||
|
||||
try {
|
||||
|
|
Loading…
Add table
Reference in a new issue