Compare commits
87 commits
master
...
v2.0-stabl
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c47fda7119 | ||
![]() |
ad2dac0659 | ||
![]() |
7bc6f5699c | ||
![]() |
f9e16eacd9 | ||
![]() |
eb76310c52 | ||
![]() |
7270aebadf | ||
![]() |
2ee30ebdf1 | ||
![]() |
c8b8dc8c07 | ||
![]() |
eefcaa762e | ||
![]() |
10eacf2873 | ||
![]() |
15b35bcc63 | ||
![]() |
f5f9196936 | ||
![]() |
27d650b89b | ||
![]() |
647fa47f25 | ||
![]() |
a310c13bf0 | ||
![]() |
bc10edb359 | ||
![]() |
b75680a15f | ||
![]() |
dff4f2613d | ||
![]() |
65cefdf879 | ||
![]() |
ba5f80a00a | ||
![]() |
aba9ad0ea0 | ||
![]() |
b40c0b8f1c | ||
![]() |
a9db080b6c | ||
![]() |
67f2bfe4da | ||
![]() |
3213c56516 | ||
![]() |
7fc6515dc6 | ||
![]() |
f7dd9d027a | ||
![]() |
846a3caf80 | ||
![]() |
0a0377b143 | ||
![]() |
01c47d0622 | ||
![]() |
0af47a0b8d | ||
![]() |
ab9c2f329c | ||
![]() |
3d48ce8f09 | ||
![]() |
a2241384e7 | ||
![]() |
5a247a57d2 | ||
![]() |
1f02bd2e66 | ||
![]() |
d7fb6ad9cf | ||
![]() |
2aa6f1bccd | ||
![]() |
0f7e4dbd48 | ||
![]() |
6a75dca024 | ||
![]() |
b7473a354d | ||
![]() |
a86666cfe5 | ||
![]() |
4324ea598b | ||
![]() |
d4410f1d07 | ||
![]() |
f0789545e7 | ||
![]() |
7d45a746d6 | ||
![]() |
3382efe5d6 | ||
![]() |
c1e14e7f6c | ||
![]() |
27b7055ac6 | ||
![]() |
f6f2dfc7fd | ||
![]() |
e746a993d0 | ||
![]() |
5f0dc8f4e6 | ||
![]() |
b064fb5bc9 | ||
![]() |
15bb297fbb | ||
![]() |
83a79ec381 | ||
![]() |
9694e5194c | ||
![]() |
0f222cdc77 | ||
![]() |
62a8b0cb33 | ||
![]() |
73f859d9e7 | ||
![]() |
37320ced18 | ||
![]() |
3bd3a41e97 | ||
![]() |
bc3f77e977 | ||
![]() |
7d259d885a | ||
![]() |
9c0cc42707 | ||
![]() |
85213516d3 | ||
![]() |
f92ed9c7a7 | ||
![]() |
36699d6ecb | ||
![]() |
1cea325a42 | ||
![]() |
d5c43f4a6e | ||
![]() |
3baed037c9 | ||
![]() |
0b208559e0 | ||
![]() |
fc29185b9f | ||
![]() |
0daa1869b2 | ||
![]() |
b1150df2f5 | ||
![]() |
465e2660e3 | ||
![]() |
792713f2c1 | ||
![]() |
e36ce9b20e | ||
![]() |
7624a8b128 | ||
![]() |
179b3ed9ff | ||
![]() |
79b1519b01 | ||
![]() |
172c78a43a | ||
![]() |
e2bf142912 | ||
![]() |
bd462c0b46 | ||
![]() |
f0a16ce17b | ||
![]() |
2f9da92e48 | ||
![]() |
f522895234 | ||
![]() |
5f4890b7ff |
52 changed files with 1349 additions and 374 deletions
|
@ -23,7 +23,7 @@ language: generic
|
|||
install:
|
||||
- ./travis_install.sh
|
||||
script:
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then mkdir build && cd build && cmake $CMAKE_ARGS .. && cmake --build .; fi
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 -a "$TRAVIS_OS_NAME" = "osx" ]; then mkdir build && cd build && cmake -DOPENSSL_ROOT_DIR="/usr/local/opt/openssl" $CMAKE_ARGS .. && cmake --build .; else if [ "$COVERITY_SCAN_BRANCH" != 1 -a "$TRAVIS_OS_NAME" = "linux" ]; then mkdir build && cd build && cmake $CMAKE_ARGS .. && cmake --build . ; fi ; fi
|
||||
sudo: required
|
||||
dist: trusty
|
||||
addons:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
cmake_minimum_required(VERSION 2.8.9)
|
||||
|
||||
if(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type")
|
||||
|
@ -10,11 +10,11 @@ set(PACKAGE "libwebsockets")
|
|||
set(CPACK_PACKAGE_NAME "${PACKAGE}")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "2")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "0")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "0")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "3")
|
||||
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 "8")
|
||||
set(SOVERSION "8.1")
|
||||
set(CPACK_SOURCE_GENERATOR "TGZ")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
set(VERSION "${CPACK_PACKAGE_VERSION}")
|
||||
|
@ -97,6 +97,7 @@ option(LWS_WITH_LWSWS "Libwebsockets Webserver" OFF)
|
|||
option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions" OFF)
|
||||
option(LWS_WITH_ACCESS_LOG "Support generating Apache-compatible access logs" OFF)
|
||||
option(LWS_WITH_SERVER_STATUS "Support json + jscript server monitoring" OFF)
|
||||
option(LWS_STATIC_PIC "Build the static version of the library with position-independent code" OFF)
|
||||
|
||||
if (LWS_WITH_LWSWS)
|
||||
message(STATUS "LWS_WITH_LWSWS --> Enabling LWS_WITH_PLUGINS and LWS_WITH_LIBUV")
|
||||
|
@ -378,7 +379,7 @@ if (NOT LWS_HAVE_inline)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
# Put the libaries and binaries that get built into directories at the
|
||||
# Put the libraries and binaries that get built into directories at the
|
||||
# top of the build tree rather than in hard-to-find leaf directories.
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
|
||||
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
|
||||
|
@ -631,6 +632,9 @@ source_group("Sources" FILES ${SOURCES})
|
|||
set(LWS_LIBRARIES)
|
||||
|
||||
if (LWS_WITH_STATIC)
|
||||
if (LWS_STATIC_PIC)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
add_library(websockets STATIC
|
||||
${HDR_PRIVATE}
|
||||
${HDR_PUBLIC}
|
||||
|
@ -799,7 +803,6 @@ if (LWS_WITH_SSL)
|
|||
|
||||
include_directories("${OPENSSL_INCLUDE_DIRS}")
|
||||
list(APPEND LIB_LIST ${OPENSSL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
# older (0.98) Openssl lacks this
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
|
@ -808,6 +811,7 @@ if (LWS_WITH_SSL)
|
|||
if (LWS_SSL_SERVER_WITH_ECDH_CERT AND NOT LWS_HAVE_OPENSSL_ECDH_H)
|
||||
message(FATAL_ERROR "Missing openssl/ecdh.h, so cannot use LWS_SSL_SERVER_WITH_ECDH_CERT")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif(LWS_WITH_SSL)
|
||||
|
||||
|
@ -839,7 +843,7 @@ if (LWS_WITH_LIBUV)
|
|||
list(APPEND LIB_LIST ${LIBUV_LIBRARIES})
|
||||
endif()
|
||||
if (LWS_WITH_HTTP_PROXY)
|
||||
find_library(LIBHUBBUB_LIBRARIES NAMES libhubbub)
|
||||
find_library(LIBHUBBUB_LIBRARIES NAMES hubbub)
|
||||
list(APPEND LIB_LIST ${LIBHUBBUB_LIBRARIES} )
|
||||
endif()
|
||||
|
||||
|
@ -865,6 +869,7 @@ endforeach()
|
|||
set (temp ${CMAKE_REQUIRED_LIBRARIES})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST})
|
||||
CHECK_FUNCTION_EXISTS(SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param)
|
||||
CHECK_FUNCTION_EXISTS(X509_VERIFY_PARAM_set1_host LWS_HAVE_X509_VERIFY_PARAM_set1_host)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${temp})
|
||||
# Generate the lws_config.h that includes all the public compilation settings.
|
||||
configure_file(
|
||||
|
@ -1177,7 +1182,7 @@ if (NOT LWS_WITHOUT_TESTAPPS)
|
|||
set(PLUGIN_SRCS ${MAIN_SRC})
|
||||
|
||||
if (WIN32)
|
||||
list(APPEND PLUGIN_SRCSset_property
|
||||
list(APPEND PLUGIN_SRCS
|
||||
${WIN32_HELPERS_PATH}/getopt.c
|
||||
${WIN32_HELPERS_PATH}/getopt_long.c
|
||||
${WIN32_HELPERS_PATH}/gettimeofday.c
|
||||
|
@ -1493,6 +1498,8 @@ message(" LIBHUBBUB_LIBRARIES = ${LIBHUBBUB_LIBRARIES}")
|
|||
message(" PLUGINS = ${PLUGINS_LIST}")
|
||||
message(" LWS_WITH_ACCESS_LOG = ${LWS_WITH_ACCESS_LOG}")
|
||||
message(" LWS_WITH_SERVER_STATUS = ${LWS_WITH_SERVER_STATUS}")
|
||||
message(" LWS_STATIC_PIC = ${LWS_STATIC_PIC}")
|
||||
|
||||
message("---------------------------------------------------------------------")
|
||||
|
||||
# These will be available to parent projects including libwebsockets using add_subdirectory()
|
||||
|
|
|
@ -225,11 +225,11 @@ Setting compile options
|
|||
-----------------------
|
||||
|
||||
To set compile time flags you can either use one of the CMake gui applications
|
||||
or do it via command line.
|
||||
or do it via the command line.
|
||||
|
||||
Command line
|
||||
------------
|
||||
To list avaialable options (ommit the H if you don't want the help text):
|
||||
To list available options (omit the H if you don't want the help text):
|
||||
|
||||
cmake -LH ..
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ allow up to that many connections, minus whatever other file descriptors are
|
|||
in use by the user code.
|
||||
|
||||
If you want to restrict that allocation, or increase it, you can use ulimit or
|
||||
similar to change the avaiable number of file descriptors, and when restarted
|
||||
similar to change the available number of file descriptors, and when restarted
|
||||
**libwebsockets** will adapt accordingly.
|
||||
|
||||
|
||||
|
@ -167,6 +167,14 @@ whereas info is ignored by default.
|
|||
External Polling Loop support
|
||||
-----------------------------
|
||||
|
||||
NOTE: You should use v2.1 or later (or master) for external polling loop
|
||||
support. After v2.0 was released a problem was found meaning some internal
|
||||
APIs needed to be exposed to deal with connections that need service even
|
||||
without any new network activity. For normal poll() and libuv/ev loops,
|
||||
lws takes care of this internally but external polling loop needs it doing
|
||||
externally. Since we can't change the API on a released version that
|
||||
means you need to use v2.1 or later for this feature to work properly.
|
||||
|
||||
**libwebsockets** maintains an internal `poll()` array for all of its
|
||||
sockets, but you can instead integrate the sockets into an
|
||||
external polling array. That's needed if **libwebsockets** will
|
||||
|
@ -497,6 +505,25 @@ There are some new members but mainly it's stuff you used to set at
|
|||
context creation time.
|
||||
|
||||
|
||||
How lws matches hostname or SNI to a vhost
|
||||
------------------------------------------
|
||||
|
||||
LWS first strips any trailing :port number.
|
||||
|
||||
Then it tries to find an exact name match for a vhost listening on the correct
|
||||
port, ie, if SNI or the Host: header provided abc.com:1234, it will match on a
|
||||
vhost named abc.com that is listening on port 1234.
|
||||
|
||||
If there is no exact match, lws will consider wildcard matches, for example
|
||||
if cats.abc.com:1234 is provided by the client by SNI or Host: header, it will
|
||||
accept a vhost "abc.com" listening on port 1234. If there was a better, exact,
|
||||
match, it will have been chosen in preference to this.
|
||||
|
||||
Connections with SSL will still have the client go on to check the
|
||||
certificate allows wildcards and error out if not.
|
||||
|
||||
|
||||
|
||||
Using lws v2 mounts on a vhost
|
||||
------------------------------
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ Vhosts can select which plugins they want to offer and give them per-vhost setti
|
|||
|
||||
```
|
||||
"ws-protocols": [{
|
||||
"warmcat,timezoom": {
|
||||
"warmcat-timezoom": {
|
||||
"status": "ok"
|
||||
}
|
||||
}]
|
||||
|
@ -157,6 +157,19 @@ The "x":"y" parameters like "status":"ok" are made available to the protocol dur
|
|||
LWS_CALLBACK_PROTOCOL_INIT (@in is a pointer to a linked list of struct lws_protocol_vhost_options
|
||||
containing the name and value pointers).
|
||||
|
||||
To indicate that a protocol should be used when no Protocol: header is sent
|
||||
by the client, you can use "default": "1"
|
||||
|
||||
```
|
||||
"ws-protocols": [{
|
||||
"warmcat-timezoom": {
|
||||
"status": "ok",
|
||||
"default": "1"
|
||||
}
|
||||
}]
|
||||
|
||||
```
|
||||
|
||||
|
||||
Other vhost options
|
||||
-------------------
|
||||
|
@ -175,6 +188,12 @@ Other vhost options
|
|||
|
||||
- "`access-log`": "filepath" sets where apache-compatible access logs will be written
|
||||
|
||||
- "`ciphers`": "<cipher list>" sets the allowed list of ciphers and key exchange protocols for the vhost. The default list is restricted to only those providing PFS (Perfect Forward Secrecy) on the author's Fedora system.
|
||||
|
||||
If you need to allow weaker ciphers,you can provide an alternative list here per-vhost.
|
||||
|
||||
- "`ecdh-curve`": "<curve name>" The default ecdh curve is "prime256v1", but you can override it here, per-vhost
|
||||
|
||||
|
||||
Mounts
|
||||
------
|
||||
|
@ -222,7 +241,7 @@ Note: currently only a fixed set of mimetypes are supported.
|
|||
Other mount options
|
||||
-------------------
|
||||
|
||||
1) When using a cgi:// protcol origin at a mountpoint, you may also give cgi environment variables specific to the mountpoint like this
|
||||
1) When using a cgi:// protocol origin at a mountpoint, you may also give cgi environment variables specific to the mountpoint like this
|
||||
|
||||
```
|
||||
{
|
||||
|
@ -256,6 +275,14 @@ options are given, the content is marked uncacheable.
|
|||
}
|
||||
|
||||
|
||||
4) You can also define a list of additional mimetypes per-mount
|
||||
|
||||
"extra-mimetypes": {
|
||||
".zip": "application/zip",
|
||||
".doc": "text/evil"
|
||||
}
|
||||
|
||||
|
||||
Plugins
|
||||
-------
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[](https://travis-ci.org/warmcat/libwebsockets)
|
||||
[](https://ci.appveyor.com/project/warmcat/libwebsockets)
|
||||
[](https://travis-ci.org/warmcat/libwebsockets)
|
||||
[](https://ci.appveyor.com/project/lws-team/libwebsockets)
|
||||
[](https://scan.coverity.com/projects/3576)
|
||||
|
||||
libwebsockets
|
||||
|
|
|
@ -84,7 +84,7 @@ The test client supports SSL too, use
|
|||
$ libwebsockets-test-client localhost --ssl -s
|
||||
```
|
||||
|
||||
the -s tells it to accept the default selfsigned cert from the server,
|
||||
the -s tells it to accept the default self-signed cert from the server,
|
||||
otherwise it will strictly fail the connection if there is no CA cert to
|
||||
validate the server's certificate.
|
||||
|
||||
|
@ -141,7 +141,7 @@ To test SSL/WSS client action, just run the client test with
|
|||
$ libwebsockets-test-client localhost --ssl
|
||||
```
|
||||
|
||||
By default the client test applet is set to accept selfsigned
|
||||
By default the client test applet is set to accept self-signed
|
||||
certificates used by the test server, this is indicated by the
|
||||
`use_ssl` var being set to `2`. Set it to `1` to reject any server
|
||||
certificate that it doesn't have a trusted CA cert for.
|
||||
|
@ -192,7 +192,7 @@ Before you can even use the PING opcode that is part of the
|
|||
standard, you must complete a handshake with a specified
|
||||
protocol. By default lws-mirror-protocol is used which is
|
||||
supported by the test server. But if you are using it on
|
||||
another server, you can specify the protcol to handshake with
|
||||
another server, you can specify the protocol to handshake with
|
||||
by `--protocol=protocolname`
|
||||
|
||||
|
||||
|
@ -350,7 +350,7 @@ Autobahn Test Notes
|
|||
-------------------
|
||||
|
||||
1) Autobahn tests the user code + lws implementation. So to get the same
|
||||
results, you need to follow test-echo.c in terms of user implmentation.
|
||||
results, you need to follow test-echo.c in terms of user implementation.
|
||||
|
||||
2) Some of the tests make no sense for Libwebsockets to support and we fail them.
|
||||
|
||||
|
|
15
appveyor.yml
15
appveyor.yml
|
@ -1,5 +1,8 @@
|
|||
environment:
|
||||
matrix:
|
||||
- LWS_METHOD: lwsws
|
||||
CMAKE_ARGS: -DLWS_WITH_LWSWS=1 -DLIBUV_INCLUDE_DIRS=C:\assets\libuv\include -DLIBUV_LIBRARIES=C:\assets\libuv\libuv.lib
|
||||
|
||||
- LWS_METHOD: default
|
||||
|
||||
- LWS_METHOD: noserver
|
||||
|
@ -14,10 +17,16 @@ environment:
|
|||
- LWS_METHOD: nossl
|
||||
CMAKE_ARGS: -DLWS_WITH_SSL=OFF
|
||||
install:
|
||||
- appveyor DownloadFile https://slproweb.com/download/Win32OpenSSL-1_0_2h.exe
|
||||
- appveyor DownloadFile https://libwebsockets.org:444/win-libuv.zip
|
||||
- mkdir c:\assets
|
||||
- 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
|
||||
- cinst -y nsis
|
||||
- SET PATH=C:\Program Files\NSIS\;C:\Program Files (x86)\NSIS\;%PATH%
|
||||
- appveyor DownloadFile https://libwebsockets.org:444/nsis-3.0rc1-setup.exe
|
||||
- cmd /c start /wait nsis-3.0rc1-setup.exe /S /D=C:\nsis
|
||||
- SET PATH=C:\Program Files\NSIS\;C:\Program Files (x86)\NSIS\;c:\nsis;%PATH%
|
||||
build:
|
||||
|
||||
build_script:
|
||||
|
|
97
changelog
97
changelog
|
@ -1,6 +1,103 @@
|
|||
Changelog
|
||||
---------
|
||||
|
||||
v2.0.3
|
||||
======
|
||||
|
||||
NB New api lws_snprintf() -> SONAME bump to 8.1
|
||||
|
||||
Fixes
|
||||
-----
|
||||
|
||||
1) Remove duplicate close in one error path
|
||||
|
||||
2) Build fix for ecdh and non-openssl
|
||||
|
||||
3) Client confirms server cert
|
||||
|
||||
4) SNI falls back to match wildcard DNS names (this is later checked against
|
||||
the cert for actual validity at SSL level)
|
||||
|
||||
5) Fix one error path on vhost adopt_socket where we are left on timeout list
|
||||
|
||||
6) lws_snprintf() - fix critical problem with snprintf not truncating buffer
|
||||
lengths (it truncated the buffer write) as (wrongly) expected
|
||||
|
||||
|
||||
v2.0.2
|
||||
======
|
||||
|
||||
Fixes
|
||||
-----
|
||||
|
||||
1) Fix possible pthread mutex leak
|
||||
|
||||
2) Make sure ACCESS_LOG can't touch freed area
|
||||
|
||||
3) extra options in lwsws conf for cipher list and ecdh curve
|
||||
|
||||
4) extra options in lwsws conf for extra mimetypes
|
||||
|
||||
5) fix default rxbuf trimming for output
|
||||
|
||||
6) lwsl_timestamp month number was off-by-one
|
||||
|
||||
7) fix daemonize.c
|
||||
|
||||
|
||||
v2.0.1
|
||||
======
|
||||
|
||||
Fixes
|
||||
-----
|
||||
|
||||
1) OpenSSL version tests not needed on LibreSSL and BoringSSL
|
||||
|
||||
2) Fix IPV6 build breakage
|
||||
|
||||
3) Some fixes for WinCE build
|
||||
|
||||
4) Additional canned mimetypes for mounts, the full list is
|
||||
|
||||
.ico image/x-icon
|
||||
.gif image/gif
|
||||
.js text/javascript
|
||||
.png image/png
|
||||
.jpg image/jpeg
|
||||
.gz application/gzip
|
||||
.JPG image/jpeg
|
||||
.html text/html
|
||||
.css text/css
|
||||
.txt text/plain
|
||||
.ttf application/x-font-ttf
|
||||
.woff application/font-woff
|
||||
.xml application/xml
|
||||
|
||||
5) Allow per-vhost setting of which protocol should get used
|
||||
when the protocol: header is not sent by the client
|
||||
|
||||
6) MINOR: user_space arg was mistakenly NULL on
|
||||
LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER
|
||||
|
||||
7) MINOR: treating recv() returning 0 as peer close destroyed throughput on ab
|
||||
tests, reverted
|
||||
|
||||
8) MINOR: %3d on URL part was always turned to _... this should only happen in
|
||||
?na%3dme=x part of the URL
|
||||
|
||||
9) MINOR: some malloc escaped check for NULL / OOM
|
||||
|
||||
10) MINOR: libuv cleanups and client connections can operate correctly with
|
||||
libuv
|
||||
|
||||
11) MINOR: POST used to hang up the connection when the body had all arrived.
|
||||
Change it so you can reply with a 200 directly rather than requiring a
|
||||
redirect
|
||||
|
||||
12) MINOR: API docs were a little behind the docs in the code
|
||||
|
||||
|
||||
|
||||
v2.0.0
|
||||
======
|
||||
|
||||
|
|
|
@ -17,6 +17,12 @@ lws_client_connect_2(struct lws *wsi)
|
|||
|
||||
lwsl_client("%s\n", __func__);
|
||||
|
||||
if (!wsi->u.hdr.ah) {
|
||||
|
||||
lwsl_err("ah was NULL at cc2\n");
|
||||
goto oom4;
|
||||
}
|
||||
|
||||
/* proxy? */
|
||||
|
||||
if (wsi->vhost->http_proxy_port) {
|
||||
|
@ -163,6 +169,7 @@ lws_client_connect_2(struct lws *wsi)
|
|||
wsi->mode = LWSCM_WSCL_WAITING_CONNECT;
|
||||
|
||||
lws_libev_accept(wsi, wsi->sock);
|
||||
lws_libuv_accept(wsi, wsi->sock);
|
||||
if (insert_wsi_socket_into_fds(context, wsi)) {
|
||||
compatible_close(wsi->sock);
|
||||
goto oom4;
|
||||
|
@ -206,7 +213,11 @@ lws_client_connect_2(struct lws *wsi)
|
|||
|| LWS_ERRNO == WSAEINVAL
|
||||
#endif
|
||||
) {
|
||||
lwsl_client("nonblocking connect retry\n");
|
||||
lwsl_client("nonblocking connect retry (errno = %d)\n",
|
||||
LWS_ERRNO);
|
||||
|
||||
if (lws_plat_check_connection_error(wsi))
|
||||
goto failed;
|
||||
|
||||
/*
|
||||
* must do specifically a POLLOUT poll to hear
|
||||
|
@ -271,6 +282,7 @@ lws_client_connect_2(struct lws *wsi)
|
|||
|
||||
wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE;
|
||||
pfd.fd = wsi->sock;
|
||||
pfd.events = LWS_POLLIN;
|
||||
pfd.revents = LWS_POLLIN;
|
||||
|
||||
n = lws_service_fd(context, &pfd);
|
||||
|
@ -283,8 +295,9 @@ lws_client_connect_2(struct lws *wsi)
|
|||
|
||||
oom4:
|
||||
/* we're closing, losing some rx is OK */
|
||||
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
|
||||
//lwsl_err("%d\n", wsi->mode);
|
||||
if (wsi->u.hdr.ah)
|
||||
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
|
||||
|
||||
if (wsi->mode == LWSCM_HTTP_CLIENT)
|
||||
wsi->vhost->protocols[0].callback(wsi,
|
||||
LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
|
||||
|
@ -364,7 +377,7 @@ html_parser_cb(const hubbub_token *token, void *pw)
|
|||
switch (token->type) {
|
||||
case HUBBUB_TOKEN_DOCTYPE:
|
||||
|
||||
p += snprintf(p, end - p, "<!DOCTYPE %.*s %s ",
|
||||
p += lws_snprintf(p, end - p, "<!DOCTYPE %.*s %s ",
|
||||
(int) token->data.doctype.name.len,
|
||||
token->data.doctype.name.ptr,
|
||||
token->data.doctype.force_quirks ?
|
||||
|
@ -373,20 +386,20 @@ html_parser_cb(const hubbub_token *token, void *pw)
|
|||
if (token->data.doctype.public_missing)
|
||||
printf("\tpublic: missing\n");
|
||||
else
|
||||
p += snprintf(p, end - p, "PUBLIC \"%.*s\"\n",
|
||||
p += lws_snprintf(p, end - p, "PUBLIC \"%.*s\"\n",
|
||||
(int) token->data.doctype.public_id.len,
|
||||
token->data.doctype.public_id.ptr);
|
||||
|
||||
if (token->data.doctype.system_missing)
|
||||
printf("\tsystem: missing\n");
|
||||
else
|
||||
p += snprintf(p, end - p, " \"%.*s\">\n",
|
||||
p += lws_snprintf(p, end - p, " \"%.*s\">\n",
|
||||
(int) token->data.doctype.system_id.len,
|
||||
token->data.doctype.system_id.ptr);
|
||||
|
||||
break;
|
||||
case HUBBUB_TOKEN_START_TAG:
|
||||
p += snprintf(p, end - p, "<%.*s", (int)token->data.tag.name.len,
|
||||
p += lws_snprintf(p, end - p, "<%.*s", (int)token->data.tag.name.len,
|
||||
token->data.tag.name.ptr);
|
||||
|
||||
/* (token->data.tag.self_closing) ?
|
||||
|
@ -406,23 +419,23 @@ html_parser_cb(const hubbub_token *token, void *pw)
|
|||
pp += r->from_len;
|
||||
plen -= r->from_len;
|
||||
}
|
||||
p += snprintf(p, end - p, " %.*s=\"%s/%.*s\"",
|
||||
p += lws_snprintf(p, end - p, " %.*s=\"%s/%.*s\"",
|
||||
(int) token->data.tag.attributes[i].name.len,
|
||||
token->data.tag.attributes[i].name.ptr,
|
||||
r->to, plen, pp);
|
||||
|
||||
} else
|
||||
|
||||
p += snprintf(p, end - p, " %.*s=\"%.*s\"",
|
||||
p += lws_snprintf(p, end - p, " %.*s=\"%.*s\"",
|
||||
(int) token->data.tag.attributes[i].name.len,
|
||||
token->data.tag.attributes[i].name.ptr,
|
||||
(int) token->data.tag.attributes[i].value.len,
|
||||
token->data.tag.attributes[i].value.ptr);
|
||||
}
|
||||
p += snprintf(p, end - p, ">\n");
|
||||
p += lws_snprintf(p, end - p, ">\n");
|
||||
break;
|
||||
case HUBBUB_TOKEN_END_TAG:
|
||||
p += snprintf(p, end - p, "</%.*s", (int) token->data.tag.name.len,
|
||||
p += lws_snprintf(p, end - p, "</%.*s", (int) token->data.tag.name.len,
|
||||
token->data.tag.name.ptr);
|
||||
/*
|
||||
(token->data.tag.self_closing) ?
|
||||
|
@ -431,25 +444,25 @@ html_parser_cb(const hubbub_token *token, void *pw)
|
|||
"attributes:" : "");
|
||||
*/
|
||||
for (i = 0; i < token->data.tag.n_attributes; i++) {
|
||||
p += snprintf(p, end - p, " %.*s='%.*s'\n",
|
||||
p += lws_snprintf(p, end - p, " %.*s='%.*s'\n",
|
||||
(int) token->data.tag.attributes[i].name.len,
|
||||
token->data.tag.attributes[i].name.ptr,
|
||||
(int) token->data.tag.attributes[i].value.len,
|
||||
token->data.tag.attributes[i].value.ptr);
|
||||
}
|
||||
p += snprintf(p, end - p, ">\n");
|
||||
p += lws_snprintf(p, end - p, ">\n");
|
||||
break;
|
||||
case HUBBUB_TOKEN_COMMENT:
|
||||
p += snprintf(p, end - p, "<!-- %.*s -->\n",
|
||||
p += lws_snprintf(p, end - p, "<!-- %.*s -->\n",
|
||||
(int) token->data.comment.len,
|
||||
token->data.comment.ptr);
|
||||
break;
|
||||
case HUBBUB_TOKEN_CHARACTER:
|
||||
p += snprintf(p, end - p, "%.*s", (int) token->data.character.len,
|
||||
p += lws_snprintf(p, end - p, "%.*s", (int) token->data.character.len,
|
||||
token->data.character.ptr);
|
||||
break;
|
||||
case HUBBUB_TOKEN_EOF:
|
||||
p += snprintf(p, end - p, "\n");
|
||||
p += lws_snprintf(p, end - p, "\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -475,6 +488,9 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
|
|||
struct lws *wsi;
|
||||
int v = SPEC_LATEST_SUPPORTED;
|
||||
|
||||
if (i->context->requested_kill)
|
||||
return NULL;
|
||||
|
||||
wsi = lws_zalloc(sizeof(struct lws));
|
||||
if (wsi == NULL)
|
||||
goto bail;
|
||||
|
@ -566,10 +582,10 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
|
|||
|
||||
/* if we went on the waiting list, no probs just return the wsi
|
||||
* when we get the ah, now or later, he will call
|
||||
* lws_client_connect_via_info2() below
|
||||
* lws_client_connect_via_info2() below.
|
||||
*/
|
||||
if (lws_header_table_attach(wsi, 0))
|
||||
lwsl_debug("%s: went on ah wait list\n", __func__);
|
||||
if (lws_header_table_attach(wsi, 0) < 0)
|
||||
return NULL;
|
||||
|
||||
if (i->parent_wsi) {
|
||||
lwsl_info("%s: created child %p of parent %p\n", __func__,
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
int lws_client_rx_sm(struct lws *wsi, unsigned char c)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
|
||||
int handled, n, m, rx_draining_ext = 0;
|
||||
unsigned short close_code;
|
||||
|
@ -31,21 +30,10 @@ int lws_client_rx_sm(struct lws *wsi, unsigned char c)
|
|||
unsigned char *pp;
|
||||
|
||||
if (wsi->u.ws.rx_draining_ext) {
|
||||
struct lws **w = &pt->rx_draining_ext_list;
|
||||
lwsl_ext("%s: RX EXT DRAINING: Removing from list\n", __func__, c);
|
||||
assert(!c);
|
||||
eff_buf.token = NULL;
|
||||
eff_buf.token_len = 0;
|
||||
wsi->u.ws.rx_draining_ext = 0;
|
||||
/* remove us from context draining ext list */
|
||||
while (*w) {
|
||||
if (*w == wsi) {
|
||||
*w = wsi->u.ws.rx_draining_ext_list;
|
||||
break;
|
||||
}
|
||||
w = &((*w)->u.ws.rx_draining_ext_list);
|
||||
}
|
||||
wsi->u.ws.rx_draining_ext_list = NULL;
|
||||
lws_remove_wsi_from_draining_ext_list(wsi);
|
||||
rx_draining_ext = 1;
|
||||
|
||||
goto drain_extension;
|
||||
|
@ -523,17 +511,16 @@ utf8_fail: lwsl_info("utf8 error\n");
|
|||
if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
|
||||
lwsl_info("Client doing pong callback\n");
|
||||
|
||||
if (n && eff_buf.token_len) {
|
||||
if (n && eff_buf.token_len)
|
||||
/* extension had more... main loop will come back
|
||||
* we want callback to be done with this set, if so,
|
||||
* because lws_is_final() hides it was final until the
|
||||
* last chunk
|
||||
*/
|
||||
wsi->u.ws.rx_draining_ext = 1;
|
||||
wsi->u.ws.rx_draining_ext_list = pt->rx_draining_ext_list;
|
||||
pt->rx_draining_ext_list = wsi;
|
||||
lwsl_ext("%s: RX EXT DRAINING: Adding to list\n", __func__);
|
||||
}
|
||||
lws_add_wsi_to_draining_ext_list(wsi);
|
||||
else
|
||||
lws_remove_wsi_from_draining_ext_list(wsi);
|
||||
|
||||
if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY ||
|
||||
wsi->state == LWSS_AWAITING_CLOSE_ACK)
|
||||
goto already_done;
|
||||
|
|
6
lib/client.c
Normal file → Executable file
6
lib/client.c
Normal file → Executable file
|
@ -148,8 +148,10 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi,
|
|||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
/* we can retry this... just cook the SSL BIO the first time */
|
||||
|
||||
if (wsi->use_ssl && !wsi->ssl)
|
||||
lws_ssl_client_bio_create(wsi);
|
||||
if (wsi->use_ssl && !wsi->ssl) {
|
||||
if (lws_ssl_client_bio_create(wsi))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wsi->use_ssl) {
|
||||
n = lws_ssl_client_connect1(wsi);
|
||||
|
|
|
@ -111,13 +111,15 @@ int
|
|||
lws_protocol_init(struct lws_context *context)
|
||||
{
|
||||
struct lws_vhost *vh = context->vhost_list;
|
||||
const struct lws_protocol_vhost_options *pvo;
|
||||
const struct lws_protocol_vhost_options *pvo, *pvo1;
|
||||
struct lws wsi;
|
||||
int n;
|
||||
|
||||
memset(&wsi, 0, sizeof(wsi));
|
||||
wsi.context = context;
|
||||
|
||||
lwsl_notice("%s\n", __func__);
|
||||
|
||||
while (vh) {
|
||||
wsi.vhost = vh;
|
||||
|
||||
|
@ -128,12 +130,32 @@ lws_protocol_init(struct lws_context *context)
|
|||
|
||||
pvo = lws_vhost_protocol_options(vh,
|
||||
vh->protocols[n].name);
|
||||
if (pvo)
|
||||
if (pvo) {
|
||||
/*
|
||||
* linked list of options specific to
|
||||
* vh + protocol
|
||||
*/
|
||||
pvo = pvo->options;
|
||||
pvo1 = pvo;
|
||||
pvo = pvo1->options;
|
||||
|
||||
while (pvo) {
|
||||
lwsl_notice(" vh %s prot %s opt %s\n",
|
||||
vh->name,
|
||||
vh->protocols[n].name,
|
||||
pvo->name);
|
||||
|
||||
if (!strcmp(pvo->name, "default")) {
|
||||
lwsl_notice("Setting default "
|
||||
"protocol for vh %s to %s\n",
|
||||
vh->name,
|
||||
vh->protocols[n].name);
|
||||
vh->default_protocol_index = n;
|
||||
}
|
||||
pvo = pvo->next;
|
||||
}
|
||||
|
||||
pvo = pvo1->options;
|
||||
}
|
||||
|
||||
/*
|
||||
* inform all the protocols that they are doing their one-time
|
||||
|
@ -351,11 +373,13 @@ lws_create_vhost(struct lws_context *context,
|
|||
info->log_filepath);
|
||||
goto bail;
|
||||
}
|
||||
#ifndef WIN32
|
||||
if (context->uid != -1)
|
||||
if (chown(info->log_filepath, context->uid,
|
||||
context->gid) == -1)
|
||||
lwsl_err("unable to chown log file %s\n",
|
||||
info->log_filepath);
|
||||
#endif
|
||||
} else
|
||||
vh->log_fd = LWS_INVALID_FILE;
|
||||
#endif
|
||||
|
@ -681,7 +705,7 @@ lws_context_destroy(struct lws_context *context)
|
|||
{
|
||||
const struct lws_protocols *protocol = NULL;
|
||||
struct lws_context_per_thread *pt;
|
||||
struct lws_vhost *vh, *vh1;
|
||||
struct lws_vhost *vh = NULL, *vh1;
|
||||
struct lws wsi;
|
||||
int n, m;
|
||||
|
||||
|
@ -714,6 +738,7 @@ lws_context_destroy(struct lws_context *context)
|
|||
/* no protocol close */);
|
||||
n--;
|
||||
}
|
||||
lws_pt_mutex_destroy(pt);
|
||||
}
|
||||
/*
|
||||
* give all extensions a chance to clean up any per-context
|
||||
|
@ -732,7 +757,8 @@ lws_context_destroy(struct lws_context *context)
|
|||
*
|
||||
* We can't free things until after the event loop shuts down.
|
||||
*/
|
||||
vh = context->vhost_list;
|
||||
if (context->protocol_init_done)
|
||||
vh = context->vhost_list;
|
||||
while (vh) {
|
||||
wsi.vhost = vh;
|
||||
protocol = vh->protocols;
|
||||
|
|
|
@ -142,9 +142,20 @@ lws_daemonize(const char *_lock_path)
|
|||
exit(9);
|
||||
}
|
||||
|
||||
/* If we got a good PID, then we can exit the parent process. */
|
||||
if (pid_daemon > 0)
|
||||
exit(0);
|
||||
/* If we got a good PID, then we can exit the parent process. */
|
||||
if (pid_daemon > 0) {
|
||||
|
||||
/*
|
||||
* Wait for confirmation signal from the child via
|
||||
* SIGCHILD / USR1, or for two seconds to elapse
|
||||
* (SIGALRM). pause() should not return.
|
||||
*/
|
||||
alarm(2);
|
||||
|
||||
pause();
|
||||
/* should not be reachable */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* At this point we are executing as the child process */
|
||||
parent = getppid();
|
||||
|
|
|
@ -202,7 +202,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
|
|||
* rx buffer by the caller, so this assumption is safe while
|
||||
* we block new rx while draining the existing rx
|
||||
*/
|
||||
if (eff_buf->token && eff_buf->token_len) {
|
||||
if (!priv->rx.avail_in && eff_buf->token && eff_buf->token_len) {
|
||||
priv->rx.next_in = (unsigned char *)eff_buf->token;
|
||||
priv->rx.avail_in = eff_buf->token_len;
|
||||
}
|
||||
|
|
|
@ -107,8 +107,10 @@ lws_read(struct lws *wsi, unsigned char *buf, size_t len)
|
|||
wsi->u.hdr.lextable_pos = 0;
|
||||
/* fallthru */
|
||||
case LWSS_HTTP_HEADERS:
|
||||
|
||||
assert(wsi->u.hdr.ah);
|
||||
if (!wsi->u.hdr.ah) {
|
||||
lwsl_err("%s: LWSS_HTTP_HEADERS: NULL ah\n", __func__);
|
||||
assert(0);
|
||||
}
|
||||
lwsl_parser("issuing %d bytes to parser\n", (int)len);
|
||||
|
||||
if (lws_handshake_client(wsi, &buf, len))
|
||||
|
@ -211,7 +213,7 @@ postbody_completion:
|
|||
goto bail;
|
||||
}
|
||||
|
||||
goto http_complete;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -241,20 +243,6 @@ read_ok:
|
|||
|
||||
return buf - oldbuf;
|
||||
|
||||
http_complete:
|
||||
lwsl_debug("%s: http_complete\n", __func__);
|
||||
|
||||
#ifndef LWS_NO_SERVER
|
||||
/* Did the client want to keep the HTTP connection going? */
|
||||
if (lws_http_transaction_completed(wsi))
|
||||
goto bail;
|
||||
#endif
|
||||
/* we may have next header set already, but return to event loop first
|
||||
* so a heaily-pipelined http/1.1 connection cannot monopolize the
|
||||
* service thread with GET hugefile.bin GET hugefile.bin etc
|
||||
*/
|
||||
goto read_ok;
|
||||
|
||||
bail:
|
||||
lwsl_debug("closing connection at lws_read bail:\n");
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
|
|
|
@ -479,7 +479,7 @@ int lws_http2_do_pps_send(struct lws_context *context, struct lws *wsi)
|
|||
wsi->u.http.fd = LWS_INVALID_FILE;
|
||||
|
||||
if (lws_is_ssl(lws_http2_get_network_wsi(wsi))) {
|
||||
lwsl_info("skipping nonexistant ssl upgrade headers\n");
|
||||
lwsl_info("skipping nonexistent ssl upgrade headers\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
53
lib/libuv.c
53
lib/libuv.c
|
@ -40,7 +40,7 @@ lws_uv_idle(uv_idle_t *handle
|
|||
struct lws_context_per_thread *pt = lws_container_of(handle,
|
||||
struct lws_context_per_thread, uv_idle);
|
||||
|
||||
lwsl_debug("%s\n", __func__);
|
||||
// lwsl_debug("%s\n", __func__);
|
||||
|
||||
/*
|
||||
* is there anybody with pending stuff that needs service forcing?
|
||||
|
@ -51,8 +51,8 @@ lws_uv_idle(uv_idle_t *handle
|
|||
/* still somebody left who wants forced service? */
|
||||
if (!lws_service_adjust_timeout(pt->context, 1, pt->tid))
|
||||
/* yes... come back again later */
|
||||
lwsl_debug("%s: done again\n", __func__);
|
||||
return;
|
||||
// lwsl_debug("%s: done again\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* there is nobody who needs service forcing, shut down idle */
|
||||
|
@ -133,6 +133,9 @@ lws_uv_timeout_cb(uv_timer_t *timer
|
|||
struct lws_context_per_thread *pt = lws_container_of(timer,
|
||||
struct lws_context_per_thread, uv_timeout_watcher);
|
||||
|
||||
if (pt->context->requested_kill)
|
||||
return;
|
||||
|
||||
lwsl_debug("%s\n", __func__);
|
||||
|
||||
lws_service_fd_tsi(pt->context, NULL, pt->tid);
|
||||
|
@ -149,6 +152,10 @@ lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, int tsi)
|
|||
|
||||
if (!loop) {
|
||||
loop = lws_malloc(sizeof(*loop));
|
||||
if (!loop) {
|
||||
lwsl_err("OOM\n");
|
||||
return -1;
|
||||
}
|
||||
#if UV_VERSION_MAJOR > 0
|
||||
uv_loop_init(loop);
|
||||
#else
|
||||
|
@ -199,14 +206,14 @@ lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, int tsi)
|
|||
}
|
||||
|
||||
uv_timer_init(pt->io_loop_uv, &pt->uv_timeout_watcher);
|
||||
uv_timer_start(&pt->uv_timeout_watcher, lws_uv_timeout_cb, 1000, 1000);
|
||||
uv_timer_start(&pt->uv_timeout_watcher, lws_uv_timeout_cb, 10, 1000);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void lws_uv_close_cb(uv_handle_t *handle)
|
||||
{
|
||||
//lwsl_err("%s\n", __func__);
|
||||
//lwsl_err("%s: handle %p\n", __func__, handle);
|
||||
}
|
||||
|
||||
static void lws_uv_walk_cb(uv_handle_t *handle, void *arg)
|
||||
|
@ -226,12 +233,13 @@ lws_libuv_destroyloop(struct lws_context *context, int tsi)
|
|||
if (!pt->io_loop_uv)
|
||||
return;
|
||||
|
||||
if (context->use_ev_sigint)
|
||||
if (context->use_ev_sigint) {
|
||||
uv_signal_stop(&pt->w_sigint.uv_watcher);
|
||||
|
||||
for (m = 0; m < ARRAY_SIZE(sigs); m++) {
|
||||
uv_signal_stop(&pt->signals[m]);
|
||||
uv_close((uv_handle_t *)&pt->signals[m], lws_uv_close_cb);
|
||||
for (m = 0; m < ARRAY_SIZE(sigs); m++) {
|
||||
uv_signal_stop(&pt->signals[m]);
|
||||
uv_close((uv_handle_t *)&pt->signals[m], lws_uv_close_cb);
|
||||
}
|
||||
}
|
||||
|
||||
uv_timer_stop(&pt->uv_timeout_watcher);
|
||||
|
@ -243,15 +251,12 @@ lws_libuv_destroyloop(struct lws_context *context, int tsi)
|
|||
while (budget-- && uv_run(pt->io_loop_uv, UV_RUN_NOWAIT))
|
||||
;
|
||||
|
||||
if (!pt->ev_loop_foreign)
|
||||
uv_stop(pt->io_loop_uv);
|
||||
|
||||
if (pt->ev_loop_foreign)
|
||||
return;
|
||||
|
||||
uv_stop(pt->io_loop_uv);
|
||||
|
||||
uv_walk(pt->io_loop_uv, lws_uv_walk_cb, NULL);
|
||||
if (pt->ev_loop_foreign)
|
||||
return;
|
||||
|
||||
while (uv_run(pt->io_loop_uv, UV_RUN_NOWAIT))
|
||||
;
|
||||
|
@ -296,15 +301,18 @@ lws_libuv_io(struct lws *wsi, int flags)
|
|||
if (!LWS_LIBUV_ENABLED(context))
|
||||
return;
|
||||
|
||||
lwsl_debug("%s: wsi: %p, flags:0x%x\n", __func__, wsi, flags);
|
||||
// lwsl_notice("%s: wsi: %p, flags:0x%x\n", __func__, wsi, flags);
|
||||
|
||||
if (!pt->io_loop_uv) {
|
||||
lwsl_info("%s: no io loop yet\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
assert((flags & (LWS_EV_START | LWS_EV_STOP)) &&
|
||||
(flags & (LWS_EV_READ | LWS_EV_WRITE)));
|
||||
if (!((flags & (LWS_EV_START | LWS_EV_STOP)) &&
|
||||
(flags & (LWS_EV_READ | LWS_EV_WRITE)))) {
|
||||
lwsl_err("%s: assert: flags %d", __func__, flags);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (flags & LWS_EV_START) {
|
||||
if (flags & LWS_EV_WRITE)
|
||||
|
@ -375,6 +383,9 @@ lws_libuv_stop(struct lws_context *context)
|
|||
struct lws_context_per_thread *pt;
|
||||
int n, m;
|
||||
|
||||
if (context->requested_kill)
|
||||
return;
|
||||
|
||||
context->requested_kill = 1;
|
||||
|
||||
m = context->count_threads;
|
||||
|
@ -473,14 +484,14 @@ lws_plat_plugins_init(struct lws_context * context, const char * const *d)
|
|||
|
||||
lwsl_notice(" %s\n", dent.name);
|
||||
|
||||
snprintf(path, sizeof(path) - 1, "%s/%s", *d, dent.name);
|
||||
lws_snprintf(path, sizeof(path) - 1, "%s/%s", *d, dent.name);
|
||||
if (uv_dlopen(path, &lib)) {
|
||||
uv_dlerror(&lib);
|
||||
lwsl_err("Error loading DSO: %s\n", lib.errmsg);
|
||||
goto bail;
|
||||
}
|
||||
/* we could open it, can we get his init function? */
|
||||
m = snprintf(path, sizeof(path) - 1, "init_%s",
|
||||
m = lws_snprintf(path, sizeof(path) - 1, "init_%s",
|
||||
dent.name + 3 /* snip lib... */);
|
||||
path[m - 3] = '\0'; /* snip the .so */
|
||||
if (uv_dlsym(&lib, path, &v)) {
|
||||
|
@ -539,11 +550,11 @@ lws_plat_plugins_destroy(struct lws_context * context)
|
|||
if (!plugin)
|
||||
return 0;
|
||||
|
||||
lwsl_notice("%s\n", __func__);
|
||||
// lwsl_notice("%s\n", __func__);
|
||||
|
||||
while (plugin) {
|
||||
p = plugin;
|
||||
m = snprintf(path, sizeof(path) - 1, "destroy_%s", plugin->name + 3);
|
||||
m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s", plugin->name + 3);
|
||||
path[m - 3] = '\0';
|
||||
|
||||
if (uv_dlsym(&plugin->lib, path, &v)) {
|
||||
|
|
191
lib/libwebsockets.c
Normal file → Executable file
191
lib/libwebsockets.c
Normal file → Executable file
|
@ -30,6 +30,14 @@
|
|||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#include <Iphlpapi.h>
|
||||
#else
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
|
||||
static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
|
||||
|
||||
|
@ -62,10 +70,6 @@ lws_free_wsi(struct lws *wsi)
|
|||
lws_free_set_NULL(wsi->rxflow_buffer);
|
||||
lws_free_set_NULL(wsi->trunc_alloc);
|
||||
|
||||
if (wsi->u.hdr.ah)
|
||||
/* we're closing, losing some rx is OK */
|
||||
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
|
||||
|
||||
/* we may not have an ah, but may be on the waiting list... */
|
||||
lws_header_table_detach(wsi, 0);
|
||||
|
||||
|
@ -153,6 +157,10 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
|
|||
|
||||
lws_access_log(wsi);
|
||||
|
||||
if (wsi->u.hdr.ah)
|
||||
/* we're closing, losing some rx is OK */
|
||||
wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
|
||||
|
||||
context = wsi->context;
|
||||
pt = &context->pt[(int)wsi->tsi];
|
||||
|
||||
|
@ -323,7 +331,7 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
|
|||
if (!wsi->u.ws.close_in_ping_buffer_len) {
|
||||
wsi->u.ws.close_in_ping_buffer_len = 2;
|
||||
wsi->u.ws.ping_payload_buf[LWS_PRE] =
|
||||
(reason >> 16) & 0xff;
|
||||
(reason >> 8) & 0xff;
|
||||
wsi->u.ws.ping_payload_buf[LWS_PRE + 1] =
|
||||
reason & 0xff;
|
||||
}
|
||||
|
@ -420,7 +428,8 @@ just_kill_connection:
|
|||
lws_remove_from_timeout_list(wsi);
|
||||
|
||||
/* checking return redundant since we anyway close */
|
||||
remove_wsi_socket_from_fds(wsi);
|
||||
if (wsi->sock != LWS_SOCK_INVALID)
|
||||
remove_wsi_socket_from_fds(wsi);
|
||||
|
||||
wsi->state = LWSS_DEAD_SOCKET;
|
||||
|
||||
|
@ -487,10 +496,22 @@ just_kill_connection:
|
|||
wsi->user_space, NULL, 0 );
|
||||
} else if (wsi->mode == LWSCM_WSCL_WAITING_SERVER_REPLY ||
|
||||
wsi->mode == LWSCM_WSCL_WAITING_CONNECT) {
|
||||
char* errorString;
|
||||
|
||||
lwsl_debug("Connection closed before server reply\n");
|
||||
wsi->vhost->protocols[0].callback(wsi,
|
||||
errorString = NULL;
|
||||
if (wsi->u.hdr.ah)
|
||||
errorString = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
|
||||
if (errorString) {
|
||||
wsi->vhost->protocols[0].callback(wsi,
|
||||
LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
|
||||
wsi->user_space, errorString,
|
||||
(unsigned int)strlen(errorString));
|
||||
} else {
|
||||
wsi->vhost->protocols[0].callback(wsi,
|
||||
LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
|
||||
wsi->user_space, NULL, 0);
|
||||
}
|
||||
} else
|
||||
lwsl_debug("not calling back closed mode=%d state=%d\n",
|
||||
wsi->mode, wsi->state_pre_close);
|
||||
|
@ -1154,17 +1175,17 @@ lwsl_timestamp(int level, char *p, int len)
|
|||
continue;
|
||||
now = time_in_microseconds() / 100;
|
||||
if (ptm)
|
||||
n = snprintf(p, len,
|
||||
n = lws_snprintf(p, len,
|
||||
"[%04d/%02d/%02d %02d:%02d:%02d:%04d] %s: ",
|
||||
ptm->tm_year + 1900,
|
||||
ptm->tm_mon,
|
||||
ptm->tm_mon + 1,
|
||||
ptm->tm_mday,
|
||||
ptm->tm_hour,
|
||||
ptm->tm_min,
|
||||
ptm->tm_sec,
|
||||
(int)(now % 10000), log_level_names[n]);
|
||||
else
|
||||
n = snprintf(p, len, "[%llu:%04d] %s: ",
|
||||
n = lws_snprintf(p, len, "[%llu:%04d] %s: ",
|
||||
(unsigned long long) now / 10000,
|
||||
(int)(now % 10000), log_level_names[n]);
|
||||
return n;
|
||||
|
@ -1309,6 +1330,16 @@ lws_get_fops(struct lws_context *context)
|
|||
return &context->fops;
|
||||
}
|
||||
|
||||
/**
|
||||
* lws_get_context - Allow getting lws_context from a Websocket connection
|
||||
* instance
|
||||
*
|
||||
* With this function, users can access context in the callback function.
|
||||
* Otherwise users may have to declare context as a global variable.
|
||||
*
|
||||
* @wsi: Websocket connection instance
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_context *
|
||||
lws_get_context(const struct lws *wsi)
|
||||
{
|
||||
|
@ -1536,7 +1567,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
|
|||
#endif
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_socket_bind(struct lws_vhost *vhost, int sockfd, int port,
|
||||
lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
|
||||
const char *iface)
|
||||
{
|
||||
#if LWS_POSIX
|
||||
|
@ -1574,7 +1605,46 @@ lws_socket_bind(struct lws_vhost *vhost, int sockfd, int port,
|
|||
v = (struct sockaddr *)&serv_addr6;
|
||||
n = sizeof(struct sockaddr_in6);
|
||||
bzero((char *) &serv_addr6, sizeof(serv_addr6));
|
||||
serv_addr6.sin6_addr = in6addr_any;
|
||||
|
||||
if (iface &&
|
||||
interface_to_sa(vhost->context, iface,
|
||||
(struct sockaddr_in *)v, n) < 0) {
|
||||
lwsl_err("Unable to find interface %s\n", iface);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iface) {
|
||||
struct ifaddrs *addrs, *addr;
|
||||
char ip[NI_MAXHOST];
|
||||
unsigned int i;
|
||||
|
||||
getifaddrs(&addrs);
|
||||
for (addr = addrs; addr; addr = addr->ifa_next) {
|
||||
if (!addr->ifa_addr ||
|
||||
addr->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
|
||||
getnameinfo(addr->ifa_addr,
|
||||
sizeof(struct sockaddr_in6),
|
||||
ip, sizeof(ip),
|
||||
NULL, 0, NI_NUMERICHOST);
|
||||
|
||||
i = 0;
|
||||
while (ip[i])
|
||||
if (ip[i++] == '%') {
|
||||
ip[i - 1] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcmp(ip, iface)) {
|
||||
serv_addr6.sin6_scope_id =
|
||||
if_nametoindex(addr->ifa_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
freeifaddrs(addrs);
|
||||
}
|
||||
|
||||
serv_addr6.sin6_family = AF_INET6;
|
||||
serv_addr6.sin6_port = htons(port);
|
||||
} else
|
||||
|
@ -1662,6 +1732,24 @@ lws_finalize_startup(struct lws_context *context)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lws_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int n;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
va_start(ap, format);
|
||||
n = vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (n >= size)
|
||||
return size;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_is_cgi(struct lws *wsi) {
|
||||
|
@ -1696,7 +1784,7 @@ lws_create_basic_wsi(struct lws_context *context, int tsi)
|
|||
new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
|
||||
new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
|
||||
|
||||
/* intialize the instance struct */
|
||||
/* initialize the instance struct */
|
||||
|
||||
new_wsi->state = LWSS_CGI;
|
||||
new_wsi->mode = LWSCM_CGI;
|
||||
|
@ -1810,7 +1898,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
if (wsi->u.hdr.ah) {
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
|
||||
uritok = WSI_TOKEN_POST_URI;
|
||||
snprintf(cgi_path, sizeof(cgi_path) - 1, "REQUEST_URI=%s",
|
||||
lws_snprintf(cgi_path, sizeof(cgi_path) - 1, "REQUEST_URI=%s",
|
||||
lws_hdr_simple_ptr(wsi, uritok));
|
||||
cgi_path[sizeof(cgi_path) - 1] = '\0';
|
||||
env_array[n++] = cgi_path;
|
||||
|
@ -1820,7 +1908,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
env_array[n++] = "REQUEST_METHOD=GET";
|
||||
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "QUERY_STRING=");
|
||||
p += lws_snprintf(p, end - p, "QUERY_STRING=");
|
||||
/* dump the individual URI Arg parameters */
|
||||
m = 0;
|
||||
while (1) {
|
||||
|
@ -1845,55 +1933,55 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len
|
|||
*p++ = '\0';
|
||||
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "PATH_INFO=%s",
|
||||
p += lws_snprintf(p, end - p, "PATH_INFO=%s",
|
||||
lws_hdr_simple_ptr(wsi, uritok) +
|
||||
script_uri_path_len);
|
||||
p++;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_REFERER)) {
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "HTTP_REFERER=%s",
|
||||
p += lws_snprintf(p, end - p, "HTTP_REFERER=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_REFERER));
|
||||
p++;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "HTTP_HOST=%s",
|
||||
p += lws_snprintf(p, end - p, "HTTP_HOST=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST));
|
||||
p++;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) {
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "HTTP_COOKIE=%s",
|
||||
p += lws_snprintf(p, end - p, "HTTP_COOKIE=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COOKIE));
|
||||
p++;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_USER_AGENT)) {
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "USER_AGENT=%s",
|
||||
p += lws_snprintf(p, end - p, "USER_AGENT=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_USER_AGENT));
|
||||
p++;
|
||||
}
|
||||
if (uritok == WSI_TOKEN_POST_URI) {
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "CONTENT_TYPE=%s",
|
||||
p += lws_snprintf(p, end - p, "CONTENT_TYPE=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE));
|
||||
p++;
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "CONTENT_LENGTH=%s",
|
||||
p += lws_snprintf(p, end - p, "CONTENT_LENGTH=%s",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH));
|
||||
p++;
|
||||
}
|
||||
}
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "SCRIPT_PATH=%s", exec_array[0]) + 1;
|
||||
p += lws_snprintf(p, end - p, "SCRIPT_PATH=%s", exec_array[0]) + 1;
|
||||
|
||||
while (mp_cgienv) {
|
||||
env_array[n++] = p;
|
||||
p += snprintf(p, end - p, "%s=%s", mp_cgienv->name,
|
||||
p += lws_snprintf(p, end - p, "%s=%s", mp_cgienv->name,
|
||||
mp_cgienv->value);
|
||||
lwsl_debug(" Applying mount-specific cgi env '%s'\n",
|
||||
env_array[n - 1]);
|
||||
|
@ -2333,10 +2421,13 @@ lws_access_log(struct lws *wsi)
|
|||
if (!wsi->access_log_pending)
|
||||
return 0;
|
||||
|
||||
if (!wsi->access_log.header_log)
|
||||
return 0;
|
||||
|
||||
if (!p)
|
||||
p = "";
|
||||
|
||||
l = snprintf(ass, sizeof(ass) - 1, "%s %d %lu %s\n",
|
||||
l = lws_snprintf(ass, sizeof(ass) - 1, "%s %d %lu %s\n",
|
||||
wsi->access_log.header_log,
|
||||
wsi->access_log.response, wsi->access_log.sent, p);
|
||||
|
||||
|
@ -2346,10 +2437,14 @@ lws_access_log(struct lws *wsi)
|
|||
} else
|
||||
lwsl_err("%s", ass);
|
||||
|
||||
if (wsi->access_log.header_log)
|
||||
if (wsi->access_log.header_log) {
|
||||
lws_free(wsi->access_log.header_log);
|
||||
if (wsi->access_log.user_agent)
|
||||
wsi->access_log.header_log = NULL;
|
||||
}
|
||||
if (wsi->access_log.user_agent) {
|
||||
lws_free(wsi->access_log.user_agent);
|
||||
wsi->access_log.user_agent = NULL;
|
||||
}
|
||||
wsi->access_log_pending = 0;
|
||||
|
||||
return 0;
|
||||
|
@ -2375,7 +2470,7 @@ lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len)
|
|||
if (len < 100)
|
||||
return 0;
|
||||
|
||||
buf += snprintf(buf, end - buf,
|
||||
buf += lws_snprintf(buf, end - buf,
|
||||
"{\n \"name\":\"%s\",\n"
|
||||
" \"port\":\"%d\",\n"
|
||||
" \"use_ssl\":\"%d\",\n"
|
||||
|
@ -2401,11 +2496,11 @@ lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len)
|
|||
if (vh->mount_list) {
|
||||
const struct lws_http_mount *m = vh->mount_list;
|
||||
|
||||
buf += snprintf(buf, end - buf, ",\n \"mounts\":[");
|
||||
buf += lws_snprintf(buf, end - buf, ",\n \"mounts\":[");
|
||||
while (m) {
|
||||
if (!first)
|
||||
buf += snprintf(buf, end - buf, ",");
|
||||
buf += snprintf(buf, end - buf,
|
||||
buf += lws_snprintf(buf, end - buf, ",");
|
||||
buf += lws_snprintf(buf, end - buf,
|
||||
"\n {\n \"mountpoint\":\"%s\",\n"
|
||||
" \"origin\":\"%s%s\",\n"
|
||||
" \"cache_max_age\":\"%d\",\n"
|
||||
|
@ -2421,25 +2516,25 @@ lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len)
|
|||
m->cache_revalidate,
|
||||
m->cache_intermediaries);
|
||||
if (m->def)
|
||||
buf += snprintf(buf, end - buf,
|
||||
buf += lws_snprintf(buf, end - buf,
|
||||
",\n \"default\":\"%s\"",
|
||||
m->def);
|
||||
buf += snprintf(buf, end - buf, "\n }");
|
||||
buf += lws_snprintf(buf, end - buf, "\n }");
|
||||
first = 0;
|
||||
m = m->mount_next;
|
||||
}
|
||||
buf += snprintf(buf, end - buf, "\n ]");
|
||||
buf += lws_snprintf(buf, end - buf, "\n ]");
|
||||
}
|
||||
|
||||
if (vh->protocols) {
|
||||
n = 0;
|
||||
first = 1;
|
||||
|
||||
buf += snprintf(buf, end - buf, ",\n \"ws-protocols\":[");
|
||||
buf += lws_snprintf(buf, end - buf, ",\n \"ws-protocols\":[");
|
||||
while (n < vh->count_protocols) {
|
||||
if (!first)
|
||||
buf += snprintf(buf, end - buf, ",");
|
||||
buf += snprintf(buf, end - buf,
|
||||
buf += lws_snprintf(buf, end - buf, ",");
|
||||
buf += lws_snprintf(buf, end - buf,
|
||||
"\n {\n \"%s\":\{\n"
|
||||
" \"status\":\"ok\"\n }\n }"
|
||||
,
|
||||
|
@ -2447,10 +2542,10 @@ lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len)
|
|||
first = 0;
|
||||
n++;
|
||||
}
|
||||
buf += snprintf(buf, end - buf, "\n ]");
|
||||
buf += lws_snprintf(buf, end - buf, "\n ]");
|
||||
}
|
||||
|
||||
buf += snprintf(buf, end - buf, "\n}");
|
||||
buf += lws_snprintf(buf, end - buf, "\n}");
|
||||
|
||||
return buf - orig;
|
||||
}
|
||||
|
@ -2469,7 +2564,7 @@ lws_json_dump_context(const struct lws_context *context, char *buf, int len)
|
|||
time_t t = time(NULL);
|
||||
int listening = 0, cgi_count = 0, n;
|
||||
|
||||
buf += snprintf(buf, end - buf, "{ "
|
||||
buf += lws_snprintf(buf, end - buf, "{ "
|
||||
"\"version\":\"%s\",\n"
|
||||
"\"uptime\":\"%ld\",\n"
|
||||
"\"cgi_spawned\":\"%d\",\n"
|
||||
|
@ -2489,19 +2584,19 @@ lws_json_dump_context(const struct lws_context *context, char *buf, int len)
|
|||
|
||||
m = getloadavg(d, 3);
|
||||
for (n = 0; n < m; n++) {
|
||||
buf += snprintf(buf, end - buf,
|
||||
buf += lws_snprintf(buf, end - buf,
|
||||
"\"l%d\":\"%.2f\",\n",
|
||||
n + 1, d[n]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
buf += snprintf(buf, end - buf, "\"pt\":[\n ");
|
||||
buf += lws_snprintf(buf, end - buf, "\"pt\":[\n ");
|
||||
for (n = 0; n < context->count_threads; n++) {
|
||||
pt = &context->pt[n];
|
||||
if (n)
|
||||
buf += snprintf(buf, end - buf, ",");
|
||||
buf += snprintf(buf, end - buf,
|
||||
buf += lws_snprintf(buf, end - buf, ",");
|
||||
buf += lws_snprintf(buf, end - buf,
|
||||
"\n {\n"
|
||||
" \"fds_count\":\"%d\",\n"
|
||||
" \"ah_pool_inuse\":\"%d\",\n"
|
||||
|
@ -2512,7 +2607,7 @@ lws_json_dump_context(const struct lws_context *context, char *buf, int len)
|
|||
pt->ah_wait_list_length);
|
||||
}
|
||||
|
||||
buf += snprintf(buf, end - buf, "], \"vhosts\":[\n ");
|
||||
buf += lws_snprintf(buf, end - buf, "], \"vhosts\":[\n ");
|
||||
|
||||
while (vh) {
|
||||
if (!first)
|
||||
|
@ -2525,7 +2620,7 @@ lws_json_dump_context(const struct lws_context *context, char *buf, int len)
|
|||
vh = vh->vhost_next;
|
||||
}
|
||||
|
||||
buf += snprintf(buf, end - buf, "],\n\"listen_wsi\":\"%d\"",
|
||||
buf += lws_snprintf(buf, end - buf, "],\n\"listen_wsi\":\"%d\"",
|
||||
listening);
|
||||
|
||||
#ifdef LWS_WITH_CGI
|
||||
|
@ -2540,10 +2635,10 @@ lws_json_dump_context(const struct lws_context *context, char *buf, int len)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
buf += snprintf(buf, end - buf, ",\n \"cgi_alive\":\"%d\"\n ",
|
||||
buf += lws_snprintf(buf, end - buf, ",\n \"cgi_alive\":\"%d\"\n ",
|
||||
cgi_count);
|
||||
|
||||
buf += snprintf(buf, end - buf, "}\n ");
|
||||
buf += lws_snprintf(buf, end - buf, "}\n ");
|
||||
|
||||
return buf - orig;
|
||||
}
|
||||
|
|
|
@ -112,7 +112,6 @@ struct sockaddr_in;
|
|||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <basetsd.h>
|
||||
#ifndef _WIN32_WCE
|
||||
#include <fcntl.h>
|
||||
|
@ -121,7 +120,8 @@ struct sockaddr_in;
|
|||
#define O_RDONLY _O_RDONLY
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
// Visual studio older than 2015 and WIN_CE has only _stricmp
|
||||
#if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(_WIN32_WCE)
|
||||
#define strcasecmp _stricmp
|
||||
#else
|
||||
#define strcasecmp stricmp
|
||||
|
@ -147,7 +147,11 @@ struct sockaddr_in;
|
|||
#define LWS_O_RDONLY _O_RDONLY
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER < 1900 /* Visual Studio 2015 already defines this in <stdio.h> */
|
||||
#define snprintf _snprintf
|
||||
#define lws_snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#ifndef __func__
|
||||
#define __func__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
#else /* NOT WIN32 */
|
||||
|
@ -306,7 +310,9 @@ LWS_VISIBLE LWS_EXTERN void lwsl_hexdump(void *buf, size_t len);
|
|||
|
||||
|
||||
struct lws;
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||
#endif
|
||||
|
||||
/* api change list for user code to test against */
|
||||
|
||||
|
@ -343,7 +349,6 @@ enum lws_context_options {
|
|||
(1 << 12),
|
||||
LWS_SERVER_OPTION_LIBUV = (1 << 10),
|
||||
LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS = (1 << 11) |
|
||||
(1 << 3) |
|
||||
(1 << 12),
|
||||
LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT = (1 << 12),
|
||||
LWS_SERVER_OPTION_EXPLICIT_VHOSTS = (1 << 13),
|
||||
|
@ -1006,7 +1011,7 @@ struct lws_extension;
|
|||
*
|
||||
* LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: if configured for
|
||||
* including OpenSSL support, this callback allows your user code
|
||||
* to load extra certifcates into the server which allow it to
|
||||
* to load extra certificates into the server which allow it to
|
||||
* verify the validity of certificates returned by clients. @user
|
||||
* is the server's OpenSSL SSL_CTX*
|
||||
*
|
||||
|
@ -1362,12 +1367,13 @@ struct lws_plugin {
|
|||
* If we add more extensions, publish the callback here ------v
|
||||
*/
|
||||
|
||||
extern int lws_extension_callback_pm_deflate(
|
||||
LWS_EXTERN
|
||||
int lws_extension_callback_pm_deflate(
|
||||
struct lws_context *context, const struct lws_extension *ext,
|
||||
struct lws *wsi, enum lws_extension_callback_reasons reason,
|
||||
void *user, void *in, size_t len);
|
||||
|
||||
LWS_EXTERN int
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_set_extension_option(struct lws *wsi, const char *ext_name,
|
||||
const char *opt_name, const char *opt_val);
|
||||
|
||||
|
@ -1385,6 +1391,7 @@ struct lws_http_mount {
|
|||
const char *def; /* default target, eg, "index.html" */
|
||||
|
||||
const struct lws_protocol_vhost_options *cgienv;
|
||||
const struct lws_protocol_vhost_options *extra_mimetypes;
|
||||
|
||||
int cgi_timeout;
|
||||
int cache_max_age;
|
||||
|
@ -1607,10 +1614,10 @@ enum {
|
|||
LWSMPRO_REDIR_HTTPS,
|
||||
};
|
||||
|
||||
LWS_EXTERN int
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len);
|
||||
|
||||
LWS_EXTERN int
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_json_dump_context(const struct lws_context *context, char *buf, int len);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
|
@ -1625,20 +1632,20 @@ lws_create_context(struct lws_context_creation_info *info);
|
|||
|
||||
struct lws_vhost;
|
||||
|
||||
LWS_VISIBLE struct lws_vhost *
|
||||
LWS_EXTERN LWS_VISIBLE struct lws_vhost *
|
||||
lws_create_vhost(struct lws_context *context,
|
||||
struct lws_context_creation_info *info);
|
||||
|
||||
LWS_VISIBLE struct lws_vhost *
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_vhost *
|
||||
lws_vhost_get(struct lws *wsi);
|
||||
|
||||
LWS_VISIBLE const struct lws_protocols *
|
||||
LWS_VISIBLE LWS_EXTERN const struct lws_protocols *
|
||||
lws_protocol_get(struct lws *wsi);
|
||||
|
||||
LWS_VISIBLE void *
|
||||
LWS_VISIBLE LWS_EXTERN void *
|
||||
lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost, const struct lws_protocols *prot,
|
||||
int size);
|
||||
LWS_VISIBLE void *
|
||||
LWS_VISIBLE LWS_EXTERN void *
|
||||
lws_protocol_vh_priv_get(struct lws_vhost *vhost, const struct lws_protocols *prot);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
|
@ -1708,7 +1715,7 @@ lws_ev_sigint_cfg(struct lws_context *context, int use_ev_sigint,
|
|||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_ev_initloop(struct lws_context *context, struct ev_loop *loop, int tsi);
|
||||
|
||||
LWS_VISIBLE void
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_ev_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents);
|
||||
#endif /* LWS_USE_LIBEV */
|
||||
|
||||
|
@ -1720,7 +1727,7 @@ lws_uv_sigint_cfg(struct lws_context *context, int use_uv_sigint,
|
|||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_libuv_run(const struct lws_context *context, int tsi);
|
||||
|
||||
LWS_VISIBLE void
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_libuv_stop(struct lws_context *context);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
|
@ -1729,7 +1736,7 @@ lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, int tsi);
|
|||
LWS_VISIBLE LWS_EXTERN uv_loop_t *
|
||||
lws_uv_getloop(struct lws_context *context, int tsi);
|
||||
|
||||
LWS_VISIBLE void
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_uv_sigint_cb(uv_signal_t *watcher, int signum);
|
||||
#endif /* LWS_USE_LIBUV */
|
||||
|
||||
|
@ -1818,6 +1825,23 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs);
|
|||
* to the address immediately after the padding won't cause an unaligned access
|
||||
* error. Sometimes for performance reasons the recommended padding is even
|
||||
* larger than sizeof(void *).
|
||||
*
|
||||
* Truncated Writes
|
||||
* ================
|
||||
*
|
||||
* The OS may not accept everything you asked to write on the connection.
|
||||
*
|
||||
* Posix defines POLLOUT indication from poll() to show that the connection
|
||||
* will accept more write data, but it doesn't specifiy how much. It may just
|
||||
* accept one byte of whatever you wanted to send.
|
||||
*
|
||||
* LWS will buffer the remainder automatically, and send it out autonomously.
|
||||
*
|
||||
* During that time, WRITABLE callbacks will be suppressed.
|
||||
*
|
||||
* This is to handle corner cases where unexpectedly the OS refuses what we
|
||||
* usually expect it to accept. You should try to send in chunks that are
|
||||
* almost always accepted in order to avoid the inefficiency of the buffering.
|
||||
*/
|
||||
|
||||
#if !defined(LWS_SIZEOFPTR)
|
||||
|
@ -1827,7 +1851,7 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs);
|
|||
#define u_int64_t unsigned long long
|
||||
#endif
|
||||
|
||||
#if __x86_64__
|
||||
#if defined(__x86_64__)
|
||||
#define _LWS_PAD_SIZE 16 /* Intel recommended for best performance */
|
||||
#else
|
||||
#define _LWS_PAD_SIZE LWS_SIZEOFPTR /* Size of a pointer on the target arch */
|
||||
|
@ -1883,7 +1907,7 @@ LWS_VISIBLE LWS_EXTERN int
|
|||
lws_callback_on_writable_all_protocol(const struct lws_context *context,
|
||||
const struct lws_protocols *protocol);
|
||||
|
||||
LWS_VISIBLE int
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_callback_on_writable_all_protocol_vhost(const struct lws_vhost *vhost,
|
||||
const struct lws_protocols *protocol);
|
||||
|
||||
|
@ -1891,7 +1915,7 @@ LWS_VISIBLE LWS_EXTERN int
|
|||
lws_callback_all_protocol(struct lws_context *context,
|
||||
const struct lws_protocols *protocol, int reason);
|
||||
|
||||
LWS_VISIBLE int
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_callback_all_protocol_vhost(struct lws_vhost *vh,
|
||||
const struct lws_protocols *protocol, int reason);
|
||||
|
||||
|
@ -2169,7 +2193,7 @@ lws_read(struct lws *wsi, unsigned char *buf, size_t len);
|
|||
* client and server for how to do.
|
||||
*/
|
||||
static LWS_INLINE LWS_WARN_DEPRECATED const struct lws_extension *
|
||||
lws_get_internal_extensions() { return NULL; }
|
||||
lws_get_internal_extensions(void) { return NULL; }
|
||||
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||||
lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi,
|
||||
void *ext_user, const struct lws_ext_options *opts,
|
||||
|
@ -2182,6 +2206,20 @@ lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi,
|
|||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_set_allocator(void *(*realloc)(void *ptr, size_t size));
|
||||
|
||||
/**
|
||||
* lws_snprintf(): lws_snprintf that truncates the returned length too
|
||||
*
|
||||
* \param str: destination buffer
|
||||
* \param size: bytes left in destination buffer
|
||||
* \param format: format string
|
||||
* \param ...: args for format
|
||||
*
|
||||
* This lets you correctly truncate buffers by concatenating lengths, if you
|
||||
* reach the limit the reported length doesn't exceed the limit.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_snprintf(char *str, size_t size, const char *format, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -81,6 +81,12 @@ lws_plat_change_pollfd(struct lws_context *context,
|
|||
return 0;
|
||||
}
|
||||
|
||||
extern "C" LWS_VISIBLE int
|
||||
lws_plat_check_connection_error(struct lws *wsi)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" LWS_VISIBLE int
|
||||
lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len)
|
||||
{
|
||||
|
|
|
@ -116,7 +116,7 @@ LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line)
|
|||
LWS_VISIBLE int
|
||||
lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &context->pt[tsi];
|
||||
struct lws_context_per_thread *pt;
|
||||
int n = -1, m, c;
|
||||
char buf;
|
||||
|
||||
|
@ -125,6 +125,8 @@ lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
|
|||
if (!context || !context->vhost_list)
|
||||
return 1;
|
||||
|
||||
pt = &context->pt[tsi];
|
||||
|
||||
if (timeout_ms < 0)
|
||||
goto faked_service;
|
||||
|
||||
|
@ -144,6 +146,19 @@ lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
|
|||
context->service_tid = context->service_tid_detected;
|
||||
|
||||
timeout_ms = lws_service_adjust_timeout(context, timeout_ms, tsi);
|
||||
/*
|
||||
* is there anybody with pending stuff that needs service forcing?
|
||||
*/
|
||||
if (!timeout_ms) {
|
||||
/* -1 timeout means just do forced service */
|
||||
lws_plat_service_tsi(context, -1, pt->tid);
|
||||
/* still somebody left who wants forced service? */
|
||||
if (!lws_service_adjust_timeout(context, 1, pt->tid)) {
|
||||
/* yes... come back again later */
|
||||
lwsl_debug("%s: done again\n", __func__);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = poll(pt->fds, pt->fds_count, timeout_ms);
|
||||
|
||||
|
@ -193,6 +208,12 @@ faked_service:
|
|||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_check_connection_error(struct lws *wsi)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_service(struct lws_context *context, int timeout_ms)
|
||||
{
|
||||
|
@ -331,7 +352,7 @@ lws_plat_plugins_init(struct lws_context * context, const char * const *d)
|
|||
|
||||
lwsl_notice(" %s\n", namelist[i]->d_name);
|
||||
|
||||
snprintf(path, sizeof(path) - 1, "%s/%s", *d,
|
||||
lws_snprintf(path, sizeof(path) - 1, "%s/%s", *d,
|
||||
namelist[i]->d_name);
|
||||
l = dlopen(path, RTLD_NOW);
|
||||
if (!l) {
|
||||
|
@ -341,7 +362,7 @@ lws_plat_plugins_init(struct lws_context * context, const char * const *d)
|
|||
goto bail;
|
||||
}
|
||||
/* we could open it, can we get his init function? */
|
||||
m = snprintf(path, sizeof(path) - 1, "init_%s",
|
||||
m = lws_snprintf(path, sizeof(path) - 1, "init_%s",
|
||||
namelist[i]->d_name + 3 /* snip lib... */);
|
||||
path[m - 3] = '\0'; /* snip the .so */
|
||||
initfunc = dlsym(l, path);
|
||||
|
@ -406,7 +427,7 @@ lws_plat_plugins_destroy(struct lws_context * context)
|
|||
|
||||
while (plugin) {
|
||||
p = plugin;
|
||||
m = snprintf(path, sizeof(path) - 1, "destroy_%s", plugin->name + 3);
|
||||
m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s", plugin->name + 3);
|
||||
path[m - 3] = '\0';
|
||||
func = dlsym(plugin->l, path);
|
||||
if (!func) {
|
||||
|
@ -538,7 +559,7 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
|
|||
freeifaddrs(ifr);
|
||||
|
||||
if (rc == -1) {
|
||||
/* check if bind to IP adddress */
|
||||
/* check if bind to IP address */
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1)
|
||||
rc = 0;
|
||||
|
|
|
@ -31,7 +31,10 @@ time_in_microseconds()
|
|||
time_t time(time_t *t)
|
||||
{
|
||||
time_t ret = time_in_microseconds() / 1000000;
|
||||
*t = ret;
|
||||
|
||||
if(t != NULL)
|
||||
*t = ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
@ -153,7 +156,7 @@ LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line)
|
|||
LWS_VISIBLE int
|
||||
lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &context->pt[tsi];
|
||||
struct lws_context_per_thread *pt;
|
||||
WSANETWORKEVENTS networkevents;
|
||||
struct lws_pollfd *pfd;
|
||||
struct lws *wsi;
|
||||
|
@ -165,6 +168,8 @@ lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
|
|||
if (context == NULL)
|
||||
return 1;
|
||||
|
||||
pt = &context->pt[tsi];
|
||||
|
||||
if (!context->service_tid_detected) {
|
||||
struct lws _lws;
|
||||
|
||||
|
@ -231,7 +236,17 @@ lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
|
|||
return -1;
|
||||
}
|
||||
|
||||
pfd->revents = (short)networkevents.lNetworkEvents;
|
||||
if ((networkevents.lNetworkEvents & FD_CONNECT) &&
|
||||
networkevents.iErrorCode[FD_CONNECT_BIT] &&
|
||||
networkevents.iErrorCode[FD_CONNECT_BIT] != LWS_EALREADY &&
|
||||
networkevents.iErrorCode[FD_CONNECT_BIT] != LWS_EINPROGRESS &&
|
||||
networkevents.iErrorCode[FD_CONNECT_BIT] != LWS_EWOULDBLOCK &&
|
||||
networkevents.iErrorCode[FD_CONNECT_BIT] != WSAEINVAL) {
|
||||
lwsl_debug("Unable to connect errno=%d\n",
|
||||
networkevents.iErrorCode[FD_CONNECT_BIT]);
|
||||
pfd->revents = LWS_POLLHUP;
|
||||
} else
|
||||
pfd->revents = (short)networkevents.lNetworkEvents;
|
||||
|
||||
if (pfd->revents & LWS_POLLOUT) {
|
||||
wsi = wsi_from_fd(context, pfd->fd);
|
||||
|
@ -406,7 +421,7 @@ lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
|
|||
pt->fds[pt->fds_count++].revents = 0;
|
||||
pt->events[pt->fds_count] = WSACreateEvent();
|
||||
WSAEventSelect(wsi->sock, pt->events[pt->fds_count],
|
||||
LWS_POLLIN | LWS_POLLHUP);
|
||||
LWS_POLLIN | LWS_POLLHUP | FD_CONNECT);
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
|
@ -424,12 +439,29 @@ lws_plat_service_periodic(struct lws_context *context)
|
|||
{
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_check_connection_error(struct lws *wsi)
|
||||
{
|
||||
int optVal;
|
||||
int optLen = sizeof(int);
|
||||
|
||||
if (getsockopt(wsi->sock, SOL_SOCKET, SO_ERROR,
|
||||
(char*)&optVal, &optLen) != SOCKET_ERROR && optVal &&
|
||||
optVal != LWS_EALREADY && optVal != LWS_EINPROGRESS &&
|
||||
optVal != LWS_EWOULDBLOCK && optVal != WSAEINVAL) {
|
||||
lwsl_debug("Connect failed SO_ERROR=%d\n", optVal);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_change_pollfd(struct lws_context *context,
|
||||
struct lws *wsi, struct lws_pollfd *pfd)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
||||
long networkevents = LWS_POLLHUP;
|
||||
long networkevents = LWS_POLLHUP | FD_CONNECT;
|
||||
|
||||
if ((pfd->events & LWS_POLLIN))
|
||||
networkevents |= LWS_POLLIN;
|
||||
|
|
|
@ -130,6 +130,7 @@ int lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len)
|
|||
n = wsi->protocol->rx_buffer_size;
|
||||
if (!n)
|
||||
n = LWS_MAX_SOCKET_IO_BUF;
|
||||
n += LWS_PRE + 4;
|
||||
if (n > len)
|
||||
n = len;
|
||||
|
||||
|
|
113
lib/parsers.c
113
lib/parsers.c
|
@ -60,6 +60,8 @@ lextable_decode(int pos, char c)
|
|||
}
|
||||
}
|
||||
|
||||
// doesn't scrub the ah rxbuffer by default, parent must do if needed
|
||||
|
||||
void
|
||||
lws_header_table_reset(struct lws *wsi, int autoservice)
|
||||
{
|
||||
|
@ -77,10 +79,6 @@ lws_header_table_reset(struct lws *wsi, int autoservice)
|
|||
ah->nfrag = 0;
|
||||
ah->pos = 0;
|
||||
|
||||
/* and reset the rx state */
|
||||
ah->rxpos = 0;
|
||||
ah->rxlen = 0;
|
||||
|
||||
/* since we will restart the ah, our new headers are not completed */
|
||||
wsi->hdr_parsing_completed = 0;
|
||||
|
||||
|
@ -182,12 +180,21 @@ lws_header_table_attach(struct lws *wsi, int autoservice)
|
|||
lws_pt_unlock(pt);
|
||||
|
||||
reset:
|
||||
|
||||
/* and reset the rx state */
|
||||
wsi->u.hdr.ah->rxpos = 0;
|
||||
wsi->u.hdr.ah->rxlen = 0;
|
||||
|
||||
lws_header_table_reset(wsi, autoservice);
|
||||
time(&wsi->u.hdr.ah->assigned);
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
if (wsi->state == LWSS_CLIENT_UNCONNECTED)
|
||||
lws_client_connect_via_info2(wsi);
|
||||
if (!lws_client_connect_via_info2(wsi))
|
||||
/* our client connect has failed, the wsi
|
||||
* has been closed
|
||||
*/
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -280,6 +287,9 @@ int lws_header_table_detach(struct lws *wsi, int autoservice)
|
|||
|
||||
wsi->u.hdr.ah = ah;
|
||||
ah->wsi = wsi; /* new owner */
|
||||
/* and reset the rx state */
|
||||
ah->rxpos = 0;
|
||||
ah->rxlen = 0;
|
||||
lws_header_table_reset(wsi, autoservice);
|
||||
time(&wsi->u.hdr.ah->assigned);
|
||||
|
||||
|
@ -300,7 +310,14 @@ int lws_header_table_detach(struct lws *wsi, int autoservice)
|
|||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
if (wsi->state == LWSS_CLIENT_UNCONNECTED)
|
||||
lws_client_connect_via_info2(wsi);
|
||||
if (!lws_client_connect_via_info2(wsi)) {
|
||||
/* our client connect has failed, the wsi
|
||||
* has been closed
|
||||
*/
|
||||
lws_pt_unlock(pt);
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
assert(!!pt->ah_wait_list_length == !!(int)(long)pt->ah_wait_list);
|
||||
|
@ -675,7 +692,9 @@ lws_parse(struct lws *wsi, unsigned char c)
|
|||
goto swallow;
|
||||
}
|
||||
/* uriencoded = in the name part, disallow */
|
||||
if (c == '=' && enc && !wsi->u.hdr.post_literal_equal)
|
||||
if (c == '=' && enc &&
|
||||
ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] &&
|
||||
!wsi->u.hdr.post_literal_equal)
|
||||
c = '_';
|
||||
|
||||
/* after the real =, we don't care how many = */
|
||||
|
@ -968,34 +987,67 @@ LWS_VISIBLE int lws_frame_is_binary(struct lws *wsi)
|
|||
return wsi->u.ws.frame_is_binary;
|
||||
}
|
||||
|
||||
void
|
||||
lws_add_wsi_to_draining_ext_list(struct lws *wsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
|
||||
if (wsi->u.ws.rx_draining_ext)
|
||||
return;
|
||||
|
||||
lwsl_ext("%s: RX EXT DRAINING: Adding to list\n", __func__);
|
||||
|
||||
wsi->u.ws.rx_draining_ext = 1;
|
||||
wsi->u.ws.rx_draining_ext_list = pt->rx_draining_ext_list;
|
||||
pt->rx_draining_ext_list = wsi;
|
||||
}
|
||||
|
||||
void
|
||||
lws_remove_wsi_from_draining_ext_list(struct lws *wsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
struct lws **w = &pt->rx_draining_ext_list;
|
||||
|
||||
if (!wsi->u.ws.rx_draining_ext)
|
||||
return;
|
||||
|
||||
lwsl_ext("%s: RX EXT DRAINING: Removing from list\n", __func__);
|
||||
|
||||
wsi->u.ws.rx_draining_ext = 0;
|
||||
|
||||
/* remove us from context draining ext list */
|
||||
while (*w) {
|
||||
if (*w == wsi) {
|
||||
/* if us, point it instead to who we were pointing to */
|
||||
*w = wsi->u.ws.rx_draining_ext_list;
|
||||
break;
|
||||
}
|
||||
w = &((*w)->u.ws.rx_draining_ext_list);
|
||||
}
|
||||
wsi->u.ws.rx_draining_ext_list = NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
lws_rx_sm(struct lws *wsi, unsigned char c)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
int callback_action = LWS_CALLBACK_RECEIVE;
|
||||
int ret = 0, n, rx_draining_ext = 0;
|
||||
struct lws_tokens eff_buf;
|
||||
|
||||
eff_buf.token = NULL;
|
||||
eff_buf.token_len = 0;
|
||||
|
||||
if (wsi->socket_is_permanently_unusable)
|
||||
return -1;
|
||||
|
||||
|
||||
switch (wsi->lws_rx_parse_state) {
|
||||
case LWS_RXPS_NEW:
|
||||
if (wsi->u.ws.rx_draining_ext) {
|
||||
struct lws **w = &pt->rx_draining_ext_list;
|
||||
|
||||
eff_buf.token = NULL;
|
||||
eff_buf.token_len = 0;
|
||||
wsi->u.ws.rx_draining_ext = 0;
|
||||
/* remove us from context draining ext list */
|
||||
while (*w) {
|
||||
if (*w == wsi) {
|
||||
*w = wsi->u.ws.rx_draining_ext_list;
|
||||
break;
|
||||
}
|
||||
w = &((*w)->u.ws.rx_draining_ext_list);
|
||||
}
|
||||
wsi->u.ws.rx_draining_ext_list = NULL;
|
||||
lws_remove_wsi_from_draining_ext_list(wsi);
|
||||
rx_draining_ext = 1;
|
||||
lwsl_err("%s: doing draining flow\n", __func__);
|
||||
|
||||
|
@ -1251,6 +1303,9 @@ handle_first:
|
|||
case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
|
||||
assert(wsi->u.ws.rx_ubuf);
|
||||
|
||||
if (wsi->u.ws.rx_draining_ext)
|
||||
goto drain_extension;
|
||||
|
||||
if (wsi->u.ws.rx_ubuf_head + LWS_PRE >=
|
||||
wsi->u.ws.rx_ubuf_alloc) {
|
||||
lwsl_err("Attempted overflow \n");
|
||||
|
@ -1411,6 +1466,9 @@ drain_extension:
|
|||
goto already_done;
|
||||
|
||||
n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &eff_buf, 0);
|
||||
/* eff_buf may be pointing somewhere completely different now,
|
||||
* it's the output
|
||||
*/
|
||||
if (n < 0) {
|
||||
/*
|
||||
* we may rely on this to get RX, just drop connection
|
||||
|
@ -1422,12 +1480,11 @@ drain_extension:
|
|||
if (rx_draining_ext && eff_buf.token_len == 0)
|
||||
goto already_done;
|
||||
|
||||
if (n && eff_buf.token_len) {
|
||||
if (n && eff_buf.token_len)
|
||||
/* extension had more... main loop will come back */
|
||||
wsi->u.ws.rx_draining_ext = 1;
|
||||
wsi->u.ws.rx_draining_ext_list = pt->rx_draining_ext_list;
|
||||
pt->rx_draining_ext_list = wsi;
|
||||
}
|
||||
lws_add_wsi_to_draining_ext_list(wsi);
|
||||
else
|
||||
lws_remove_wsi_from_draining_ext_list(wsi);
|
||||
|
||||
if (eff_buf.token_len > 0 ||
|
||||
callback_action == LWS_CALLBACK_RECEIVE_PONG) {
|
||||
|
@ -1492,7 +1549,7 @@ lws_remaining_packet_payload(struct lws *wsi)
|
|||
* to expect in that state and can deal with it in bulk more efficiently.
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
lws_payload_until_length_exhausted(struct lws *wsi, unsigned char **buf,
|
||||
size_t *len)
|
||||
{
|
||||
|
@ -1517,7 +1574,7 @@ lws_payload_until_length_exhausted(struct lws *wsi, unsigned char **buf,
|
|||
|
||||
/* we want to leave 1 byte for the parser to handle properly */
|
||||
if (avail <= 1)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
avail--;
|
||||
rx_ubuf = wsi->u.ws.rx_ubuf + LWS_PRE + wsi->u.ws.rx_ubuf_head;
|
||||
|
@ -1547,4 +1604,6 @@ lws_payload_until_length_exhausted(struct lws *wsi, unsigned char **buf,
|
|||
wsi->u.ws.rx_ubuf_head += avail;
|
||||
wsi->u.ws.rx_packet_length -= avail;
|
||||
*len -= avail;
|
||||
|
||||
return avail;
|
||||
}
|
||||
|
|
|
@ -82,12 +82,13 @@
|
|||
#include <in6addr.h>
|
||||
#endif
|
||||
#include <mstcpip.h>
|
||||
#include <io.h>
|
||||
|
||||
#ifndef __func__
|
||||
#define __func__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
#if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(_WIN32_WCE)
|
||||
#define vsnprintf _vsnprintf
|
||||
#else
|
||||
#ifdef LWS_HAVE__VSNPRINTF
|
||||
|
@ -96,7 +97,7 @@
|
|||
#endif
|
||||
|
||||
#ifdef LWS_HAVE__SNPRINTF
|
||||
#define snprintf _snprintf
|
||||
#define lws_snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#else /* not windows --> */
|
||||
|
@ -193,6 +194,7 @@ static inline int compatible_close(int fd) { return close(fd); }
|
|||
#else
|
||||
#include <wolfssl/openssl/ssl.h>
|
||||
#include <wolfssl/error-ssl.h>
|
||||
#define OPENSSL_NO_TLSEXT
|
||||
#endif /* not USE_OLD_CYASSL */
|
||||
#else
|
||||
#if defined(LWS_USE_POLARSSL)
|
||||
|
@ -220,6 +222,16 @@ static inline int compatible_close(int fd) { return close(fd); }
|
|||
#ifdef LWS_HAVE_OPENSSL_ECDH_H
|
||||
#include <openssl/ecdh.h>
|
||||
#endif
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x0009080afL)
|
||||
/* later openssl defines this to negate the presence of tlsext... but it was only
|
||||
* introduced at 0.9.8j. Earlier versions don't know it exists so don't
|
||||
* define it... making it look like the feature exists...
|
||||
*/
|
||||
#define OPENSSL_NO_TLSEXT
|
||||
#endif
|
||||
|
||||
#endif /* not USE_MBEDTLS */
|
||||
#endif /* not USE_POLARSSL */
|
||||
#endif /* not USE_WOLFSSL */
|
||||
|
@ -625,7 +637,7 @@ struct lws_context_per_thread {
|
|||
* vhostwide SSL context
|
||||
* vhostwide proxy
|
||||
*
|
||||
* heirarchy:
|
||||
* hierarchy:
|
||||
*
|
||||
* context -> vhost -> wsi
|
||||
*
|
||||
|
@ -678,6 +690,7 @@ struct lws_vhost {
|
|||
int allow_non_ssl_on_ssl_port;
|
||||
unsigned int user_supplied_ssl_ctx:1;
|
||||
#endif
|
||||
unsigned char default_protocol_index;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -884,7 +897,7 @@ enum uri_esc_states {
|
|||
#ifndef LWS_NO_CLIENT
|
||||
struct client_info_stash {
|
||||
char address[256];
|
||||
char path[1024];
|
||||
char path[4096];
|
||||
char host[256];
|
||||
char origin[256];
|
||||
char protocol[256];
|
||||
|
@ -1269,7 +1282,7 @@ struct lws {
|
|||
unsigned int extension_data_pending:1;
|
||||
#endif
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
unsigned int use_ssl:2;
|
||||
unsigned int use_ssl:3;
|
||||
unsigned int upgraded:1;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
|
@ -1304,7 +1317,7 @@ struct lws {
|
|||
LWS_EXTERN int log_level;
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_socket_bind(struct lws_vhost *vhost, int sockfd, int port,
|
||||
lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
|
||||
const char *iface);
|
||||
|
||||
LWS_EXTERN void
|
||||
|
@ -1432,7 +1445,7 @@ lws_client_interpret_server_handshake(struct lws *wsi);
|
|||
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||||
lws_rx_sm(struct lws *wsi, unsigned char c);
|
||||
|
||||
LWS_EXTERN void
|
||||
LWS_EXTERN int
|
||||
lws_payload_until_length_exhausted(struct lws *wsi, unsigned char **buf, size_t *len);
|
||||
|
||||
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||||
|
@ -1486,6 +1499,9 @@ void lws_http2_configure_if_upgraded(struct lws *wsi);
|
|||
LWS_EXTERN int
|
||||
lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_plat_check_connection_error(struct lws *wsi);
|
||||
|
||||
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||||
lws_header_table_attach(struct lws *wsi, int autoservice);
|
||||
|
||||
|
@ -1612,6 +1628,13 @@ lws_pt_mutex_init(struct lws_context_per_thread *pt)
|
|||
{
|
||||
pthread_mutex_init(&pt->lock, NULL);
|
||||
}
|
||||
|
||||
static LWS_INLINE void
|
||||
lws_pt_mutex_destroy(struct lws_context_per_thread *pt)
|
||||
{
|
||||
pthread_mutex_destroy(&pt->lock);
|
||||
}
|
||||
|
||||
static LWS_INLINE void
|
||||
lws_pt_lock(struct lws_context_per_thread *pt)
|
||||
{
|
||||
|
@ -1625,6 +1648,7 @@ lws_pt_unlock(struct lws_context_per_thread *pt)
|
|||
}
|
||||
#else
|
||||
#define lws_pt_mutex_init(_a) (void)(_a)
|
||||
#define lws_pt_mutex_destroy(_a) (void)(_a)
|
||||
#define lws_pt_lock(_a) (void)(_a)
|
||||
#define lws_pt_unlock(_a) (void)(_a)
|
||||
#endif
|
||||
|
@ -1751,6 +1775,10 @@ lws_plat_service_periodic(struct lws_context *context);
|
|||
LWS_EXTERN int
|
||||
lws_plat_change_pollfd(struct lws_context *context, struct lws *wsi,
|
||||
struct lws_pollfd *pfd);
|
||||
LWS_EXTERN void
|
||||
lws_add_wsi_to_draining_ext_list(struct lws *wsi);
|
||||
LWS_EXTERN void
|
||||
lws_remove_wsi_from_draining_ext_list(struct lws *wsi);
|
||||
LWS_EXTERN int
|
||||
lws_plat_context_early_init(void);
|
||||
LWS_EXTERN void
|
||||
|
|
|
@ -6,6 +6,11 @@ lws_rewrite_create(struct lws *wsi, hubbub_callback_t cb, const char *from, cons
|
|||
{
|
||||
struct lws_rewrite *r = lws_malloc(sizeof(*r));
|
||||
|
||||
if (!r) {
|
||||
lwsl_err("OOM\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hubbub_parser_create("UTF-8", false, &r->parser) != HUBBUB_OK) {
|
||||
lws_free(r);
|
||||
|
||||
|
|
|
@ -214,12 +214,14 @@ handshake_0405(struct lws_context *context, struct lws *wsi)
|
|||
strcpy(p, (char *)pt->serv_buf);
|
||||
p += accept_len;
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL)) {
|
||||
/* we can only return the protocol header if:
|
||||
* - one came in, and ... */
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) &&
|
||||
/* - it is not an empty string */
|
||||
wsi->protocol->name &&
|
||||
wsi->protocol->name[0]) {
|
||||
LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Protocol: ");
|
||||
n = lws_hdr_copy(wsi, p, 128, WSI_TOKEN_PROTOCOL);
|
||||
if (n < 0)
|
||||
goto bail;
|
||||
p += n;
|
||||
p += lws_snprintf(p, 128, "%s", wsi->protocol->name);
|
||||
}
|
||||
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
|
|
216
lib/server.c
216
lib/server.c
|
@ -67,7 +67,7 @@ lws_context_init_server(struct lws_context_creation_info *info,
|
|||
else
|
||||
#endif
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context))
|
||||
if (LWS_IPV6_ENABLED(vhost->context))
|
||||
sockfd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
else
|
||||
#endif
|
||||
|
@ -132,7 +132,15 @@ lws_context_init_server(struct lws_context_creation_info *info,
|
|||
vhost->lserv_wsi = wsi;
|
||||
|
||||
#if LWS_POSIX
|
||||
listen(wsi->sock, LWS_SOMAXCONN);
|
||||
n = listen(wsi->sock, LWS_SOMAXCONN);
|
||||
if (n < 0) {
|
||||
lwsl_err("listen failed with error %d\n", LWS_ERRNO);
|
||||
vhost->lserv_wsi = NULL;
|
||||
vhost->context->count_wsi_allocated--;
|
||||
remove_wsi_socket_from_fds(wsi);
|
||||
vhost->context->pt[m].wsi_listening = NULL;
|
||||
goto bail;
|
||||
}
|
||||
} /* for each thread able to independently listen */
|
||||
#else
|
||||
mbed3_tcp_stream_bind(wsi->sock, info->port, wsi);
|
||||
|
@ -179,22 +187,59 @@ struct lws_vhost *
|
|||
lws_select_vhost(struct lws_context *context, int port, const char *servername)
|
||||
{
|
||||
struct lws_vhost *vhost = context->vhost_list;
|
||||
const char *p;
|
||||
int n, m, colon;
|
||||
|
||||
n = strlen(servername);
|
||||
colon = n;
|
||||
p = strchr(servername, ':');
|
||||
if (p)
|
||||
colon = p - servername;
|
||||
|
||||
/* first try exact matches */
|
||||
|
||||
while (vhost) {
|
||||
if (port == vhost->listen_port &&
|
||||
!strcmp(vhost->name, servername)) {
|
||||
!strncmp(vhost->name, servername, colon)) {
|
||||
lwsl_info("SNI: Found: %s\n", servername);
|
||||
return vhost;
|
||||
}
|
||||
vhost = vhost->vhost_next;
|
||||
}
|
||||
|
||||
/*
|
||||
* if no exact matches, try matching *.vhost-name
|
||||
* unintentional matches are possible but resolve to x.com for *.x.com
|
||||
* which is reasonable. If exact match exists we already chose it and
|
||||
* never reach here. SSL will still fail it if the cert doesn't allow
|
||||
* *.x.com.
|
||||
*/
|
||||
|
||||
vhost = context->vhost_list;
|
||||
while (vhost) {
|
||||
m = strlen(vhost->name);
|
||||
if (port == vhost->listen_port &&
|
||||
m <= (colon - 2) &&
|
||||
servername[colon - m - 1] == '.' &&
|
||||
!strncmp(vhost->name, servername + colon - m, m)) {
|
||||
lwsl_info("SNI: Found %s on wildcard: %s\n",
|
||||
servername, vhost->name);
|
||||
return vhost;
|
||||
}
|
||||
vhost = vhost->vhost_next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char * get_mimetype(const char *file)
|
||||
static const char *
|
||||
get_mimetype(const char *file, const struct lws_http_mount *m)
|
||||
{
|
||||
int n = strlen(file);
|
||||
const struct lws_protocol_vhost_options *pvo = NULL;
|
||||
|
||||
if (m)
|
||||
pvo = m->extra_mimetypes;
|
||||
|
||||
if (n < 5)
|
||||
return NULL;
|
||||
|
@ -214,22 +259,51 @@ static const char * get_mimetype(const char *file)
|
|||
if (!strcmp(&file[n - 4], ".jpg"))
|
||||
return "image/jpeg";
|
||||
|
||||
if (!strcmp(&file[n - 3], ".gz"))
|
||||
return "application/gzip";
|
||||
|
||||
if (!strcmp(&file[n - 4], ".JPG"))
|
||||
return "image/jpeg";
|
||||
|
||||
if (!strcmp(&file[n - 5], ".html"))
|
||||
return "text/html";
|
||||
|
||||
if (!strcmp(&file[n - 4], ".css"))
|
||||
return "text/css";
|
||||
|
||||
if (!strcmp(&file[n - 4], ".txt"))
|
||||
return "text/plain";
|
||||
|
||||
if (!strcmp(&file[n - 4], ".svg"))
|
||||
return "image/svg+xml";
|
||||
|
||||
if (!strcmp(&file[n - 4], ".ttf"))
|
||||
return "application/x-font-ttf";
|
||||
|
||||
if (!strcmp(&file[n - 5], ".woff"))
|
||||
return "application/font-woff";
|
||||
|
||||
if (!strcmp(&file[n - 4], ".xml"))
|
||||
return "application/xml";
|
||||
|
||||
while (pvo) {
|
||||
if (!strcmp(&file[n - strlen(pvo->name)], pvo->name))
|
||||
return pvo->value;
|
||||
|
||||
pvo = pvo->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lws_http_serve(struct lws *wsi, char *uri, const char *origin)
|
||||
static int
|
||||
lws_http_serve(struct lws *wsi, char *uri, const char *origin,
|
||||
const struct lws_http_mount *m)
|
||||
{
|
||||
const char *mimetype;
|
||||
#ifndef _WIN32_WCE
|
||||
struct stat st;
|
||||
#endif
|
||||
char path[256], sym[256];
|
||||
unsigned char *p = (unsigned char *)sym + 32 + LWS_PRE, *start = p;
|
||||
unsigned char *end = p + sizeof(sym) - 32 - LWS_PRE;
|
||||
|
@ -238,8 +312,9 @@ int lws_http_serve(struct lws *wsi, char *uri, const char *origin)
|
|||
#endif
|
||||
int n, spin = 0;
|
||||
|
||||
snprintf(path, sizeof(path) - 1, "%s/%s", origin, uri);
|
||||
lws_snprintf(path, sizeof(path) - 1, "%s/%s", origin, uri);
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
do {
|
||||
spin++;
|
||||
|
||||
|
@ -258,12 +333,12 @@ int lws_http_serve(struct lws *wsi, char *uri, const char *origin)
|
|||
}
|
||||
sym[len] = '\0';
|
||||
lwsl_debug("symlink %s -> %s\n", path, sym);
|
||||
snprintf(path, sizeof(path) - 1, "%s", sym);
|
||||
lws_snprintf(path, sizeof(path) - 1, "%s", sym);
|
||||
}
|
||||
#endif
|
||||
if ((S_IFMT & st.st_mode) == S_IFDIR) {
|
||||
lwsl_debug("default filename append to dir\n");
|
||||
snprintf(path, sizeof(path) - 1, "%s/%s/index.html",
|
||||
lws_snprintf(path, sizeof(path) - 1, "%s/%s/index.html",
|
||||
origin, uri);
|
||||
}
|
||||
|
||||
|
@ -309,8 +384,9 @@ int lws_http_serve(struct lws *wsi, char *uri, const char *origin)
|
|||
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_ETAG,
|
||||
(unsigned char *)sym, n, &p, end))
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
mimetype = get_mimetype(path);
|
||||
mimetype = get_mimetype(path, m);
|
||||
if (!mimetype) {
|
||||
lwsl_err("unknown mimetype for %s", path);
|
||||
goto bail;
|
||||
|
@ -519,34 +595,39 @@ lws_http_action(struct lws *wsi)
|
|||
lws_access_log(wsi);
|
||||
|
||||
wsi->access_log.header_log = lws_malloc(l);
|
||||
if (wsi->access_log.header_log) {
|
||||
|
||||
tmp = localtime(&t);
|
||||
if (tmp)
|
||||
strftime(da, sizeof(da), "%d/%b/%Y:%H:%M:%S %z", tmp);
|
||||
else
|
||||
strcpy(da, "01/Jan/1970:00:00:00 +0000");
|
||||
tmp = localtime(&t);
|
||||
if (tmp)
|
||||
strftime(da, sizeof(da), "%d/%b/%Y:%H:%M:%S %z", tmp);
|
||||
else
|
||||
strcpy(da, "01/Jan/1970:00:00:00 +0000");
|
||||
|
||||
pa = lws_get_peer_simple(wsi, ads, sizeof(ads));
|
||||
if (!pa)
|
||||
pa = "(unknown)";
|
||||
pa = lws_get_peer_simple(wsi, ads, sizeof(ads));
|
||||
if (!pa)
|
||||
pa = "(unknown)";
|
||||
|
||||
if (meth >= 0)
|
||||
me = method_names[meth];
|
||||
else
|
||||
me = "unknown";
|
||||
if (meth >= 0)
|
||||
me = method_names[meth];
|
||||
else
|
||||
me = "unknown";
|
||||
|
||||
snprintf(wsi->access_log.header_log, l,
|
||||
"%s - - [%s] \"%s %s %s\"",
|
||||
pa, da, me, uri_ptr,
|
||||
hver[wsi->u.http.request_version]);
|
||||
lws_snprintf(wsi->access_log.header_log, l,
|
||||
"%s - - [%s] \"%s %s %s\"",
|
||||
pa, da, me, uri_ptr,
|
||||
hver[wsi->u.http.request_version]);
|
||||
|
||||
l = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_USER_AGENT);
|
||||
if (l) {
|
||||
wsi->access_log.user_agent = lws_malloc(l + 2);
|
||||
lws_hdr_copy(wsi, wsi->access_log.user_agent,
|
||||
l + 1, WSI_TOKEN_HTTP_USER_AGENT);
|
||||
l = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_USER_AGENT);
|
||||
if (l) {
|
||||
wsi->access_log.user_agent = lws_malloc(l + 2);
|
||||
if (wsi->access_log.user_agent)
|
||||
lws_hdr_copy(wsi, wsi->access_log.user_agent,
|
||||
l + 1, WSI_TOKEN_HTTP_USER_AGENT);
|
||||
else
|
||||
lwsl_err("OOM getting user agent\n");
|
||||
}
|
||||
wsi->access_log_pending = 1;
|
||||
}
|
||||
wsi->access_log_pending = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -606,11 +687,11 @@ lws_http_action(struct lws *wsi)
|
|||
|
||||
/* > at start indicates deal with by redirect */
|
||||
if (hit->origin_protocol & 4)
|
||||
n = snprintf((char *)end, 256, "%s%s",
|
||||
n = lws_snprintf((char *)end, 256, "%s%s",
|
||||
oprot[hit->origin_protocol & 1],
|
||||
hit->origin);
|
||||
else
|
||||
n = snprintf((char *)end, 256,
|
||||
n = lws_snprintf((char *)end, 256,
|
||||
"https://%s/%s/",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST),
|
||||
uri_ptr);
|
||||
|
@ -672,7 +753,7 @@ lws_http_action(struct lws *wsi)
|
|||
wsi->cache_revalidate = hit->cache_revalidate;
|
||||
wsi->cache_intermediaries = hit->cache_intermediaries;
|
||||
|
||||
n = lws_http_serve(wsi, s, hit->origin);
|
||||
n = lws_http_serve(wsi, s, hit->origin, hit);
|
||||
if (n) {
|
||||
/*
|
||||
* lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
|
||||
|
@ -726,11 +807,18 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
|||
struct allocated_headers *ah;
|
||||
int protocol_len, n, hit;
|
||||
char protocol_list[128];
|
||||
char protocol_name[32];
|
||||
char protocol_name[64];
|
||||
char *p;
|
||||
|
||||
assert(len < 10000000);
|
||||
assert(wsi->u.hdr.ah);
|
||||
if (len >= 10000000) {
|
||||
lwsl_err("%s: assert: len %ld\n", __func__, (long)len);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (!wsi->u.hdr.ah) {
|
||||
lwsl_err("%s: assert: NULL ah\n", __func__);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
wsi->more_rx_waiting = !!len;
|
||||
|
@ -762,7 +850,8 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
|||
|
||||
if (vhost)
|
||||
wsi->vhost = vhost;
|
||||
}
|
||||
} else
|
||||
lwsl_info("no host\n");
|
||||
|
||||
wsi->vhost->trans++;
|
||||
if (!wsi->conn_stat_done) {
|
||||
|
@ -790,7 +879,7 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
|||
goto upgrade_h2c;
|
||||
}
|
||||
#endif
|
||||
lwsl_err("Unknown upgrade\n");
|
||||
lwsl_info("Unknown upgrade\n");
|
||||
/* dunno what he wanted to upgrade to */
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
@ -816,11 +905,11 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
|||
#ifdef LWS_USE_HTTP2
|
||||
upgrade_h2c:
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP2_SETTINGS)) {
|
||||
lwsl_err("missing http2_settings\n");
|
||||
lwsl_info("missing http2_settings\n");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
lwsl_err("h2c upgrade...\n");
|
||||
lwsl_info("h2c upgrade...\n");
|
||||
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP2_SETTINGS);
|
||||
/* convert the peer's HTTP-Settings */
|
||||
|
@ -916,18 +1005,21 @@ upgrade_ws:
|
|||
|
||||
if (!hit) {
|
||||
if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL)) {
|
||||
lwsl_err("No protocol from \"%s\" supported\n",
|
||||
lwsl_info("No protocol from \"%s\" supported\n",
|
||||
protocol_list);
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
/*
|
||||
* some clients only have one protocol and
|
||||
* do not send the protocol list header...
|
||||
* allow it and match to protocol 0
|
||||
* allow it and match to the vhost's default
|
||||
* protocol (which itself defaults to zero)
|
||||
*/
|
||||
lwsl_info("defaulting to prot 0 handler\n");
|
||||
lwsl_info("defaulting to prot handler %d\n",
|
||||
wsi->vhost->default_protocol_index);
|
||||
n = 0;
|
||||
wsi->protocol = &wsi->vhost->protocols[0];
|
||||
wsi->protocol = &wsi->vhost->protocols[
|
||||
(int)wsi->vhost->default_protocol_index];
|
||||
}
|
||||
|
||||
/* allocate wsi->user storage */
|
||||
|
@ -961,7 +1053,7 @@ upgrade_ws:
|
|||
break;
|
||||
|
||||
default:
|
||||
lwsl_warn("Unknown client spec version %d\n",
|
||||
lwsl_info("Unknown client spec version %d\n",
|
||||
wsi->ietf_spec_revision);
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
@ -1105,7 +1197,7 @@ lws_create_new_server_wsi(struct lws_vhost *vhost)
|
|||
new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
|
||||
new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
|
||||
|
||||
/* intialize the instance struct */
|
||||
/* initialize the instance struct */
|
||||
|
||||
new_wsi->state = LWSS_HTTP;
|
||||
new_wsi->mode = LWSCM_HTTP_SERVING;
|
||||
|
@ -1234,6 +1326,8 @@ lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd)
|
|||
*/
|
||||
if ((context->vhost_list->protocols[0].callback)(new_wsi,
|
||||
LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED, NULL, NULL, 0)) {
|
||||
/* force us off the timeout list by hand */
|
||||
lws_set_timeout(new_wsi, NO_PENDING_TIMEOUT, 0);
|
||||
compatible_close(new_wsi->sock);
|
||||
lws_free(new_wsi);
|
||||
return NULL;
|
||||
|
@ -1369,6 +1463,10 @@ lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
|
|||
* below to the rx buffer (via lws_header_table_reset()).
|
||||
*/
|
||||
wsi->u.hdr.preamble_rx = lws_malloc(len);
|
||||
if (!wsi->u.hdr.preamble_rx) {
|
||||
lwsl_err("OOM\n");
|
||||
goto bail;
|
||||
}
|
||||
memcpy(wsi->u.hdr.preamble_rx, readbuf, len);
|
||||
wsi->u.hdr.preamble_rx_len = len;
|
||||
|
||||
|
@ -1443,7 +1541,7 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi,
|
|||
wsi->state == LWSS_HTTP_ISSUING_FILE ||
|
||||
wsi->state == LWSS_HTTP_HEADERS) {
|
||||
if (!wsi->u.hdr.ah)
|
||||
/* no autoservice beacuse we will do it next */
|
||||
/* no autoservice because we will do it next */
|
||||
if (lws_header_table_attach(wsi, 0))
|
||||
goto try_pollout;
|
||||
|
||||
|
@ -1473,7 +1571,12 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi,
|
|||
goto try_pollout;
|
||||
}
|
||||
}
|
||||
assert(ah->rxpos != ah->rxlen && ah->rxlen);
|
||||
if (!(ah->rxpos != ah->rxlen && ah->rxlen)) {
|
||||
lwsl_err("%s: assert: rxpos %d, rxlen %d\n",
|
||||
__func__, ah->rxpos, ah->rxlen);
|
||||
|
||||
assert(0);
|
||||
}
|
||||
/* just ignore incoming if waiting for close */
|
||||
if (wsi->state != LWSS_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
|
||||
n = lws_read(wsi, ah->rx + ah->rxpos,
|
||||
|
@ -1484,6 +1587,8 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi,
|
|||
if ( wsi->u.hdr.ah->rxlen)
|
||||
wsi->u.hdr.ah->rxpos += n;
|
||||
|
||||
lwsl_debug("%s: wsi %p: ah read rxpos %d, rxlen %d\n", __func__, wsi, wsi->u.hdr.ah->rxpos, wsi->u.hdr.ah->rxlen);
|
||||
|
||||
if (wsi->u.hdr.ah->rxpos == wsi->u.hdr.ah->rxlen &&
|
||||
(wsi->mode != LWSCM_HTTP_SERVING &&
|
||||
wsi->mode != LWSCM_HTTP_SERVING_ACCEPTED &&
|
||||
|
@ -1585,7 +1690,7 @@ try_pollout:
|
|||
if (accept_fd < 0) {
|
||||
if (LWS_ERRNO == LWS_EAGAIN ||
|
||||
LWS_ERRNO == LWS_EWOULDBLOCK) {
|
||||
lwsl_err("accept asks to try again\n");
|
||||
// lwsl_err("accept asks to try again\n");
|
||||
break;
|
||||
}
|
||||
lwsl_err("ERROR on accept: %s\n", strerror(LWS_ERRNO));
|
||||
|
@ -1749,6 +1854,7 @@ lws_interpret_incoming_packet(struct lws *wsi, unsigned char **buf, size_t len)
|
|||
}
|
||||
|
||||
if (wsi->u.ws.rx_draining_ext) {
|
||||
// lwsl_notice("draining with 0\n");
|
||||
m = lws_rx_sm(wsi, 0);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
|
@ -1760,9 +1866,13 @@ lws_interpret_incoming_packet(struct lws *wsi, unsigned char **buf, size_t len)
|
|||
wsi->rxflow_pos++;
|
||||
|
||||
/* consume payload bytes efficiently */
|
||||
if (wsi->lws_rx_parse_state ==
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED)
|
||||
lws_payload_until_length_exhausted(wsi, buf, &len);
|
||||
if (
|
||||
wsi->lws_rx_parse_state ==
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED) {
|
||||
m = lws_payload_until_length_exhausted(wsi, buf, &len);
|
||||
if (wsi->rxflow_buffer)
|
||||
wsi->rxflow_pos += m;
|
||||
}
|
||||
|
||||
/* process the byte */
|
||||
m = lws_rx_sm(wsi, *(*buf)++);
|
||||
|
|
|
@ -368,6 +368,8 @@ int lws_rxflow_cache(struct lws *wsi, unsigned char *buf, int n, int len)
|
|||
/* a new rxflow, buffer it and warn caller */
|
||||
lwsl_info("new rxflow input buffer len %d\n", len - n);
|
||||
wsi->rxflow_buffer = lws_malloc(len - n);
|
||||
if (!wsi->rxflow_buffer)
|
||||
return -1;
|
||||
wsi->rxflow_len = len - n;
|
||||
wsi->rxflow_pos = 0;
|
||||
memcpy(wsi->rxflow_buffer, buf + n, len - n);
|
||||
|
@ -406,7 +408,10 @@ lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi)
|
|||
for (n = 0; n < context->max_http_header_pool; n++)
|
||||
if (pt->ah_pool[n].rxpos != pt->ah_pool[n].rxlen) {
|
||||
/* any ah with pending rx must be attached to someone */
|
||||
assert(pt->ah_pool[n].wsi);
|
||||
if (!pt->ah_pool[n].wsi) {
|
||||
lwsl_err("%s: assert: no wsi attached to ah\n", __func__);
|
||||
assert(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -440,9 +445,10 @@ lws_service_flag_pending(struct lws_context *context, int tsi)
|
|||
while (wsi) {
|
||||
pt->fds[wsi->position_in_fds_table].revents |=
|
||||
pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN;
|
||||
if (pt->fds[wsi->position_in_fds_table].revents &
|
||||
LWS_POLLIN)
|
||||
if (pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN) {
|
||||
forced = 1;
|
||||
break;
|
||||
}
|
||||
wsi = wsi->u.ws.rx_draining_ext_list;
|
||||
}
|
||||
|
||||
|
@ -605,7 +611,10 @@ spin_chunks:
|
|||
if (wsi->chunked)
|
||||
return 0;
|
||||
|
||||
wsi->u.http.content_remain -= n;
|
||||
/* if we know the content length, decrement the content remaining */
|
||||
if (wsi->u.http.content_length > 0)
|
||||
wsi->u.http.content_remain -= n;
|
||||
|
||||
if (wsi->u.http.content_remain || !wsi->u.http.content_length)
|
||||
return 0;
|
||||
|
||||
|
@ -622,6 +631,17 @@ completed:
|
|||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
lws_is_ws_with_ext(struct lws *wsi)
|
||||
{
|
||||
#if defined(LWS_NO_EXTENSIONS)
|
||||
return 0;
|
||||
#else
|
||||
return wsi->state == LWSS_ESTABLISHED &&
|
||||
!!wsi->count_act_ext;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* lws_service_fd() - Service polled socket with something waiting
|
||||
* @context: Websocket context
|
||||
|
@ -886,9 +906,24 @@ read:
|
|||
wsi->u.hdr.ah->rxpos;
|
||||
} else {
|
||||
if (wsi->mode != LWSCM_HTTP_CLIENT_ACCEPTED) {
|
||||
/*
|
||||
* extension may not consume everything (eg, pmd may be constrained
|
||||
* as to what it can output...) has to go in per-wsi rx buf area.
|
||||
* Otherwise in large temp serv_buf area.
|
||||
*/
|
||||
eff_buf.token = (char *)pt->serv_buf;
|
||||
if (lws_is_ws_with_ext(wsi)) {
|
||||
eff_buf.token_len = wsi->u.ws.rx_ubuf_alloc;
|
||||
} else {
|
||||
eff_buf.token_len = LWS_MAX_SOCKET_IO_BUF;
|
||||
}
|
||||
|
||||
if (eff_buf.token_len > LWS_MAX_SOCKET_IO_BUF)
|
||||
eff_buf.token_len = LWS_MAX_SOCKET_IO_BUF;
|
||||
|
||||
eff_buf.token_len = lws_ssl_capable_read(wsi,
|
||||
pt->serv_buf, pending ? pending :
|
||||
LWS_MAX_SOCKET_IO_BUF);
|
||||
(unsigned char *)eff_buf.token, pending ? pending :
|
||||
eff_buf.token_len);
|
||||
switch (eff_buf.token_len) {
|
||||
case 0:
|
||||
lwsl_info("%s: zero length read\n", __func__);
|
||||
|
@ -901,8 +936,7 @@ read:
|
|||
lwsl_info("Closing when error\n");
|
||||
goto close_and_handled;
|
||||
}
|
||||
|
||||
eff_buf.token = (char *)pt->serv_buf;
|
||||
// lwsl_notice("Actual RX %d\n", eff_buf.token_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -918,7 +952,7 @@ drain:
|
|||
lws_change_pollfd(wsi, LWS_POLLIN, 0);
|
||||
|
||||
/* let user code know, he'll usually ask for writeable
|
||||
* callback and drain / reenable it there
|
||||
* callback and drain / re-enable it there
|
||||
*/
|
||||
if (user_callback_handle_rxflow(
|
||||
wsi->protocol->callback,
|
||||
|
@ -958,6 +992,8 @@ drain:
|
|||
* around again it will pick up from where it
|
||||
* left off.
|
||||
*/
|
||||
// lwsl_notice("doing lws_read from pt->serv_buf %p %p for len %d\n", pt->serv_buf, eff_buf.token, (int)eff_buf.token_len);
|
||||
|
||||
n = lws_read(wsi, (unsigned char *)eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
if (n < 0) {
|
||||
|
@ -984,7 +1020,11 @@ drain:
|
|||
|
||||
pending = lws_ssl_pending(wsi);
|
||||
if (pending) {
|
||||
pending = pending > LWS_MAX_SOCKET_IO_BUF ?
|
||||
if (lws_is_ws_with_ext(wsi))
|
||||
pending = pending > wsi->u.ws.rx_ubuf_alloc ?
|
||||
wsi->u.ws.rx_ubuf_alloc : pending;
|
||||
else
|
||||
pending = pending > LWS_MAX_SOCKET_IO_BUF ?
|
||||
LWS_MAX_SOCKET_IO_BUF : pending;
|
||||
goto read;
|
||||
}
|
||||
|
|
|
@ -38,11 +38,51 @@ lws_ssl_client_bio_create(struct lws *wsi)
|
|||
#if defined(LWS_USE_MBEDTLS)
|
||||
#else
|
||||
struct lws_context *context = wsi->context;
|
||||
#if defined(CYASSL_SNI_HOST_NAME) || defined(WOLFSSL_SNI_HOST_NAME) || defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
|
||||
const char *hostname = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST);
|
||||
char hostname[128], *p;
|
||||
|
||||
#if defined LWS_HAVE_X509_VERIFY_PARAM_set1_host
|
||||
X509_VERIFY_PARAM *param;
|
||||
#endif
|
||||
if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
|
||||
_WSI_TOKEN_CLIENT_HOST) <= 0) {
|
||||
lwsl_err("%s: Unable to get hostname\n", __func__);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* remove any :port part on the hostname... necessary for network
|
||||
* connection but typical certificates do not contain it
|
||||
*/
|
||||
p = hostname;
|
||||
while (*p) {
|
||||
if (*p == ':') {
|
||||
*p = '\0';
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
wsi->ssl = SSL_new(wsi->vhost->ssl_client_ctx);
|
||||
if (!wsi->ssl) {
|
||||
lwsl_err("SSL_new failed: %s\n",
|
||||
ERR_error_string(lws_ssl_get_error(wsi, 0), NULL));
|
||||
lws_decode_ssl_error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined LWS_HAVE_X509_VERIFY_PARAM_set1_host
|
||||
{
|
||||
param = SSL_get0_param(wsi->ssl);
|
||||
/* Enable automatic hostname checks */
|
||||
X509_VERIFY_PARAM_set_hostflags(param,
|
||||
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
||||
X509_VERIFY_PARAM_set1_host(param, hostname, 0);
|
||||
/* Configure a non-zero callback if desired */
|
||||
SSL_set_verify(wsi->ssl, SSL_VERIFY_PEER, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef USE_WOLFSSL
|
||||
SSL_set_mode(wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||
#endif
|
||||
|
@ -267,18 +307,17 @@ lws_ssl_client_connect2(struct lws *wsi)
|
|||
lws_latency_pre(context, wsi);
|
||||
n = SSL_get_verify_result(wsi->ssl);
|
||||
lws_latency(context, wsi,
|
||||
"SSL_get_verify_result LWS_CONNMODE..HANDSHAKE",
|
||||
n, n > 0);
|
||||
"SSL_get_verify_result LWS_CONNMODE..HANDSHAKE", n, n > 0);
|
||||
|
||||
if (n != X509_V_OK) {
|
||||
if ((n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
|
||||
n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) && wsi->use_ssl == 2) {
|
||||
n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) &&
|
||||
wsi->use_ssl == 2) {
|
||||
lwsl_notice("accepting self-signed certificate\n");
|
||||
} else {
|
||||
lwsl_err("server's cert didn't look good, X509_V_ERR = %d: %s\n",
|
||||
n, ERR_error_string(n, sb));
|
||||
lws_ssl_elaborate_error();
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
12
lib/ssl.c
12
lib/ssl.c
|
@ -194,10 +194,13 @@ lws_ssl_destroy(struct lws_vhost *vhost)
|
|||
if (!vhost->user_supplied_ssl_ctx && vhost->ssl_client_ctx)
|
||||
SSL_CTX_free(vhost->ssl_client_ctx);
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100006L)
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x01000000) || defined(USE_WOLFSSL)
|
||||
ERR_remove_state(0);
|
||||
#else
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10100005L)
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10100005L) && \
|
||||
!defined(LIBRESSL_VERSION_NUMBER) && \
|
||||
!defined(OPENSSL_IS_BORINGSSL)
|
||||
ERR_remove_thread_state();
|
||||
#else
|
||||
ERR_remove_thread_state(NULL);
|
||||
|
@ -208,6 +211,7 @@ lws_ssl_destroy(struct lws_vhost *vhost)
|
|||
CRYPTO_cleanup_all_ex_data();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
|
@ -686,10 +690,13 @@ lws_ssl_context_destroy(struct lws_context *context)
|
|||
#else
|
||||
#if defined(LWS_USE_MBEDTLS)
|
||||
#else
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100006L)
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x01000000) || defined(USE_WOLFSSL)
|
||||
ERR_remove_state(0);
|
||||
#else
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10100005L)
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10100005L) && \
|
||||
!defined(LIBRESSL_VERSION_NUMBER) && \
|
||||
!defined(OPENSSL_IS_BORINGSSL)
|
||||
ERR_remove_thread_state();
|
||||
#else
|
||||
ERR_remove_thread_state(NULL);
|
||||
|
@ -700,4 +707,5 @@ lws_ssl_context_destroy(struct lws_context *context)
|
|||
CRYPTO_cleanup_all_ex_data();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -219,6 +219,25 @@ context. After calling this, any further use of the context is
|
|||
undefined.
|
||||
</blockquote>
|
||||
<hr>
|
||||
<h2>lws_set_extension_option - </h2>
|
||||
<i>int</i>
|
||||
<b>lws_set_extension_option</b>
|
||||
(<i>struct lws *</i> <b>wsi</b>,
|
||||
<i>const char *</i> <b>ext_name</b>,
|
||||
<i>const char *</i> <b>opt_name</b>,
|
||||
<i>const char *</i> <b>opt_val</b>)
|
||||
<h3>Arguments</h3>
|
||||
<dl>
|
||||
<dt><b>wsi</b>
|
||||
<dd>websocket connection
|
||||
<dt><b>ext_name</b>
|
||||
<dd>name of ext, like "permessage-deflate"
|
||||
<dt><b>opt_name</b>
|
||||
<dd>name of option, like "rx_buf_size"
|
||||
<dt><b>opt_val</b>
|
||||
<dd>value to set option to
|
||||
</dl>
|
||||
<hr>
|
||||
<h2>lws_return_http_status - Return simple http status</h2>
|
||||
<i>int</i>
|
||||
<b>lws_return_http_status</b>
|
||||
|
@ -324,6 +343,22 @@ using globals statics in the user code.
|
|||
<dd>Callback reason index
|
||||
</dl>
|
||||
<hr>
|
||||
<h2>lws_callback_all_protocol_vhost - Callback all connections using the given protocol with the given reason</h2>
|
||||
<i>int</i>
|
||||
<b>lws_callback_all_protocol_vhost</b>
|
||||
(<i>struct lws_vhost *</i> <b>vh</b>,
|
||||
<i>const struct lws_protocols *</i> <b>protocol</b>,
|
||||
<i>int</i> <b>reason</b>)
|
||||
<h3>Arguments</h3>
|
||||
<dl>
|
||||
<dt><b>vh</b>
|
||||
<dd>Vhost whose connections will get callbacks
|
||||
<dt><b>protocol</b>
|
||||
<dd>Which protocol to match
|
||||
<dt><b>reason</b>
|
||||
<dd>Callback reason index
|
||||
</dl>
|
||||
<hr>
|
||||
<h2>lws_get_socket_fd - returns the socket file descriptor</h2>
|
||||
<i>int</i>
|
||||
<b>lws_get_socket_fd</b>
|
||||
|
@ -396,12 +431,10 @@ has been created.
|
|||
<h2>lws_set_proxy - Setups proxy to lws_context.</h2>
|
||||
<i>int</i>
|
||||
<b>lws_set_proxy</b>
|
||||
(<i>struct lws_context *</i> <b>context</b>,
|
||||
(<i>struct lws_vhost *</i> <b>vhost</b>,
|
||||
<i>const char *</i> <b>proxy</b>)
|
||||
<h3>Arguments</h3>
|
||||
<dl>
|
||||
<dt><b>context</b>
|
||||
<dd>pointer to struct lws_context you want set proxy to
|
||||
<dt><b>proxy</b>
|
||||
<dd>pointer to c string containing proxy in format address:port
|
||||
</dl>
|
||||
|
@ -512,6 +545,22 @@ This is never set at the start of a writeable callback, but any write
|
|||
may set it.
|
||||
</blockquote>
|
||||
<hr>
|
||||
<h2>lws_get_context - Allow geting lws_context from a Websocket connection instance</h2>
|
||||
<i>LWS_EXTERN struct lws_context *</i>
|
||||
<b>lws_get_context</b>
|
||||
(<i>const struct lws *</i> <b>wsi</b>)
|
||||
<h3>Arguments</h3>
|
||||
<dl>
|
||||
<dt><b>wsi</b>
|
||||
<dd>Websocket connection instance
|
||||
</dl>
|
||||
<h3>Description</h3>
|
||||
<blockquote>
|
||||
<p>
|
||||
With this function, users can access context in the callback function.
|
||||
Otherwise users may have to declare context as a global variable.
|
||||
</blockquote>
|
||||
<hr>
|
||||
<h2>lws_parse_uri - </h2>
|
||||
<i>LWS_EXTERN int</i>
|
||||
<b>lws_parse_uri</b>
|
||||
|
@ -543,8 +592,10 @@ and the leading / on the path is consequently lost
|
|||
<i>LWS_EXTERN int</i>
|
||||
<b>lws_cgi</b>
|
||||
(<i>struct lws *</i> <b>wsi</b>,
|
||||
<i>char *const *</i> <b>exec_array</b>,
|
||||
<i>int</i> <b>timeout_secs</b>)
|
||||
<i>const char *const *</i> <b>exec_array</b>,
|
||||
<i>int</i> <b>script_uri_path_len</b>,
|
||||
<i>int</i> <b>timeout_secs</b>,
|
||||
<i>const struct lws_protocol_vhost_options *</i> <b>mp_cgienv</b>)
|
||||
<h3>Arguments</h3>
|
||||
<dl>
|
||||
<dt><b>wsi</b>
|
||||
|
@ -553,6 +604,16 @@ and the leading / on the path is consequently lost
|
|||
<dd>array of "exec-name" "arg1" ... "argn" NULL
|
||||
</dl>
|
||||
<hr>
|
||||
<h2>lws_cgi_write_split_stdout_headers - </h2>
|
||||
<i>LWS_EXTERN int</i>
|
||||
<b>lws_cgi_write_split_stdout_headers</b>
|
||||
(<i>struct lws *</i> <b>wsi</b>)
|
||||
<h3>Arguments</h3>
|
||||
<dl>
|
||||
<dt><b>wsi</b>
|
||||
<dd>connection to own the process
|
||||
</dl>
|
||||
<hr>
|
||||
<h2>lws_cgi_kill - </h2>
|
||||
<i>LWS_EXTERN int</i>
|
||||
<b>lws_cgi_kill</b>
|
||||
|
@ -800,6 +861,25 @@ Many protocols won't care becuse their packets are always small.
|
|||
<dd>Websocket connection instance to get callback for
|
||||
</dl>
|
||||
<hr>
|
||||
<h2>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 blocking in turn.</h2>
|
||||
<i>int</i>
|
||||
<b>lws_callback_on_writable_all_protocol_vhost</b>
|
||||
(<i>const struct lws_vhost *</i> <b>vhost</b>,
|
||||
<i>const struct lws_protocols *</i> <b>protocol</b>)
|
||||
<h3>Arguments</h3>
|
||||
<dl>
|
||||
<dt><b>vhost</b>
|
||||
<dd>Only consider connections on this lws_vhost
|
||||
<dt><b>protocol</b>
|
||||
<dd>Protocol whose connections will get callbacks
|
||||
</dl>
|
||||
<h3>Description</h3>
|
||||
<blockquote>
|
||||
<p>
|
||||
This calls back connections with the same protocol ON THE SAME
|
||||
VHOST ONLY.
|
||||
</blockquote>
|
||||
<hr>
|
||||
<h2>lws_callback_on_writable_all_protocol - Request a callback for all connections using the given protocol when it becomes possible to write to each socket without blocking in turn.</h2>
|
||||
<i>int</i>
|
||||
<b>lws_callback_on_writable_all_protocol</b>
|
||||
|
@ -812,6 +892,12 @@ Many protocols won't care becuse their packets are always small.
|
|||
<dt><b>protocol</b>
|
||||
<dd>Protocol whose connections will get callbacks
|
||||
</dl>
|
||||
<h3>Description</h3>
|
||||
<blockquote>
|
||||
<p>
|
||||
This calls back any connection using the same protocol on ANY
|
||||
VHOST.
|
||||
</blockquote>
|
||||
<hr>
|
||||
<h2>lws_http_transaction_completed - wait for new http transaction or close</h2>
|
||||
<i>int LWS_WARN_UNUSED_RESULT</i>
|
||||
|
@ -1615,104 +1701,149 @@ header.
|
|||
<i>unsigned int</i> <b>fd_limit_per_thread</b>;<br>
|
||||
<i>unsigned int</i> <b>timeout_secs</b>;<br>
|
||||
<i>const char *</i> <b>ecdh_curve</b>;<br>
|
||||
<i>const char *</i> <b>vhost_name</b>;<br>
|
||||
<i>const char *const *</i> <b>plugin_dirs</b>;<br>
|
||||
<i>const struct lws_protocol_vhost_options *</i> <b>pvo</b>;<br>
|
||||
<i>int</i> <b>keepalive_timeout</b>;<br>
|
||||
<i>const char *</i> <b>log_filepath</b>;<br>
|
||||
<i>const struct lws_http_mount *</i> <b>mounts</b>;<br>
|
||||
<i>const char *</i> <b>server_string</b>;<br>
|
||||
};<br>
|
||||
<h3>Members</h3>
|
||||
<dl>
|
||||
<dt><b>port</b>
|
||||
<dd>Port to listen on... you can use CONTEXT_PORT_NO_LISTEN to
|
||||
<dd>VHOST: Port to listen on... you can use CONTEXT_PORT_NO_LISTEN to
|
||||
suppress listening on any port, that's what you want if you are
|
||||
not running a websocket server at all but just using it as a
|
||||
client
|
||||
<dt><b>iface</b>
|
||||
<dd>NULL to bind the listen socket to all interfaces, or the
|
||||
<dd>VHOST: NULL to bind the listen socket to all interfaces, or the
|
||||
interface name, eg, "eth2"
|
||||
If options specifies LWS_SERVER_OPTION_UNIX_SOCK, this member is
|
||||
the pathname of a UNIX domain socket. you can use the UNIX domain
|
||||
sockets in abstract namespace, by prepending an @ symbole to the
|
||||
socket name.
|
||||
<dt><b>protocols</b>
|
||||
<dd>Array of structures listing supported protocols and a protocol-
|
||||
<dd>VHOST: Array of structures listing supported protocols and a protocol-
|
||||
specific callback for each one. The list is ended with an
|
||||
entry that has a NULL callback pointer.
|
||||
It's not const because we write the owning_server member
|
||||
<dt><b>extensions</b>
|
||||
<dd>NULL or array of lws_extension structs listing the
|
||||
<dd>VHOST: NULL or array of lws_extension structs listing the
|
||||
extensions this context supports. If you configured with
|
||||
--without-extensions, you should give NULL here.
|
||||
<dt><b>token_limits</b>
|
||||
<dd>NULL or struct lws_token_limits pointer which is initialized
|
||||
<dd>CONTEXT: NULL or struct lws_token_limits pointer which is initialized
|
||||
with a token length limit for each possible WSI_TOKEN_***
|
||||
<dt><b>ssl_cert_filepath</b>
|
||||
<dd>If libwebsockets was compiled to use ssl, and you want
|
||||
<dd>VHOST: If libwebsockets was compiled to use ssl, and you want
|
||||
to listen using SSL, set to the filepath to fetch the
|
||||
server cert from, otherwise NULL for unencrypted
|
||||
<dt><b>ssl_private_key_filepath</b>
|
||||
<dd>filepath to private key if wanting SSL mode;
|
||||
<dd>VHOST: filepath to private key if wanting SSL mode;
|
||||
if this is set to NULL but sll_cert_filepath is set, the
|
||||
OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY callback is called
|
||||
to allow setting of the private key directly via openSSL
|
||||
library calls
|
||||
<dt><b>ssl_ca_filepath</b>
|
||||
<dd>CA certificate filepath or NULL
|
||||
<dd>VHOST: CA certificate filepath or NULL
|
||||
<dt><b>ssl_cipher_list</b>
|
||||
<dd>List of valid ciphers to use (eg,
|
||||
<dd>VHOST: List of valid ciphers to use (eg,
|
||||
"RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"
|
||||
or you can leave it as NULL to get "DEFAULT"
|
||||
<dt><b>http_proxy_address</b>
|
||||
<dd>If non-NULL, attempts to proxy via the given address.
|
||||
<dd>VHOST: If non-NULL, attempts to proxy via the given address.
|
||||
If proxy auth is required, use format
|
||||
"username:password<tt><b>server</b></tt>:port"
|
||||
<dt><b>http_proxy_port</b>
|
||||
<dd>If http_proxy_address was non-NULL, uses this port at
|
||||
<dd>VHOST: If http_proxy_address was non-NULL, uses this port at
|
||||
the address
|
||||
<dt><b>gid</b>
|
||||
<dd>group id to change to after setting listen socket, or -1.
|
||||
<dd>CONTEXT: group id to change to after setting listen socket, or -1.
|
||||
<dt><b>uid</b>
|
||||
<dd>user id to change to after setting listen socket, or -1.
|
||||
<dd>CONTEXT: user id to change to after setting listen socket, or -1.
|
||||
<dt><b>options</b>
|
||||
<dd>0, or LWS_SERVER_OPTION_... bitfields
|
||||
<dd>VHOST + CONTEXT: 0, or LWS_SERVER_OPTION_... bitfields
|
||||
<dt><b>user</b>
|
||||
<dd>optional user pointer that can be recovered via the context
|
||||
<dd>CONTEXT: optional user pointer that can be recovered via the context
|
||||
pointer using lws_context_user
|
||||
<dt><b>ka_time</b>
|
||||
<dd>0 for no keepalive, otherwise apply this keepalive timeout to
|
||||
<dd>CONTEXT: 0 for no keepalive, otherwise apply this keepalive timeout to
|
||||
all libwebsocket sockets, client or server
|
||||
<dt><b>ka_probes</b>
|
||||
<dd>if ka_time was nonzero, after the timeout expires how many
|
||||
<dd>CONTEXT: if ka_time was nonzero, after the timeout expires how many
|
||||
times to try to get a response from the peer before giving up
|
||||
and killing the connection
|
||||
<dt><b>ka_interval</b>
|
||||
<dd>if ka_time was nonzero, how long to wait before each ka_probes
|
||||
<dd>CONTEXT: if ka_time was nonzero, how long to wait before each ka_probes
|
||||
attempt
|
||||
<dt><b>provided_client_ssl_ctx</b>
|
||||
<dd>If non-null, swap out libwebsockets ssl
|
||||
<dd>CONTEXT: If non-null, swap out libwebsockets ssl
|
||||
implementation for the one provided by provided_ssl_ctx.
|
||||
Libwebsockets no longer is responsible for freeing the context
|
||||
if this option is selected.
|
||||
<dt><b>provided_client_ssl_ctx</b>
|
||||
<dd>If non-null, swap out libwebsockets ssl
|
||||
<dd>CONTEXT: If non-null, swap out libwebsockets ssl
|
||||
implementation for the one provided by provided_ssl_ctx.
|
||||
Libwebsockets no longer is responsible for freeing the context
|
||||
if this option is selected.
|
||||
<dt><b>max_http_header_data</b>
|
||||
<dd>The max amount of header payload that can be handled
|
||||
<dd>CONTEXT: The max amount of header payload that can be handled
|
||||
in an http request (unrecognized header payload is dropped)
|
||||
<dt><b>max_http_header_pool</b>
|
||||
<dd>The max number of connections with http headers that
|
||||
<dd>CONTEXT: The max number of connections with http headers that
|
||||
can be processed simultaneously (the corresponding memory is
|
||||
allocated for the lifetime of the context). If the pool is
|
||||
busy new incoming connections must wait for accept until one
|
||||
becomes free.
|
||||
<dt><b>count_threads</b>
|
||||
<dd>how many contexts to create in an array, 0 = 1
|
||||
<dd>CONTEXT: how many contexts to create in an array, 0 = 1
|
||||
<dt><b>fd_limit_per_thread</b>
|
||||
<dd>nonzero means restrict each service thread to this
|
||||
<dd>CONTEXT: nonzero means restrict each service thread to this
|
||||
many fds, 0 means the default which is divide the process fd
|
||||
limit by the number of threads.
|
||||
<dt><b>timeout_secs</b>
|
||||
<dd>various processes involving network roundtrips in the
|
||||
<dd>VHOST: various processes involving network roundtrips in the
|
||||
library are protected from hanging forever by timeouts. If
|
||||
nonzero, this member lets you set the timeout used in seconds.
|
||||
Otherwise a default timeout is used.
|
||||
<dt><b>ecdh_curve</b>
|
||||
<dd>if NULL, defaults to initializing server with "prime256v1"
|
||||
<dd>VHOST: if NULL, defaults to initializing server with "prime256v1"
|
||||
<dt><b>vhost_name</b>
|
||||
<dd>VHOST: name of vhost, must match external DNS name used to
|
||||
access the site, like "warmcat.com" as it's used to match
|
||||
<dt><b>plugin_dirs</b>
|
||||
<dd>CONTEXT: NULL, or NULL-terminated array of directories to
|
||||
scan for lws protocol plugins at context creation time
|
||||
<dt><b>pvo</b>
|
||||
<dd>VHOST: pointer to optional linked list of per-vhost
|
||||
options made accessible to protocols
|
||||
<dt><b>keepalive_timeout</b>
|
||||
<dd>VHOST: (default = 0 = 60s) seconds to allow remote
|
||||
client to hold on to an idle HTTP/1.1 connection
|
||||
<dt><b>log_filepath</b>
|
||||
<dd>VHOST: filepath to append logs to... this is opened before
|
||||
any dropping of initial privileges
|
||||
<dt><b>mounts</b>
|
||||
<dd>VHOST: optional linked list of mounts for this vhost
|
||||
<dt><b>server_string</b>
|
||||
<dd>CONTEXT: string used in HTTP headers to identify server
|
||||
software, if NULL, "libwebsockets".
|
||||
</dl>
|
||||
<h3>Description</h3>
|
||||
<blockquote>
|
||||
<p>
|
||||
This is also used to create vhosts.... if LWS_SERVER_OPTION_EXPLICIT_VHOSTS
|
||||
is not given, then for backwards compatibility one vhost is created at
|
||||
context-creation time using the info from this struct.
|
||||
<p>
|
||||
If LWS_SERVER_OPTION_EXPLICIT_VHOSTS is given, then no vhosts are created
|
||||
at the same time as the context, they are expected to be created afterwards.
|
||||
</blockquote>
|
||||
<h3>Host</h3>
|
||||
<blockquote>
|
||||
header and / or SNI name for SSL.
|
||||
</blockquote>
|
||||
<hr>
|
||||
<h2>struct lws_client_connect_info - parameters to connect with when using lws_client_connect_via_info()</h2>
|
||||
<b>struct lws_client_connect_info</b> {<br>
|
||||
|
@ -1728,6 +1859,10 @@ Otherwise a default timeout is used.
|
|||
<i>void *</i> <b>userdata</b>;<br>
|
||||
<i>const struct lws_extension *</i> <b>client_exts</b>;<br>
|
||||
<i>const char *</i> <b>method</b>;<br>
|
||||
<i>struct lws *</i> <b>parent_wsi</b>;<br>
|
||||
<i>const char *</i> <b>uri_replace_from</b>;<br>
|
||||
<i>const char *</i> <b>uri_replace_to</b>;<br>
|
||||
<i>struct lws_vhost *</i> <b>vhost</b>;<br>
|
||||
};<br>
|
||||
<h3>Members</h3>
|
||||
<dl>
|
||||
|
@ -1756,6 +1891,17 @@ Otherwise a default timeout is used.
|
|||
<dt><b>method</b>
|
||||
<dd>if non-NULL, do this http method instead of ws[s] upgrade.
|
||||
use "GET" to be a simple http client connection
|
||||
<dt><b>parent_wsi</b>
|
||||
<dd>if another wsi is responsible for this connection, give it here.
|
||||
this is used to make sure if the parent closes so do any
|
||||
child connections first.
|
||||
<dt><b>uri_replace_from</b>
|
||||
<dd>if non-NULL, when this string is found in URIs in
|
||||
text/html content-encoding, it's replaced with <tt><b>uri_replace_to</b></tt>
|
||||
<dt><b>uri_replace_to</b>
|
||||
<dd>see above
|
||||
<dt><b>vhost</b>
|
||||
<dd>vhost to bind to (used to determine related SSL_CTX)
|
||||
</dl>
|
||||
<hr>
|
||||
<h2>lws_close_reason - Set reason and aux data to send with Close packet If you are going to return nonzero from the callback requesting the connection to close, you can optionally call this to set the reason the peer will be told if possible.</h2>
|
||||
|
@ -1777,3 +1923,27 @@ use "GET" to be a simple http client connection
|
|||
<dd>Length of data in <tt><b>buf</b></tt> to send
|
||||
</dl>
|
||||
<hr>
|
||||
<h2>lws_snprintf - </h2>
|
||||
<i>LWS_EXTERN int</i>
|
||||
<b>lws_snprintf</b>
|
||||
(<i>char *</i> <b>str</b>,
|
||||
<i>size_t</i> <b>size</b>,
|
||||
<i>const char *</i> <b>format</b>,
|
||||
<i></i> <b>...</b>)
|
||||
<h3>Arguments</h3>
|
||||
<dl>
|
||||
<dt><b>...</b>
|
||||
<dd>variable arguments
|
||||
</dl>
|
||||
<h3>Description</h3>
|
||||
<blockquote>
|
||||
<p>
|
||||
\param str: destination buffer
|
||||
\param size: bytes left in destination buffer
|
||||
\param format: format string
|
||||
\param ...: args for format
|
||||
<p>
|
||||
This lets you correctly truncate buffers by concatenating lengths, if you
|
||||
reach the limit the reported length doesn't exceed the limit.
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Name: libwebsockets
|
||||
Version: 2.0.0
|
||||
Version: 2.0.3
|
||||
Release: 1%{?dist}
|
||||
Summary: Websocket Server and Client Library
|
||||
|
||||
|
@ -55,7 +55,7 @@ rm -rf $RPM_BUILD_ROOT
|
|||
/usr/bin/libwebsockets-test-echo
|
||||
/usr/bin/libwebsockets-test-fraggle
|
||||
/usr/bin/libwebsockets-test-fuzxy
|
||||
/%{_libdir}/libwebsockets.so.8
|
||||
/%{_libdir}/libwebsockets.so.8.1
|
||||
/%{_libdir}/libwebsockets.so
|
||||
/%{_libdir}/cmake/libwebsockets/LibwebsocketsConfig.cmake
|
||||
/%{_libdir}/cmake/libwebsockets/LibwebsocketsConfigVersion.cmake
|
||||
|
@ -70,6 +70,15 @@ rm -rf $RPM_BUILD_ROOT
|
|||
/%{_libdir}/pkgconfig/libwebsockets.pc
|
||||
|
||||
%changelog
|
||||
* Thu Sep 15 2016 Andy Green <andy@warmcat.com> 2.0.3-1
|
||||
- MAJOR Upstream 2.0.3 release
|
||||
|
||||
* Mon Jun 06 2016 Andy Green <andy@warmcat.com> 2.0.2-1
|
||||
- MINOR Upstream 2.0.2 release
|
||||
|
||||
* Thu May 12 2016 Andy Green <andy@warmcat.com> 2.0.1-1
|
||||
- MINOR Upstream 2.0.1 release
|
||||
|
||||
* Thu May 05 2016 Andy Green <andy@warmcat.com> 2.0.0-1
|
||||
- MAJOR SONAMEBUMP APICHANGES Upstream 2.0.0 release
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
/* SSL server using ECDH certificate */
|
||||
#cmakedefine LWS_SSL_SERVER_WITH_ECDH_CERT
|
||||
#cmakedefine LWS_HAVE_SSL_CTX_set1_param
|
||||
#cmakedefine LWS_HAVE_X509_VERIFY_PARAM_set1_host
|
||||
|
||||
/* CGI apis */
|
||||
#cmakedefine LWS_WITH_CGI
|
||||
|
|
55
lwsws/conf.c
55
lwsws/conf.c
|
@ -60,10 +60,13 @@ static const char * const paths_vhosts[] = {
|
|||
"vhosts[].mounts[].cache-reuse",
|
||||
"vhosts[].mounts[].cache-revalidate",
|
||||
"vhosts[].mounts[].cache-intermediaries",
|
||||
"vhosts[].mounts[].extra-mimetypes.*",
|
||||
"vhosts[].ws-protocols[].*.*",
|
||||
"vhosts[].ws-protocols[].*",
|
||||
"vhosts[].ws-protocols[]",
|
||||
"vhosts[].keepalive_timeout",
|
||||
"vhosts[].ciphers",
|
||||
"vhosts[].ecdh-curve",
|
||||
};
|
||||
|
||||
enum lejp_vhost_paths {
|
||||
|
@ -87,10 +90,13 @@ enum lejp_vhost_paths {
|
|||
LEJPVP_MOUNT_CACHE_REUSE,
|
||||
LEJPVP_MOUNT_CACHE_REVALIDATE,
|
||||
LEJPVP_MOUNT_CACHE_INTERMEDIARIES,
|
||||
LEJPVP_MOUNT_EXTRA_MIMETYPES,
|
||||
LEJPVP_PROTOCOL_NAME_OPT,
|
||||
LEJPVP_PROTOCOL_NAME,
|
||||
LEJPVP_PROTOCOL,
|
||||
LEJPVP_KEEPALIVE_TIMEOUT,
|
||||
LEJPVP_CIPHERS,
|
||||
LEJPVP_ECDH_CURVE,
|
||||
};
|
||||
|
||||
#define MAX_PLUGIN_DIRS 10
|
||||
|
@ -104,9 +110,12 @@ struct jpargs {
|
|||
struct lws_http_mount *head, *last;
|
||||
|
||||
struct lws_protocol_vhost_options *pvo;
|
||||
struct lws_protocol_vhost_options *pvo_em;
|
||||
struct lws_http_mount m;
|
||||
const char **plugin_dirs;
|
||||
int count_plugin_dirs;
|
||||
|
||||
unsigned int fresh_mount:1;
|
||||
};
|
||||
|
||||
static void *
|
||||
|
@ -172,7 +181,7 @@ lejp_globals_cb(struct lejp_ctx *ctx, char reason)
|
|||
return 0;
|
||||
}
|
||||
|
||||
a->p += snprintf(a->p, a->end - a->p, "%s", ctx->buf);
|
||||
a->p += lws_snprintf(a->p, a->end - a->p, "%s", ctx->buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -225,8 +234,10 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
|
|||
}
|
||||
|
||||
if (reason == LEJPCB_OBJECT_START &&
|
||||
ctx->path_match == LEJPVP_MOUNTS + 1)
|
||||
ctx->path_match == LEJPVP_MOUNTS + 1) {
|
||||
a->fresh_mount = 1;
|
||||
memset(&a->m, 0, sizeof(a->m));
|
||||
}
|
||||
|
||||
/* this catches, eg, vhosts[].ws-protocols[].xxx-protocol */
|
||||
if (reason == LEJPCB_OBJECT_START &&
|
||||
|
@ -239,11 +250,11 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
|
|||
a->pvo->next = a->info->pvo;
|
||||
a->info->pvo = a->pvo;
|
||||
a->pvo->name = a->p;
|
||||
lwsl_err("adding %s\n", a->p);
|
||||
lwsl_notice(" adding protocol %s\n", a->p);
|
||||
a->p += n;
|
||||
a->pvo->value = a->p;
|
||||
a->pvo->options = NULL;
|
||||
a->p += snprintf(a->p, a->end - a->p, "%s", ctx->buf);
|
||||
a->p += lws_snprintf(a->p, a->end - a->p, "%s", ctx->buf);
|
||||
*(a->p)++ = '\0';
|
||||
}
|
||||
|
||||
|
@ -279,10 +290,14 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
|
|||
">https://",
|
||||
};
|
||||
|
||||
if (!a->fresh_mount)
|
||||
return 0;
|
||||
|
||||
if (!a->m.mountpoint || !a->m.origin) {
|
||||
lwsl_err("mountpoint and origin required\n");
|
||||
return 1;
|
||||
}
|
||||
lwsl_debug("adding mount %s\n", a->m.mountpoint);
|
||||
m = lwsws_align(a);
|
||||
memcpy(m, &a->m, sizeof(*m));
|
||||
if (a->last)
|
||||
|
@ -306,6 +321,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
|
|||
a->head = m;
|
||||
|
||||
a->last = m;
|
||||
a->fresh_mount = 0;
|
||||
}
|
||||
|
||||
/* we only match on the prepared path strings */
|
||||
|
@ -374,6 +390,12 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
|
|||
case LEJPVP_KEEPALIVE_TIMEOUT:
|
||||
a->info->keepalive_timeout = atoi(ctx->buf);
|
||||
return 0;
|
||||
case LEJPVP_CIPHERS:
|
||||
a->info->ssl_cipher_list = a->p;
|
||||
break;
|
||||
case LEJPVP_ECDH_CURVE:
|
||||
a->info->ecdh_curve = a->p;
|
||||
break;
|
||||
case LEJPVP_CGI_ENV:
|
||||
mp_cgienv = lwsws_align(a);
|
||||
a->p += sizeof(*a->m.cgienv);
|
||||
|
@ -386,7 +408,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
|
|||
a->p += n;
|
||||
mp_cgienv->value = a->p;
|
||||
mp_cgienv->options = NULL;
|
||||
a->p += snprintf(a->p, a->end - a->p, "%s", ctx->buf);
|
||||
a->p += lws_snprintf(a->p, a->end - a->p, "%s", ctx->buf);
|
||||
*(a->p)++ = '\0';
|
||||
|
||||
lwsl_notice(" adding cgi-env '%s' = '%s'\n", mp_cgienv->name,
|
||||
|
@ -409,15 +431,28 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
|
|||
a->p += n;
|
||||
pvo->value = a->p;
|
||||
pvo->options = NULL;
|
||||
a->p += snprintf(a->p, a->end - a->p, "%s", ctx->buf);
|
||||
*(a->p)++ = '\0';
|
||||
break;
|
||||
|
||||
case LEJPVP_MOUNT_EXTRA_MIMETYPES:
|
||||
a->pvo_em = lwsws_align(a);
|
||||
a->p += sizeof(*a->pvo_em);
|
||||
|
||||
n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
|
||||
/* ie, enable this protocol, no options yet */
|
||||
a->pvo_em->next = a->m.extra_mimetypes;
|
||||
a->m.extra_mimetypes = a->pvo_em;
|
||||
a->pvo_em->name = a->p;
|
||||
lwsl_notice(" adding extra-mimetypes %s -> %s\n", a->p, ctx->buf);
|
||||
a->p += n;
|
||||
a->pvo_em->value = a->p;
|
||||
a->pvo_em->options = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
a->p += snprintf(a->p, a->end - a->p, "%s", ctx->buf);
|
||||
a->p += lws_snprintf(a->p, a->end - a->p, "%s", ctx->buf);
|
||||
*(a->p)++ = '\0';
|
||||
|
||||
return 0;
|
||||
|
@ -483,7 +518,7 @@ lwsws_get_config_d(void *user, const char *d, const char * const *paths,
|
|||
}
|
||||
|
||||
while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
|
||||
snprintf(path, sizeof(path) - 1, "%s/%s", d, dent.name);
|
||||
lws_snprintf(path, sizeof(path) - 1, "%s/%s", d, dent.name);
|
||||
ret = lwsws_get_config(user, path, paths, count_paths, cb);
|
||||
if (ret)
|
||||
goto bail;
|
||||
|
@ -523,7 +558,7 @@ lwsws_get_config_d(void *user, const char *d, const char * const *paths,
|
|||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
snprintf(path, sizeof(path) - 1, "%s/%s", d,
|
||||
lws_snprintf(path, sizeof(path) - 1, "%s/%s", d,
|
||||
namelist[i]->d_name);
|
||||
ret = lwsws_get_config(user, path, paths, count_paths, cb);
|
||||
if (ret) {
|
||||
|
|
|
@ -149,7 +149,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|||
#endif
|
||||
|
||||
if (strlen(in) >= 12 &&
|
||||
!strncmp(in + strlen(in) - 12, "/postresults", 12)) {
|
||||
!strncmp((char *)in + strlen(in) - 12, "/postresults", 12)) {
|
||||
m = sprintf(buf, "<html><body>Form results: '%s'<br>"
|
||||
"</body></html>", pss->post_string);
|
||||
|
||||
|
|
12
lwsws/lejp.c
12
lwsws/lejp.c
|
@ -115,7 +115,15 @@ lejp_check_path_match(struct lejp_ctx *ctx)
|
|||
}
|
||||
ctx->wild[ctx->wildcount++] = p - ctx->path;
|
||||
q++;
|
||||
while (*p && *p != '.')
|
||||
/*
|
||||
* if * has something after it, match to .
|
||||
* if ends with *, eat everything.
|
||||
* This implies match sequences must be ordered like
|
||||
* x.*.*
|
||||
* x.*
|
||||
* if both options are possible
|
||||
*/
|
||||
while (*p && (*p != '.' || !*q))
|
||||
p++;
|
||||
}
|
||||
if (*p || *q)
|
||||
|
@ -140,7 +148,7 @@ lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len)
|
|||
|
||||
n = ctx->wild[wildcard];
|
||||
|
||||
while (--len && n < ctx->ppos && ctx->path[n] != '.')
|
||||
while (--len && n < ctx->ppos && (n == ctx->wild[wildcard] || ctx->path[n] != '.'))
|
||||
*dest++ = ctx->path[n++];
|
||||
|
||||
*dest = '\0';
|
||||
|
|
14
lwsws/lejp.h
14
lwsws/lejp.h
|
@ -1,3 +1,5 @@
|
|||
#include "../lib/libwebsockets.h"
|
||||
|
||||
|
||||
struct lejp_ctx;
|
||||
|
||||
|
@ -140,7 +142,7 @@ enum lejp_callbacks {
|
|||
*
|
||||
* LEJPCB_OBJECT_END: An object ended
|
||||
*/
|
||||
extern char _lejp_callback(struct lejp_ctx *ctx, char reason);
|
||||
LWS_EXTERN char _lejp_callback(struct lejp_ctx *ctx, char reason);
|
||||
|
||||
typedef char (*lejp_callback)(struct lejp_ctx *ctx, char reason);
|
||||
|
||||
|
@ -213,20 +215,20 @@ struct lejp_ctx {
|
|||
unsigned char wildcount;
|
||||
};
|
||||
|
||||
extern void
|
||||
LWS_EXTERN void
|
||||
lejp_construct(struct lejp_ctx *ctx,
|
||||
char (*callback)(struct lejp_ctx *ctx, char reason), void *user,
|
||||
const char * const *paths, unsigned char paths_count);
|
||||
|
||||
extern void
|
||||
LWS_EXTERN void
|
||||
lejp_destruct(struct lejp_ctx *ctx);
|
||||
|
||||
extern int
|
||||
LWS_EXTERN int
|
||||
lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len);
|
||||
|
||||
extern void
|
||||
LWS_EXTERN void
|
||||
lejp_change_callback(struct lejp_ctx *ctx,
|
||||
char (*callback)(struct lejp_ctx *ctx, char reason));
|
||||
|
||||
extern int
|
||||
LWS_EXTERN int
|
||||
lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len);
|
||||
|
|
|
@ -62,7 +62,7 @@ static struct lws_protocols protocols[] = {
|
|||
sizeof (struct per_session_data__http), /* per_session_data_size */
|
||||
0, /* max frame size / rx buffer */
|
||||
},
|
||||
{ }
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
void sighandler(int sig)
|
||||
|
|
|
@ -39,7 +39,7 @@ struct per_session_data__server_status {
|
|||
int pos;
|
||||
};
|
||||
|
||||
static const struct lws_protocols protocols[];
|
||||
static const struct lws_protocols protocols[1];
|
||||
|
||||
static void
|
||||
uv_timeout_cb_server_status(uv_timer_t *w
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
#include "../lib/libwebsockets.h"
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#ifdef WIN32
|
||||
#include <gettimeofday.h>
|
||||
#endif
|
||||
|
||||
|
||||
struct per_session_data__lws_status {
|
||||
struct per_session_data__lws_status *list;
|
||||
|
@ -54,7 +58,7 @@ update_status(struct lws *wsi, struct per_session_data__lws_status *pss)
|
|||
struct tm tm;
|
||||
#endif
|
||||
|
||||
p += snprintf(p, 512, " { %s, \"wsi\":\"%d\", \"conns\":[",
|
||||
p += lws_snprintf(p, 512, " { %s, \"wsi\":\"%d\", \"conns\":[",
|
||||
server_info, live_wsi);
|
||||
|
||||
/* render the list */
|
||||
|
@ -75,7 +79,7 @@ update_status(struct lws *wsi, struct per_session_data__lws_status *pss)
|
|||
if (subsequent)
|
||||
*p++ = ',';
|
||||
subsequent = 1;
|
||||
p += snprintf(p, sizeof(cache) - (p - start) - 1,
|
||||
p += lws_snprintf(p, sizeof(cache) - (p - start) - 1,
|
||||
"{\"peer\":\"%s\",\"time\":\"%s\","
|
||||
"\"ua\":\"%s\"}",
|
||||
(*pp)->ip, date, (*pp)->user_agent);
|
||||
|
@ -147,6 +151,11 @@ callback_lws_status(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
lwsl_notice("pmd test: RX len %d\n", (int)len);
|
||||
puts(in);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
pp = &list;
|
||||
while (*pp) {
|
||||
|
|
|
@ -82,11 +82,16 @@ Release Checklist
|
|||
- Bump version to 1.6.4
|
||||
- MINOR fix xyz
|
||||
|
||||
6) signed tag
|
||||
6) update api docs
|
||||
|
||||
$ cmake ..
|
||||
$ cp doc/* ..
|
||||
|
||||
7) signed tag
|
||||
|
||||
git tag -s vX.Y[.Z]
|
||||
|
||||
7) git
|
||||
8) git
|
||||
|
||||
a) push
|
||||
|
||||
|
|
|
@ -50,6 +50,14 @@ function check {
|
|||
fi
|
||||
fi
|
||||
|
||||
if [ "$1" == "0" ] ; then
|
||||
a="`dd if=$LOG bs=1 skip=$LEN 2>/dev/null |grep "get\ \ =" | tr -s ' ' | cut -d' ' -f4-`"
|
||||
if [ "$a" != "$2" ] ; then
|
||||
echo "URL path '$a' not $2"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$1" == "1" ] ; then
|
||||
a="`dd if=$LOG bs=1 skip=$LEN 2>/dev/null |grep URI\ Arg\ 1\: | tr -s ' ' | cut -d' ' -f5-`"
|
||||
if [ "$a" != "$2" ] ; then
|
||||
|
@ -106,9 +114,10 @@ check 1 "key1=value1"
|
|||
check
|
||||
|
||||
echo
|
||||
echo "---- ? processing (/test?key1%3d2=value1)"
|
||||
echo "---- ? processing (/t%3dest?key1%3d2=value1)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e "GET /test?key1%3d2=value1 HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
echo -e "GET /t%3dest?key1%3d2=value1 HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check 0 "/t=est"
|
||||
check 1 "key1_2=value1"
|
||||
check
|
||||
|
||||
|
@ -224,7 +233,7 @@ check default
|
|||
check
|
||||
|
||||
echo
|
||||
echo "---- nonexistant file"
|
||||
echo "---- nonexistent file"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e "GET /nope HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check media
|
||||
|
|
|
@ -271,13 +271,13 @@ callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
|
||||
static struct lws_protocols protocols[] = {
|
||||
{
|
||||
"dumb-increment-protocol,fake-nonexistant-protocol",
|
||||
"dumb-increment-protocol",
|
||||
callback_dumb_increment,
|
||||
0,
|
||||
20,
|
||||
},
|
||||
{
|
||||
"fake-nonexistant-protocol,lws-mirror-protocol",
|
||||
"lws-mirror-protocol",
|
||||
callback_lws_mirror,
|
||||
0,
|
||||
128,
|
||||
|
|
|
@ -66,6 +66,11 @@ callback_echo(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|||
|
||||
#ifndef LWS_NO_SERVER
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
pss->index = 0;
|
||||
pss->len = -1;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
do_tx:
|
||||
|
||||
|
@ -182,7 +187,7 @@ static struct lws_protocols protocols[] = {
|
|||
/* first protocol must always be HTTP handler */
|
||||
|
||||
{
|
||||
"", /* name - can be overriden with -e */
|
||||
"", /* name - can be overridden with -e */
|
||||
callback_echo,
|
||||
sizeof(struct per_session_data__echo), /* per_session_data_size */
|
||||
MAX_ECHO_PAYLOAD,
|
||||
|
|
|
@ -349,7 +349,7 @@ int main(int argc, char **argv)
|
|||
struct lws_client_connect_info i;
|
||||
|
||||
address = argv[optind];
|
||||
snprintf(ads_port, sizeof(ads_port), "%s:%u",
|
||||
lws_snprintf(ads_port, sizeof(ads_port), "%s:%u",
|
||||
address, port & 65535);
|
||||
memset(&i, 0, sizeof(i));
|
||||
i.context = context;
|
||||
|
|
|
@ -78,7 +78,7 @@ struct ping {
|
|||
};
|
||||
|
||||
struct per_session_data__ping {
|
||||
uint64_t ping_index;
|
||||
unsigned long long ping_index;
|
||||
|
||||
struct ping ringbuffer[PING_RINGBUFFER_SIZE];
|
||||
int ringbuffer_head;
|
||||
|
@ -110,7 +110,7 @@ callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
unsigned char *p;
|
||||
unsigned long iv;
|
||||
int match = 0;
|
||||
uint64_t l;
|
||||
unsigned long long l;
|
||||
int shift;
|
||||
int n;
|
||||
|
||||
|
@ -158,7 +158,7 @@ callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
l = 0;
|
||||
|
||||
while (shift >= 0) {
|
||||
l |= ((uint64_t)*p++) << shift;
|
||||
l |= ((unsigned long long)*p++) << shift;
|
||||
shift -= 8;
|
||||
}
|
||||
|
||||
|
@ -396,7 +396,7 @@ int main(int argc, char **argv)
|
|||
case 'r':
|
||||
clients = atoi(optarg);
|
||||
if (clients > MAX_PING_CLIENTS || clients < 1) {
|
||||
fprintf(stderr, "Max clients supportd = %d\n",
|
||||
fprintf(stderr, "Max clients supported = %d\n",
|
||||
MAX_PING_CLIENTS);
|
||||
return 1;
|
||||
}
|
||||
|
@ -453,7 +453,7 @@ int main(int argc, char **argv)
|
|||
/* create client websockets using dumb increment protocol */
|
||||
|
||||
address = argv[optind];
|
||||
snprintf(ads_port, sizeof(ads_port), "%s:%u",
|
||||
lws_snprintf(ads_port, sizeof(ads_port), "%s:%u",
|
||||
address, port & 65535);
|
||||
lwsl_notice("Connecting to %s...\n", ads_port);
|
||||
memset(&i, 0, sizeof(i));
|
||||
|
|
|
@ -279,7 +279,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|||
LWS_O_RDONLY);
|
||||
|
||||
if (pss->fd == LWS_INVALID_FILE) {
|
||||
lwsl_err("faild to open file %s\n", leaf_path);
|
||||
lwsl_err("failed to open file %s\n", leaf_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -407,6 +407,8 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|||
lwsl_notice("LWS_CALLBACK_HTTP_BODY: len %d\n", (int)len);
|
||||
strncpy(pss->post_string, in, sizeof (pss->post_string) -1);
|
||||
pss->post_string[sizeof(pss->post_string) - 1] = '\0';
|
||||
if (len < sizeof(pss->post_string) - 1)
|
||||
pss->post_string[len] = '\0';
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP_BODY_COMPLETION:
|
||||
|
|
|
@ -42,7 +42,7 @@ update_status(struct lws *wsi, struct per_session_data__lws_status *pss)
|
|||
struct tm tm;
|
||||
#endif
|
||||
|
||||
p += snprintf(p, 512, " { %s, \"wsi\":\"%d\", \"conns\":[",
|
||||
p += lws_snprintf(p, 512, " { %s, \"wsi\":\"%d\", \"conns\":[",
|
||||
server_info, live_wsi);
|
||||
|
||||
/* render the list */
|
||||
|
@ -67,7 +67,7 @@ update_status(struct lws *wsi, struct per_session_data__lws_status *pss)
|
|||
if (subsequent)
|
||||
*p++ = ',';
|
||||
subsequent = 1;
|
||||
p += snprintf(p, sizeof(cache) - (p - start) - 1,
|
||||
p += lws_snprintf(p, sizeof(cache) - (p - start) - 1,
|
||||
"{\"peer\":\"%s\",\"time\":\"%s\","
|
||||
"\"ua\":\"%s\"}",
|
||||
(*pp)->ip, date, (*pp)->user_agent);
|
||||
|
@ -131,6 +131,11 @@ callback_lws_status(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
update_status(wsi, pss);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
lwsl_notice("pmd test: RX len %d\n", (int)len);
|
||||
puts(in);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
m = lws_write(wsi, (unsigned char *)cache + LWS_PRE, cache_len,
|
||||
LWS_WRITE_TEXT);
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
#include <libwebsockets.h>
|
||||
#include <getopt.h>
|
||||
#ifndef WIN32
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
int debug_level = 7;
|
||||
struct lws_context *context;
|
||||
|
@ -81,6 +83,7 @@ static const struct lws_http_mount mount = {
|
|||
LOCAL_RESOURCE_PATH, /* where to go on the filesystem for that */
|
||||
"test.html", /* default filename if none given */
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
@ -90,6 +93,19 @@ static const struct lws_http_mount mount = {
|
|||
1, /* strlen("/"), ie length of the mountpoint */
|
||||
};
|
||||
|
||||
/*
|
||||
* this sets a per-vhost, per-protocol option name:value pair
|
||||
* the effect is to set this protocol to be the default one for the vhost,
|
||||
* ie, selected if no Protocol: header is sent with the ws upgrade.
|
||||
*/
|
||||
|
||||
static const struct lws_protocol_vhost_options pvo_opt = {
|
||||
NULL,
|
||||
NULL,
|
||||
"default",
|
||||
"1"
|
||||
};
|
||||
|
||||
/*
|
||||
* We must enable the plugin protocols we want into our vhost with a
|
||||
* linked-list. We can also give the plugin per-vhost options here.
|
||||
|
@ -111,7 +127,7 @@ static const struct lws_protocol_vhost_options pvo_1 = {
|
|||
|
||||
static const struct lws_protocol_vhost_options pvo = {
|
||||
&pvo_1,
|
||||
NULL,
|
||||
&pvo_opt,
|
||||
"dumb-increment-protocol",
|
||||
""
|
||||
};
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue