Compare commits
	
		
			30 Commits
		
	
	
		
			v11.2.4
			...
			bsergean-p
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 317e3c44bf | ||
|  | 61b90251af | ||
|  | 851157f252 | ||
|  | 69541cf750 | ||
|  | 1e166eee57 | ||
|  | 6860b2d09d | ||
|  | 9bbd1f1b30 | ||
|  | 18c2b69633 | ||
|  | 178f218374 | ||
|  | 6a1aa27b5f | ||
|  | e7f89ae529 | ||
|  | cdeaf8e2be | ||
|  | dbafa0aa07 | ||
|  | 3baf59a031 | ||
|  | b5804c2082 | ||
|  | 30bcddb99f | ||
|  | 47fd04e210 | ||
|  | 4f5b0c4f07 | ||
|  | c2d497abc5 | ||
|  | bbe2ae6dd3 | ||
|  | 26897b2425 | ||
|  | e3c98a03cc | ||
|  | 97fedf9482 | ||
|  | ae187c0e98 | ||
|  | 0f21a20fe3 | ||
|  | 54db6ec8bb | ||
|  | 0e0a748037 | ||
|  | 3b19b0eeca | ||
|  | dbfe3104e8 | ||
|  | 68fd8c20d6 | 
							
								
								
									
										2
									
								
								.github/workflows/mkdocs.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/mkdocs.yml
									
									
									
									
										vendored
									
									
								
							| @@ -21,5 +21,7 @@ jobs: | |||||||
|         pip install pygments |         pip install pygments | ||||||
|     - name: Build doc |     - name: Build doc | ||||||
|       run: | |       run: | | ||||||
|  |         git clean -dfx . | ||||||
|  |         git fetch | ||||||
|         git pull |         git pull | ||||||
|         mkdocs gh-deploy |         mkdocs gh-deploy | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								.github/workflows/unittest_linux.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/unittest_linux.yml
									
									
									
									
										vendored
									
									
								
							| @@ -3,6 +3,7 @@ on: | |||||||
|   push: |   push: | ||||||
|     paths-ignore: |     paths-ignore: | ||||||
|     - 'docs/**' |     - 'docs/**' | ||||||
|  |   pull_request: | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   linux: |   linux: | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								.github/workflows/unittest_linux_asan.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/unittest_linux_asan.yml
									
									
									
									
										vendored
									
									
								
							| @@ -3,6 +3,7 @@ on: | |||||||
|   push: |   push: | ||||||
|     paths-ignore: |     paths-ignore: | ||||||
|     - 'docs/**' |     - 'docs/**' | ||||||
|  |   pull_request: | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   linux: |   linux: | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ on: | |||||||
|   push: |   push: | ||||||
|     paths-ignore: |     paths-ignore: | ||||||
|     - 'docs/**' |     - 'docs/**' | ||||||
|  |   pull_request: | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   mac_tsan_mbedtls: |   mac_tsan_mbedtls: | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ on: | |||||||
|   push: |   push: | ||||||
|     paths-ignore: |     paths-ignore: | ||||||
|     - 'docs/**' |     - 'docs/**' | ||||||
|  |   pull_request: | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   mac_tsan_openssl: |   mac_tsan_openssl: | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ on: | |||||||
|   push: |   push: | ||||||
|     paths-ignore: |     paths-ignore: | ||||||
|     - 'docs/**' |     - 'docs/**' | ||||||
|  |   pull_request: | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   mac_tsan_sectransport: |   mac_tsan_sectransport: | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								.github/workflows/unittest_uwp.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/unittest_uwp.yml
									
									
									
									
										vendored
									
									
								
							| @@ -3,6 +3,7 @@ on: | |||||||
|   push: |   push: | ||||||
|     paths-ignore: |     paths-ignore: | ||||||
|     - 'docs/**' |     - 'docs/**' | ||||||
|  |   pull_request: | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   uwp: |   uwp: | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								.github/workflows/unittest_windows.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/unittest_windows.yml
									
									
									
									
										vendored
									
									
								
							| @@ -3,6 +3,7 @@ on: | |||||||
|   push: |   push: | ||||||
|     paths-ignore: |     paths-ignore: | ||||||
|     - 'docs/**' |     - 'docs/**' | ||||||
|  |   pull_request: | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   windows: |   windows: | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								.github/workflows/unittest_windows_gcc.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/unittest_windows_gcc.yml
									
									
									
									
										vendored
									
									
								
							| @@ -3,6 +3,7 @@ on: | |||||||
|   push: |   push: | ||||||
|     paths-ignore: |     paths-ignore: | ||||||
|     - 'docs/**' |     - 'docs/**' | ||||||
|  |   pull_request: | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   windows: |   windows: | ||||||
|   | |||||||
| @@ -1,5 +1,8 @@ | |||||||
| find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) | find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) | ||||||
|  |  | ||||||
|  | # mbedtls-3.0 changed headers files, and we need to ifdef'out a few things | ||||||
|  | find_path(MBEDTLS_VERSION_GREATER_THAN_3 mbedtls/build_info.h) | ||||||
|  |  | ||||||
| find_library(MBEDTLS_LIBRARY mbedtls) | find_library(MBEDTLS_LIBRARY mbedtls) | ||||||
| find_library(MBEDX509_LIBRARY mbedx509) | find_library(MBEDX509_LIBRARY mbedx509) | ||||||
| find_library(MBEDCRYPTO_LIBRARY mbedcrypto) | find_library(MBEDCRYPTO_LIBRARY mbedcrypto) | ||||||
|   | |||||||
| @@ -180,18 +180,28 @@ if (USE_TLS) | |||||||
|       # set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /opt/local/include/openssl-1.0) |       # set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /opt/local/include/openssl-1.0) | ||||||
|     endif() |     endif() | ||||||
|  |  | ||||||
|     # Use OPENSSL_ROOT_DIR CMake variable if you need to use your own openssl |     # This OPENSSL_FOUND check is to help find a cmake manually configured OpenSSL | ||||||
|  |     if (NOT OPENSSL_FOUND) | ||||||
|       find_package(OpenSSL REQUIRED) |       find_package(OpenSSL REQUIRED) | ||||||
|  |     endif() | ||||||
|     message(STATUS "OpenSSL: " ${OPENSSL_VERSION}) |     message(STATUS "OpenSSL: " ${OPENSSL_VERSION}) | ||||||
|  |  | ||||||
|     add_definitions(${OPENSSL_DEFINITIONS}) |     add_definitions(${OPENSSL_DEFINITIONS}) | ||||||
|     target_include_directories(ixwebsocket PUBLIC ${OPENSSL_INCLUDE_DIR}) |     target_include_directories(ixwebsocket PUBLIC $<BUILD_INTERFACE:${OPENSSL_INCLUDE_DIR}>) | ||||||
|     target_link_libraries(ixwebsocket ${OPENSSL_LIBRARIES}) |     target_link_libraries(ixwebsocket ${OPENSSL_LIBRARIES}) | ||||||
|   elseif (USE_MBED_TLS) |   elseif (USE_MBED_TLS) | ||||||
|     message(STATUS "TLS configured to use mbedtls") |     message(STATUS "TLS configured to use mbedtls") | ||||||
|  |  | ||||||
|  |     # This MBEDTLS_FOUND check is to help find a cmake manually configured MbedTLS | ||||||
|  |     if (NOT MBEDTLS_FOUND) | ||||||
|       find_package(MbedTLS REQUIRED) |       find_package(MbedTLS REQUIRED) | ||||||
|     target_include_directories(ixwebsocket PUBLIC ${MBEDTLS_INCLUDE_DIRS}) |        | ||||||
|  |       if (MBEDTLS_VERSION_GREATER_THAN_3) | ||||||
|  |         target_compile_definitions(ixwebsocket PRIVATE IXWEBSOCKET_USE_MBED_TLS_MIN_VERSION_3) | ||||||
|  |       endif() | ||||||
|  |        | ||||||
|  |     endif() | ||||||
|  |     target_include_directories(ixwebsocket PUBLIC $<BUILD_INTERFACE:${MBEDTLS_INCLUDE_DIRS}>) | ||||||
|     target_link_libraries(ixwebsocket ${MBEDTLS_LIBRARIES}) |     target_link_libraries(ixwebsocket ${MBEDTLS_LIBRARIES}) | ||||||
|   elseif (USE_SECURE_TRANSPORT) |   elseif (USE_SECURE_TRANSPORT) | ||||||
|     message(STATUS "TLS configured to use secure transport") |     message(STATUS "TLS configured to use secure transport") | ||||||
| @@ -202,9 +212,11 @@ endif() | |||||||
| option(USE_ZLIB "Enable zlib support" TRUE) | option(USE_ZLIB "Enable zlib support" TRUE) | ||||||
|  |  | ||||||
| if (USE_ZLIB) | if (USE_ZLIB) | ||||||
|   # Use ZLIB_ROOT CMake variable if you need to use your own zlib |   # This ZLIB_FOUND check is to help find a cmake manually configured zlib | ||||||
|  |   if (NOT ZLIB_FOUND) | ||||||
|     find_package(ZLIB REQUIRED) |     find_package(ZLIB REQUIRED) | ||||||
|   include_directories(${ZLIB_INCLUDE_DIRS}) |   endif() | ||||||
|  |   target_include_directories(ixwebsocket PUBLIC $<BUILD_INTERFACE:${ZLIB_INCLUDE_DIRS}>) | ||||||
|   target_link_libraries(ixwebsocket ${ZLIB_LIBRARIES}) |   target_link_libraries(ixwebsocket ${ZLIB_LIBRARIES}) | ||||||
|  |  | ||||||
|   target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_ZLIB) |   target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_ZLIB) | ||||||
| @@ -242,23 +254,29 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") | |||||||
|     target_compile_options(ixwebsocket PRIVATE /MP) |     target_compile_options(ixwebsocket PRIVATE /MP) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | include(GNUInstallDirs) | ||||||
|  |  | ||||||
| target_include_directories(ixwebsocket PUBLIC | target_include_directories(ixwebsocket PUBLIC | ||||||
|   $<BUILD_INTERFACE:${IXWEBSOCKET_INCLUDE_DIRS}/> |   $<BUILD_INTERFACE:${IXWEBSOCKET_INCLUDE_DIRS}/> | ||||||
|   $<INSTALL_INTERFACE:include/ixwebsocket> |   $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/ixwebsocket> | ||||||
| ) | ) | ||||||
|  |  | ||||||
| set_target_properties(ixwebsocket PROPERTIES PUBLIC_HEADER "${IXWEBSOCKET_HEADERS}") | set_target_properties(ixwebsocket PROPERTIES PUBLIC_HEADER "${IXWEBSOCKET_HEADERS}") | ||||||
|  |  | ||||||
|  | option(IXWEBSOCKET_INSTALL "Install IXWebSocket" TRUE) | ||||||
|  |  | ||||||
|  | if (IXWEBSOCKET_INSTALL) | ||||||
|   install(TARGETS ixwebsocket |   install(TARGETS ixwebsocket | ||||||
|           EXPORT ixwebsocket |           EXPORT ixwebsocket | ||||||
|         ARCHIVE DESTINATION lib |           ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} | ||||||
|         PUBLIC_HEADER DESTINATION include/ixwebsocket/ |           PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ixwebsocket/ | ||||||
|   ) |   ) | ||||||
|  |  | ||||||
|   install(EXPORT ixwebsocket |   install(EXPORT ixwebsocket | ||||||
|           FILE ixwebsocket-config.cmake |           FILE ixwebsocket-config.cmake | ||||||
|           NAMESPACE ixwebsocket:: |           NAMESPACE ixwebsocket:: | ||||||
|         DESTINATION lib/cmake/ixwebsocket) |           DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/ixwebsocket) | ||||||
|  | endif() | ||||||
|  |  | ||||||
| if (USE_WS OR USE_TEST) | if (USE_WS OR USE_TEST) | ||||||
|   include(FetchContent) |   include(FetchContent) | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								README.md
									
									
									
									
									
								
							| @@ -24,6 +24,7 @@ A bad security bug affecting users compiling with SSL enabled and OpenSSL as the | |||||||
|  |  | ||||||
| #include <ixwebsocket/IXNetSystem.h> | #include <ixwebsocket/IXNetSystem.h> | ||||||
| #include <ixwebsocket/IXWebSocket.h> | #include <ixwebsocket/IXWebSocket.h> | ||||||
|  | #include <ixwebsocket/IXUserAgent.h> | ||||||
| #include <iostream> | #include <iostream> | ||||||
|  |  | ||||||
| int main() | int main() | ||||||
| @@ -34,6 +35,8 @@ int main() | |||||||
|     // Our websocket object |     // Our websocket object | ||||||
|     ix::WebSocket webSocket; |     ix::WebSocket webSocket; | ||||||
|  |  | ||||||
|  |     // Connect to a server with encryption | ||||||
|  |     // See https://machinezone.github.io/IXWebSocket/usage/#tls-support-and-configuration | ||||||
|     std::string url("wss://echo.websocket.org"); |     std::string url("wss://echo.websocket.org"); | ||||||
|     webSocket.setUrl(url); |     webSocket.setUrl(url); | ||||||
|  |  | ||||||
| @@ -53,6 +56,12 @@ int main() | |||||||
|                 std::cout << "Connection established" << std::endl; |                 std::cout << "Connection established" << std::endl; | ||||||
|                 std::cout << "> " << std::flush; |                 std::cout << "> " << std::flush; | ||||||
|             } |             } | ||||||
|  |             else if (msg->type == ix::WebSocketMessageType::Error) | ||||||
|  |             { | ||||||
|  |                 // Maybe SSL is not configured properly | ||||||
|  |                 std::cout << "Connection error: " << msg->errorInfo.reason << std::endl; | ||||||
|  |                 std::cout << "> " << std::flush; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
| @@ -123,6 +132,7 @@ To check the performance of a websocket library, you can look at the [autoroute] | |||||||
| | Windows           | Disabled          | None              | [![Build2][5]][0] | | | Windows           | Disabled          | None              | [![Build2][5]][0] | | ||||||
| | UWP               | Disabled          | None              | [![Build2][6]][0] | | | UWP               | Disabled          | None              | [![Build2][6]][0] | | ||||||
| | Linux             | OpenSSL           | Address Sanitizer | [![Build2][7]][0] | | | Linux             | OpenSSL           | Address Sanitizer | [![Build2][7]][0] | | ||||||
|  | | Mingw             | Disabled          | None              | [![Build2][8]][0] | | ||||||
|  |  | ||||||
| * ASAN fails on Linux because of a known problem, we need a  | * ASAN fails on Linux because of a known problem, we need a  | ||||||
| * Some tests are disabled on Windows/UWP because of a pathing problem | * Some tests are disabled on Windows/UWP because of a pathing problem | ||||||
| @@ -136,4 +146,5 @@ To check the performance of a websocket library, you can look at the [autoroute] | |||||||
| [5]: https://github.com/machinezone/IXWebSocket/workflows/windows/badge.svg | [5]: https://github.com/machinezone/IXWebSocket/workflows/windows/badge.svg | ||||||
| [6]: https://github.com/machinezone/IXWebSocket/workflows/uwp/badge.svg | [6]: https://github.com/machinezone/IXWebSocket/workflows/uwp/badge.svg | ||||||
| [7]: https://github.com/machinezone/IXWebSocket/workflows/linux_asan/badge.svg | [7]: https://github.com/machinezone/IXWebSocket/workflows/linux_asan/badge.svg | ||||||
|  | [8]: https://github.com/machinezone/IXWebSocket/workflows/unittest_windows_gcc/badge.svg | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,6 +2,38 @@ | |||||||
|  |  | ||||||
| All changes to this project will be documented in this file. | All changes to this project will be documented in this file. | ||||||
|  |  | ||||||
|  | ## [11.3.1] - 2021-10-22 | ||||||
|  |  | ||||||
|  | (library/cmake) Compatible with MbedTLS 3 + fix a bug on Windows where the incorrect remote port is computed (#320) | ||||||
|  |  | ||||||
|  | ## [11.3.0] - 2021-09-20 | ||||||
|  |  | ||||||
|  | (library/cmake) Only find OpenSSL, MbedTLS, zlib if they have not already been found, make CMake install optional (#317) + Use GNUInstallDirs in cmake (#318) | ||||||
|  |  | ||||||
|  | ## [11.2.10] - 2021-07-27 | ||||||
|  |  | ||||||
|  | (ws) bump CLI command line parsing library from 1.8 to 2.0 | ||||||
|  |  | ||||||
|  | ## [11.2.9] - 2021-06-08 | ||||||
|  |  | ||||||
|  | (ws) ws connect has a -g option to gzip decompress messages for API such as the websocket Huobi Global. | ||||||
|  |  | ||||||
|  | ## [11.2.8] - 2021-06-03 | ||||||
|  |  | ||||||
|  | (websocket client + server) WebSocketMessage class tweak to fix unsafe patterns | ||||||
|  |  | ||||||
|  | ## [11.2.7] - 2021-05-27 | ||||||
|  |  | ||||||
|  | (websocket server) Handle and accept firefox browser special upgrade value (keep-alive, Upgrade) | ||||||
|  |  | ||||||
|  | ## [11.2.6] - 2021-05-18 | ||||||
|  |  | ||||||
|  | (Windows) move EINVAL (re)definition from IXSocket.h to IXNetSystem.h (fix #289) | ||||||
|  |  | ||||||
|  | ## [11.2.5] - 2021-04-04 | ||||||
|  |  | ||||||
|  | (http client) DEL is not an HTTP method name, but DELETE is | ||||||
|  |  | ||||||
| ## [11.2.4] - 2021-03-25 | ## [11.2.4] - 2021-03-25 | ||||||
|  |  | ||||||
| (cmake) install IXUniquePtr.h | (cmake) install IXUniquePtr.h | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ Options for building: | |||||||
| * `-DBUILD_SHARED_LIBS=ON` will build the unittest as a shared libary instead of a static library, which is the default | * `-DBUILD_SHARED_LIBS=ON` will build the unittest as a shared libary instead of a static library, which is the default | ||||||
| * `-DUSE_ZLIB=1` will enable zlib support, required for http client + server + websocket per message deflate extension | * `-DUSE_ZLIB=1` will enable zlib support, required for http client + server + websocket per message deflate extension | ||||||
| * `-DUSE_TLS=1` will enable TLS support | * `-DUSE_TLS=1` will enable TLS support | ||||||
| * `-DUSE_OPEN_SSL=1` will use [openssl](https://www.openssl.org/) for the TLS support (default on Linux and Windows) | * `-DUSE_OPEN_SSL=1` will use [openssl](https://www.openssl.org/) for the TLS support (default on Linux and Windows). When using a custom version of openssl (say a prebuilt version, odd runtime problems can happens, as in #319, and special cmake trickery will be required (see this [comment](https://github.com/machinezone/IXWebSocket/issues/175#issuecomment-620231032)) | ||||||
| * `-DUSE_MBED_TLS=1` will use [mbedlts](https://tls.mbed.org/) for the TLS support | * `-DUSE_MBED_TLS=1` will use [mbedlts](https://tls.mbed.org/) for the TLS support | ||||||
| * `-DUSE_WS=1` will build the ws interactive command line tool | * `-DUSE_WS=1` will build the ws interactive command line tool | ||||||
| * `-DUSE_TEST=1` will build the unittest | * `-DUSE_TEST=1` will build the unittest | ||||||
|   | |||||||
| @@ -374,13 +374,10 @@ The webSocket reference is guaranteed to be always valid ; by design the callbac | |||||||
| // Bound host name, max connections and listen backlog can also be passed in as parameters. | // Bound host name, max connections and listen backlog can also be passed in as parameters. | ||||||
| ix::WebSocketServer server(port); | ix::WebSocketServer server(port); | ||||||
|  |  | ||||||
| server.setOnClientMessageCallback(std::shared_ptr<ConnectionState> connectionState, | server.setOnClientMessageCallback([](std::shared_ptr<ix::ConnectionState> connectionState, ix::WebSocket & webSocket, const ix::WebSocketMessagePtr & msg) { | ||||||
|                                   WebSocket& webSocket, |  | ||||||
|                                   const WebSocketMessagePtr& msg) |  | ||||||
| { |  | ||||||
|     // The ConnectionState object contains information about the connection, |     // The ConnectionState object contains information about the connection, | ||||||
|     // at this point only the client ip address and the port. |     // at this point only the client ip address and the port. | ||||||
|     std::cout << "Remote ip: " << connectionState->getRemoteIp(); |     std::cout << "Remote ip: " << connectionState->getRemoteIp() << std::endl; | ||||||
|  |  | ||||||
|     if (msg->type == ix::WebSocketMessageType::Open) |     if (msg->type == ix::WebSocketMessageType::Open) | ||||||
|     { |     { | ||||||
| @@ -398,7 +395,7 @@ server.setOnClientMessageCallback(std::shared_ptr<ConnectionState> connectionSta | |||||||
|         std::cout << "Headers:" << std::endl; |         std::cout << "Headers:" << std::endl; | ||||||
|         for (auto it : msg->openInfo.headers) |         for (auto it : msg->openInfo.headers) | ||||||
|         { |         { | ||||||
|             std::cout << it.first << ": " << it.second << std::endl; |             std::cout << "\t" << it.first << ": " << it.second << std::endl; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     else if (msg->type == ix::WebSocketMessageType::Message) |     else if (msg->type == ix::WebSocketMessageType::Message) | ||||||
| @@ -407,9 +404,11 @@ server.setOnClientMessageCallback(std::shared_ptr<ConnectionState> connectionSta | |||||||
|         // All connected clients are available in an std::set. See the broadcast cpp example. |         // All connected clients are available in an std::set. See the broadcast cpp example. | ||||||
|         // Second parameter tells whether we are sending the message in binary or text mode. |         // Second parameter tells whether we are sending the message in binary or text mode. | ||||||
|         // Here we send it in the same mode as it was received. |         // Here we send it in the same mode as it was received. | ||||||
|  |         std::cout << "Received: " << msg->str << std::endl; | ||||||
|  |  | ||||||
|         webSocket.send(msg->str, msg->binary); |         webSocket.send(msg->str, msg->binary); | ||||||
|     } |     } | ||||||
| ); | }); | ||||||
|  |  | ||||||
| auto res = server.listen(); | auto res = server.listen(); | ||||||
| if (!res.first) | if (!res.first) | ||||||
|   | |||||||
| @@ -137,7 +137,7 @@ namespace ix | |||||||
|             { |             { | ||||||
|                 contentLength = std::stoi(headers["Content-Length"]); |                 contentLength = std::stoi(headers["Content-Length"]); | ||||||
|             } |             } | ||||||
|             catch (std::exception) |             catch (const std::exception&) | ||||||
|             { |             { | ||||||
|                 return std::make_tuple( |                 return std::make_tuple( | ||||||
|                     false, "Error parsing HTTP Header 'Content-Length'", httpRequest); |                     false, "Error parsing HTTP Header 'Content-Length'", httpRequest); | ||||||
|   | |||||||
| @@ -20,10 +20,11 @@ | |||||||
|  |  | ||||||
| namespace ix | namespace ix | ||||||
| { | { | ||||||
|  |     // https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods | ||||||
|     const std::string HttpClient::kPost = "POST"; |     const std::string HttpClient::kPost = "POST"; | ||||||
|     const std::string HttpClient::kGet = "GET"; |     const std::string HttpClient::kGet = "GET"; | ||||||
|     const std::string HttpClient::kHead = "HEAD"; |     const std::string HttpClient::kHead = "HEAD"; | ||||||
|     const std::string HttpClient::kDel = "DEL"; |     const std::string HttpClient::kDelete = "DELETE"; | ||||||
|     const std::string HttpClient::kPut = "PUT"; |     const std::string HttpClient::kPut = "PUT"; | ||||||
|     const std::string HttpClient::kPatch = "PATCH"; |     const std::string HttpClient::kPatch = "PATCH"; | ||||||
|  |  | ||||||
| @@ -189,14 +190,14 @@ namespace ix | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Set a default Accept header if none is present |         // Set a default Accept header if none is present | ||||||
|         if (headers.find("Accept") == headers.end()) |         if (args->extraHeaders.find("Accept") == args->extraHeaders.end()) | ||||||
|         { |         { | ||||||
|             ss << "Accept: */*" |             ss << "Accept: */*" | ||||||
|                << "\r\n"; |                << "\r\n"; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Set a default User agent if none is present |         // Set a default User agent if none is present | ||||||
|         if (headers.find("User-Agent") == headers.end()) |         if (args->extraHeaders.find("User-Agent") == args->extraHeaders.end()) | ||||||
|         { |         { | ||||||
|             ss << "User-Agent: " << userAgent() << "\r\n"; |             ss << "User-Agent: " << userAgent() << "\r\n"; | ||||||
|         } |         } | ||||||
| @@ -557,9 +558,9 @@ namespace ix | |||||||
|         return request(url, kHead, std::string(), args); |         return request(url, kHead, std::string(), args); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     HttpResponsePtr HttpClient::del(const std::string& url, HttpRequestArgsPtr args) |     HttpResponsePtr HttpClient::Delete(const std::string& url, HttpRequestArgsPtr args) | ||||||
|     { |     { | ||||||
|         return request(url, kDel, std::string(), args); |         return request(url, kDelete, std::string(), args); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     HttpResponsePtr HttpClient::request(const std::string& url, |     HttpResponsePtr HttpClient::request(const std::string& url, | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ namespace ix | |||||||
|  |  | ||||||
|         HttpResponsePtr get(const std::string& url, HttpRequestArgsPtr args); |         HttpResponsePtr get(const std::string& url, HttpRequestArgsPtr args); | ||||||
|         HttpResponsePtr head(const std::string& url, HttpRequestArgsPtr args); |         HttpResponsePtr head(const std::string& url, HttpRequestArgsPtr args); | ||||||
|         HttpResponsePtr del(const std::string& url, HttpRequestArgsPtr args); |         HttpResponsePtr Delete(const std::string& url, HttpRequestArgsPtr args); | ||||||
|  |  | ||||||
|         HttpResponsePtr post(const std::string& url, |         HttpResponsePtr post(const std::string& url, | ||||||
|                              const HttpParameters& httpParameters, |                              const HttpParameters& httpParameters, | ||||||
| @@ -94,7 +94,7 @@ namespace ix | |||||||
|         const static std::string kPost; |         const static std::string kPost; | ||||||
|         const static std::string kGet; |         const static std::string kGet; | ||||||
|         const static std::string kHead; |         const static std::string kHead; | ||||||
|         const static std::string kDel; |         const static std::string kDelete; | ||||||
|         const static std::string kPut; |         const static std::string kPut; | ||||||
|         const static std::string kPatch; |         const static std::string kPatch; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -193,6 +193,7 @@ namespace ix | |||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | #if defined(_WIN32) && defined(__GNUC__) | ||||||
|     static int hexval(unsigned c) |     static int hexval(unsigned c) | ||||||
|     { |     { | ||||||
|         if (c - '0' < 10) return c - '0'; |         if (c - '0' < 10) return c - '0'; | ||||||
| @@ -200,6 +201,7 @@ namespace ix | |||||||
|         if (c - 'a' < 6) return c - 'a' + 10; |         if (c - 'a' < 6) return c - 'a' + 10; | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     // |     // | ||||||
|     // mingw does not have inet_pton, which were taken as is from the musl C library. |     // mingw does not have inet_pton, which were taken as is from the musl C library. | ||||||
|   | |||||||
| @@ -18,6 +18,19 @@ | |||||||
| #include <io.h> | #include <io.h> | ||||||
| #include <ws2def.h> | #include <ws2def.h> | ||||||
|  |  | ||||||
|  | #undef EWOULDBLOCK | ||||||
|  | #undef EAGAIN | ||||||
|  | #undef EINPROGRESS | ||||||
|  | #undef EBADF | ||||||
|  | #undef EINVAL | ||||||
|  |  | ||||||
|  | // map to WSA error codes | ||||||
|  | #define EWOULDBLOCK WSAEWOULDBLOCK | ||||||
|  | #define EAGAIN WSATRY_AGAIN | ||||||
|  | #define EINPROGRESS WSAEINPROGRESS | ||||||
|  | #define EBADF WSAEBADF | ||||||
|  | #define EINVAL WSAEINVAL | ||||||
|  |  | ||||||
| // Define our own poll on Windows, as a wrapper on top of select | // Define our own poll on Windows, as a wrapper on top of select | ||||||
| typedef unsigned long int nfds_t; | typedef unsigned long int nfds_t; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,20 +15,6 @@ | |||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
| #include <BaseTsd.h> | #include <BaseTsd.h> | ||||||
| typedef SSIZE_T ssize_t; | typedef SSIZE_T ssize_t; | ||||||
|  |  | ||||||
| #undef EWOULDBLOCK |  | ||||||
| #undef EAGAIN |  | ||||||
| #undef EINPROGRESS |  | ||||||
| #undef EBADF |  | ||||||
| #undef EINVAL |  | ||||||
|  |  | ||||||
| // map to WSA error codes |  | ||||||
| #define EWOULDBLOCK WSAEWOULDBLOCK |  | ||||||
| #define EAGAIN WSATRY_AGAIN |  | ||||||
| #define EINPROGRESS WSAEINPROGRESS |  | ||||||
| #define EBADF WSAEBADF |  | ||||||
| #define EINVAL WSAEINVAL |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #include "IXCancellationRequest.h" | #include "IXCancellationRequest.h" | ||||||
|   | |||||||
| @@ -132,7 +132,11 @@ namespace ix | |||||||
|                 errMsg = "Cannot parse cert file '" + _tlsOptions.certFile + "'"; |                 errMsg = "Cannot parse cert file '" + _tlsOptions.certFile + "'"; | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|  | #ifdef IXWEBSOCKET_USE_MBED_TLS_MIN_VERSION_3 | ||||||
|  |             if (mbedtls_pk_parse_keyfile(&_pkey, _tlsOptions.keyFile.c_str(), "", mbedtls_ctr_drbg_random, &_ctr_drbg) < 0) | ||||||
|  | #else | ||||||
|             if (mbedtls_pk_parse_keyfile(&_pkey, _tlsOptions.keyFile.c_str(), "") < 0) |             if (mbedtls_pk_parse_keyfile(&_pkey, _tlsOptions.keyFile.c_str(), "") < 0) | ||||||
|  | #endif | ||||||
|             { |             { | ||||||
|                 errMsg = "Cannot parse key file '" + _tlsOptions.keyFile + "'"; |                 errMsg = "Cannot parse key file '" + _tlsOptions.keyFile + "'"; | ||||||
|                 return false; |                 return false; | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ | |||||||
| #include <mbedtls/debug.h> | #include <mbedtls/debug.h> | ||||||
| #include <mbedtls/entropy.h> | #include <mbedtls/entropy.h> | ||||||
| #include <mbedtls/error.h> | #include <mbedtls/error.h> | ||||||
| #include <mbedtls/net.h> | #include <mbedtls/net_sockets.h> | ||||||
| #include <mbedtls/platform.h> | #include <mbedtls/platform.h> | ||||||
| #include <mbedtls/x509.h> | #include <mbedtls/x509.h> | ||||||
| #include <mbedtls/x509_crt.h> | #include <mbedtls/x509_crt.h> | ||||||
|   | |||||||
| @@ -15,6 +15,12 @@ | |||||||
| #include <cmath> | #include <cmath> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | namespace | ||||||
|  | { | ||||||
|  |     const std::string emptyMsg; | ||||||
|  | } // namespace | ||||||
|  |  | ||||||
|  |  | ||||||
| namespace ix | namespace ix | ||||||
| { | { | ||||||
|     OnTrafficTrackerCallback WebSocket::_onTrafficTrackerCallback = nullptr; |     OnTrafficTrackerCallback WebSocket::_onTrafficTrackerCallback = nullptr; | ||||||
| @@ -38,7 +44,7 @@ namespace ix | |||||||
|             [this](uint16_t code, const std::string& reason, size_t wireSize, bool remote) { |             [this](uint16_t code, const std::string& reason, size_t wireSize, bool remote) { | ||||||
|                 _onMessageCallback( |                 _onMessageCallback( | ||||||
|                     ix::make_unique<WebSocketMessage>(WebSocketMessageType::Close, |                     ix::make_unique<WebSocketMessage>(WebSocketMessageType::Close, | ||||||
|                                                       "", |                                                       emptyMsg, | ||||||
|                                                       wireSize, |                                                       wireSize, | ||||||
|                                                       WebSocketErrorInfo(), |                                                       WebSocketErrorInfo(), | ||||||
|                                                       WebSocketOpenInfo(), |                                                       WebSocketOpenInfo(), | ||||||
| @@ -69,7 +75,7 @@ namespace ix | |||||||
|         _extraHeaders = headers; |         _extraHeaders = headers; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const std::string& WebSocket::getUrl() const |     const std::string WebSocket::getUrl() const | ||||||
|     { |     { | ||||||
|         std::lock_guard<std::mutex> lock(_configMutex); |         std::lock_guard<std::mutex> lock(_configMutex); | ||||||
|         return _url; |         return _url; | ||||||
| @@ -88,7 +94,7 @@ namespace ix | |||||||
|         _socketTLSOptions = socketTLSOptions; |         _socketTLSOptions = socketTLSOptions; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const WebSocketPerMessageDeflateOptions& WebSocket::getPerMessageDeflateOptions() const |     const WebSocketPerMessageDeflateOptions WebSocket::getPerMessageDeflateOptions() const | ||||||
|     { |     { | ||||||
|         std::lock_guard<std::mutex> lock(_configMutex); |         std::lock_guard<std::mutex> lock(_configMutex); | ||||||
|         return _perMessageDeflateOptions; |         return _perMessageDeflateOptions; | ||||||
| @@ -217,7 +223,7 @@ namespace ix | |||||||
|  |  | ||||||
|         _onMessageCallback(ix::make_unique<WebSocketMessage>( |         _onMessageCallback(ix::make_unique<WebSocketMessage>( | ||||||
|             WebSocketMessageType::Open, |             WebSocketMessageType::Open, | ||||||
|             "", |             emptyMsg, | ||||||
|             0, |             0, | ||||||
|             WebSocketErrorInfo(), |             WebSocketErrorInfo(), | ||||||
|             WebSocketOpenInfo(status.uri, status.headers, status.protocol), |             WebSocketOpenInfo(status.uri, status.headers, status.protocol), | ||||||
| @@ -251,7 +257,7 @@ namespace ix | |||||||
|  |  | ||||||
|         _onMessageCallback( |         _onMessageCallback( | ||||||
|             ix::make_unique<WebSocketMessage>(WebSocketMessageType::Open, |             ix::make_unique<WebSocketMessage>(WebSocketMessageType::Open, | ||||||
|                                               "", |                                               emptyMsg, | ||||||
|                                               0, |                                               0, | ||||||
|                                               WebSocketErrorInfo(), |                                               WebSocketErrorInfo(), | ||||||
|                                               WebSocketOpenInfo(status.uri, status.headers), |                                               WebSocketOpenInfo(status.uri, status.headers), | ||||||
| @@ -338,7 +344,7 @@ namespace ix | |||||||
|                 connectErr.http_status = status.http_status; |                 connectErr.http_status = status.http_status; | ||||||
|  |  | ||||||
|                 _onMessageCallback(ix::make_unique<WebSocketMessage>(WebSocketMessageType::Error, |                 _onMessageCallback(ix::make_unique<WebSocketMessage>(WebSocketMessageType::Error, | ||||||
|                                                                      "", |                                                                      emptyMsg, | ||||||
|                                                                      0, |                                                                      0, | ||||||
|                                                                      connectErr, |                                                                      connectErr, | ||||||
|                                                                      WebSocketOpenInfo(), |                                                                      WebSocketOpenInfo(), | ||||||
|   | |||||||
| @@ -92,8 +92,8 @@ namespace ix | |||||||
|         ReadyState getReadyState() const; |         ReadyState getReadyState() const; | ||||||
|         static std::string readyStateToString(ReadyState readyState); |         static std::string readyStateToString(ReadyState readyState); | ||||||
|  |  | ||||||
|         const std::string& getUrl() const; |         const std::string getUrl() const; | ||||||
|         const WebSocketPerMessageDeflateOptions& getPerMessageDeflateOptions() const; |         const WebSocketPerMessageDeflateOptions getPerMessageDeflateOptions() const; | ||||||
|         int getPingInterval() const; |         int getPingInterval() const; | ||||||
|         size_t bufferedAmount() const; |         size_t bufferedAmount() const; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -204,6 +204,9 @@ namespace ix | |||||||
|         // Check the value of the connection field |         // Check the value of the connection field | ||||||
|         // Some websocket servers (Go/Gorilla?) send lowercase values for the |         // Some websocket servers (Go/Gorilla?) send lowercase values for the | ||||||
|         // connection header, so do a case insensitive comparison |         // connection header, so do a case insensitive comparison | ||||||
|  |         // | ||||||
|  |         // See https://github.com/apache/thrift/commit/7c4bdf9914fcba6c89e0f69ae48b9675578f084a | ||||||
|  |         // | ||||||
|         if (!insensitiveStringCompare(headers["connection"], "Upgrade")) |         if (!insensitiveStringCompare(headers["connection"], "Upgrade")) | ||||||
|         { |         { | ||||||
|             std::stringstream ss; |             std::stringstream ss; | ||||||
| @@ -296,7 +299,8 @@ namespace ix | |||||||
|             return sendErrorResponse(400, "Missing Upgrade header"); |             return sendErrorResponse(400, "Missing Upgrade header"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (!insensitiveStringCompare(headers["upgrade"], "WebSocket")) |         if (!insensitiveStringCompare(headers["upgrade"], "WebSocket") && | ||||||
|  |             headers["Upgrade"] != "keep-alive, Upgrade") // special case for firefox | ||||||
|         { |         { | ||||||
|             return sendErrorResponse(400, |             return sendErrorResponse(400, | ||||||
|                                      "Invalid Upgrade header, " |                                      "Invalid Upgrade header, " | ||||||
|   | |||||||
| @@ -42,6 +42,18 @@ namespace ix | |||||||
|         { |         { | ||||||
|             ; |             ; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * @brief Deleted overload to prevent binding `str` to a temporary, which would cause | ||||||
|  |          * undefined behavior since class members don't extend lifetime beyond the constructor call. | ||||||
|  |          */ | ||||||
|  |         WebSocketMessage(WebSocketMessageType t, | ||||||
|  |                          std::string&& s, | ||||||
|  |                          size_t w, | ||||||
|  |                          WebSocketErrorInfo e, | ||||||
|  |                          WebSocketOpenInfo o, | ||||||
|  |                          WebSocketCloseInfo c, | ||||||
|  |                          bool b = false) = delete; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     using WebSocketMessagePtr = std::unique_ptr<WebSocketMessage>; |     using WebSocketMessagePtr = std::unique_ptr<WebSocketMessage>; | ||||||
|   | |||||||
| @@ -14,12 +14,12 @@ namespace ix | |||||||
| { | { | ||||||
|     /// Default values as defined in the RFC |     /// Default values as defined in the RFC | ||||||
|     const uint8_t WebSocketPerMessageDeflateOptions::kDefaultServerMaxWindowBits = 15; |     const uint8_t WebSocketPerMessageDeflateOptions::kDefaultServerMaxWindowBits = 15; | ||||||
|     static const int minServerMaxWindowBits = 8; |     static const uint8_t minServerMaxWindowBits = 8; | ||||||
|     static const int maxServerMaxWindowBits = 15; |     static const uint8_t maxServerMaxWindowBits = 15; | ||||||
|  |  | ||||||
|     const uint8_t WebSocketPerMessageDeflateOptions::kDefaultClientMaxWindowBits = 15; |     const uint8_t WebSocketPerMessageDeflateOptions::kDefaultClientMaxWindowBits = 15; | ||||||
|     static const int minClientMaxWindowBits = 8; |     static const uint8_t minClientMaxWindowBits = 8; | ||||||
|     static const int maxClientMaxWindowBits = 15; |     static const uint8_t maxClientMaxWindowBits = 15; | ||||||
|  |  | ||||||
|     WebSocketPerMessageDeflateOptions::WebSocketPerMessageDeflateOptions( |     WebSocketPerMessageDeflateOptions::WebSocketPerMessageDeflateOptions( | ||||||
|         bool enabled, |         bool enabled, | ||||||
| @@ -85,11 +85,7 @@ namespace ix | |||||||
|  |  | ||||||
|             if (startsWith(token, "server_max_window_bits=")) |             if (startsWith(token, "server_max_window_bits=")) | ||||||
|             { |             { | ||||||
|                 std::string val = token.substr(token.find_last_of("=") + 1); |                 uint8_t x = strtol(token.substr(token.find_last_of("=") + 1).c_str(), nullptr, 10); | ||||||
|                 std::stringstream ss; |  | ||||||
|                 ss << val; |  | ||||||
|                 int x; |  | ||||||
|                 ss >> x; |  | ||||||
|  |  | ||||||
|                 // Sanitize values to be in the proper range [8, 15] in |                 // Sanitize values to be in the proper range [8, 15] in | ||||||
|                 // case a server would give us bogus values |                 // case a server would give us bogus values | ||||||
| @@ -99,11 +95,7 @@ namespace ix | |||||||
|  |  | ||||||
|             if (startsWith(token, "client_max_window_bits=")) |             if (startsWith(token, "client_max_window_bits=")) | ||||||
|             { |             { | ||||||
|                 std::string val = token.substr(token.find_last_of("=") + 1); |                 uint8_t x = strtol(token.substr(token.find_last_of("=") + 1).c_str(), nullptr, 10); | ||||||
|                 std::stringstream ss; |  | ||||||
|                 ss << val; |  | ||||||
|                 int x; |  | ||||||
|                 ss >> x; |  | ||||||
|  |  | ||||||
|                 // Sanitize values to be in the proper range [8, 15] in |                 // Sanitize values to be in the proper range [8, 15] in | ||||||
|                 // case a server would give us bogus values |                 // case a server would give us bogus values | ||||||
|   | |||||||
| @@ -39,8 +39,8 @@ namespace ix | |||||||
|         bool _enabled; |         bool _enabled; | ||||||
|         bool _clientNoContextTakeover; |         bool _clientNoContextTakeover; | ||||||
|         bool _serverNoContextTakeover; |         bool _serverNoContextTakeover; | ||||||
|         int _clientMaxWindowBits; |         uint8_t _clientMaxWindowBits; | ||||||
|         int _serverMaxWindowBits; |         uint8_t _serverMaxWindowBits; | ||||||
|  |  | ||||||
|         void sanitizeClientMaxWindowBits(); |         void sanitizeClientMaxWindowBits(); | ||||||
|     }; |     }; | ||||||
|   | |||||||
| @@ -191,7 +191,6 @@ namespace ix | |||||||
|                         // Make sure the OS send buffer is flushed before moving on |                         // Make sure the OS send buffer is flushed before moving on | ||||||
|                         do |                         do | ||||||
|                         { |                         { | ||||||
|                             size_t bufferedAmount = client->bufferedAmount(); |  | ||||||
|                             std::chrono::duration<double, std::milli> duration(500); |                             std::chrono::duration<double, std::milli> duration(500); | ||||||
|                             std::this_thread::sleep_for(duration); |                             std::this_thread::sleep_for(duration); | ||||||
|                         } while (client->bufferedAmount() != 0); |                         } while (client->bufferedAmount() != 0); | ||||||
|   | |||||||
| @@ -6,4 +6,4 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #define IX_WEBSOCKET_VERSION "11.2.4" | #define IX_WEBSOCKET_VERSION "11.3.1" | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								main.cpp
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								main.cpp
									
									
									
									
									
								
							| @@ -15,6 +15,7 @@ | |||||||
|  |  | ||||||
| #include <ixwebsocket/IXNetSystem.h> | #include <ixwebsocket/IXNetSystem.h> | ||||||
| #include <ixwebsocket/IXWebSocket.h> | #include <ixwebsocket/IXWebSocket.h> | ||||||
|  | #include <ixwebsocket/IXUserAgent.h> | ||||||
| #include <iostream> | #include <iostream> | ||||||
|  |  | ||||||
| int main() | int main() | ||||||
| @@ -25,9 +26,12 @@ int main() | |||||||
|     // Our websocket object |     // Our websocket object | ||||||
|     ix::WebSocket webSocket; |     ix::WebSocket webSocket; | ||||||
|  |  | ||||||
|  |     // Connect to a server with encryption | ||||||
|  |     // See https://machinezone.github.io/IXWebSocket/usage/#tls-support-and-configuration | ||||||
|     std::string url("wss://echo.websocket.org"); |     std::string url("wss://echo.websocket.org"); | ||||||
|     webSocket.setUrl(url); |     webSocket.setUrl(url); | ||||||
|  |  | ||||||
|  |     std::cout << ix::userAgent() << std::endl; | ||||||
|     std::cout << "Connecting to " << url << "..." << std::endl; |     std::cout << "Connecting to " << url << "..." << std::endl; | ||||||
|  |  | ||||||
|     // Setup a callback to be fired (in a background thread, watch out for race conditions !) |     // Setup a callback to be fired (in a background thread, watch out for race conditions !) | ||||||
| @@ -44,6 +48,12 @@ int main() | |||||||
|                 std::cout << "Connection established" << std::endl; |                 std::cout << "Connection established" << std::endl; | ||||||
|                 std::cout << "> " << std::flush; |                 std::cout << "> " << std::flush; | ||||||
|             } |             } | ||||||
|  |             else if (msg->type == ix::WebSocketMessageType::Error) | ||||||
|  |             { | ||||||
|  |                 // Maybe SSL is not configured properly | ||||||
|  |                 std::cout << "Connection error: " << msg->errorInfo.reason << std::endl; | ||||||
|  |                 std::cout << "> " << std::flush; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								makefile.dev
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								makefile.dev
									
									
									
									
									
								
							| @@ -22,37 +22,37 @@ install: brew | |||||||
| # Default rule does not use python as that requires first time users to have Python3 installed | # Default rule does not use python as that requires first time users to have Python3 installed | ||||||
| # | # | ||||||
| brew: | brew: | ||||||
| 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; ninja install) | 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=OFF -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; ninja install) | ||||||
|  |  | ||||||
| # Docker default target. We've had problems with OpenSSL and TLS 1.3 (on the | # Docker default target. We've had problems with OpenSSL and TLS 1.3 (on the | ||||||
| # server side ?) and I can't work-around it easily, so we're using mbedtls on | # server side ?) and I can't work-around it easily, so we're using mbedtls on | ||||||
| # Linux for the SSL backend, which works great. | # Linux for the SSL backend, which works great. | ||||||
| ws_mbedtls_install: | ws_mbedtls_install: | ||||||
| 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_ZLIB=OFF -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja install) | 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_ZLIB=OFF -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja install) | ||||||
|  |  | ||||||
| ws: | ws: | ||||||
| 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install) | 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install) | ||||||
|  |  | ||||||
| ws_unity: | ws_unity: | ||||||
| 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install) | 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install) | ||||||
|  |  | ||||||
| ws_install: | ws_install: | ||||||
| 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. -DUSE_TEST=0 && ninja install) | 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. -DUSE_TEST=0 && ninja install) | ||||||
|  |  | ||||||
| ws_install_release: | ws_install_release: | ||||||
| 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. -DUSE_TEST=0 && ninja install) | 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. -DUSE_TEST=0 && ninja install) | ||||||
|  |  | ||||||
| ws_openssl_install: | ws_openssl_install: | ||||||
| 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_OPEN_SSL=1 .. ; ninja install) | 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_OPEN_SSL=1 .. ; ninja install) | ||||||
|  |  | ||||||
| ws_mbedtls: | ws_mbedtls: | ||||||
| 	mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; make -j 4) | 	mkdir -p build && (cd build ; cmake -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; make -j 4) | ||||||
|  |  | ||||||
| ws_no_ssl: | ws_no_ssl: | ||||||
| 	mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_WS=1 .. ; make -j 4) | 	mkdir -p build && (cd build ; cmake -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_WS=1 .. ; make -j 4) | ||||||
|  |  | ||||||
| ws_no_python: | ws_no_python: | ||||||
| 	mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. ; make -j4 install) | 	mkdir -p build && (cd build ; cmake -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. ; make -j4 install) | ||||||
|  |  | ||||||
| uninstall: | uninstall: | ||||||
| 	xargs rm -fv < build/install_manifest.txt | 	xargs rm -fv < build/install_manifest.txt | ||||||
| @@ -111,27 +111,27 @@ test_server: | |||||||
| 	(cd test && npm i ws && node broadcast-server.js) | 	(cd test && npm i ws && node broadcast-server.js) | ||||||
|  |  | ||||||
| test: | test: | ||||||
| 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 ..) | 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 ..) | ||||||
| 	(cd build ; ninja) | 	(cd build ; ninja) | ||||||
| 	(cd build ; ninja -v test) | 	(cd build ; ninja -v test) | ||||||
|  |  | ||||||
| test_asan: | test_asan: | ||||||
| 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer") | 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer") | ||||||
| 	(cd build ; ninja) | 	(cd build ; ninja) | ||||||
| 	(cd build ; ctest -V .) | 	(cd build ; ctest -V .) | ||||||
|  |  | ||||||
| test_tsan_mbedtls: | test_tsan_mbedtls: | ||||||
| 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_MBED_TLS=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer") | 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_MBED_TLS=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer") | ||||||
| 	(cd build ; ninja) | 	(cd build ; ninja) | ||||||
| 	(cd build ; ninja test) | 	(cd build ; ninja test) | ||||||
|  |  | ||||||
| test_tsan_openssl: | test_tsan_openssl: | ||||||
| 	mkdir -p build && (cd build ; cmake -GNinja --DCMAKE_UNITY_BUILD=ON DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPENS_SSL=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer") | 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_UNITY_BUILD=ON DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPENS_SSL=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer") | ||||||
| 	(cd build ; ninja) | 	(cd build ; ninja) | ||||||
| 	(cd build ; ninja test) | 	(cd build ; ninja test) | ||||||
|  |  | ||||||
| test_tsan_sectransport: | test_tsan_sectransport: | ||||||
| 	mkdir -p build && (cd build ; cmake -GNinja --DCMAKE_UNITY_BUILD=ON DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPENS_SSL=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer") | 	mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPENS_SSL=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer") | ||||||
| 	(cd build ; ninja) | 	(cd build ; ninja) | ||||||
| 	(cd build ; ninja test) | 	(cd build ; ninja test) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										5134
									
								
								third_party/cli11/CLI11.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5134
									
								
								third_party/cli11/CLI11.hpp
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2
									
								
								ws/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								ws/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -8,7 +8,7 @@ | |||||||
|       "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" |       "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" | ||||||
|     }, |     }, | ||||||
|     "ws": { |     "ws": { | ||||||
|       "version": "6.2.0", |       "version": ">=6.2.2", | ||||||
|       "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.0.tgz", |       "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.0.tgz", | ||||||
|       "integrity": "sha512-deZYUNlt2O4buFCa3t5bKLf8A7FPP/TVjwOeVNpw818Ma5nk4MLXls2eoEGS39o8119QIYxTrTDoPQ5B/gTD6w==", |       "integrity": "sha512-deZYUNlt2O4buFCa3t5bKLf8A7FPP/TVjwOeVNpw818Ma5nk4MLXls2eoEGS39o8119QIYxTrTDoPQ5B/gTD6w==", | ||||||
|       "requires": { |       "requires": { | ||||||
|   | |||||||
							
								
								
									
										35
									
								
								ws/ws.cpp
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								ws/ws.cpp
									
									
									
									
									
								
							| @@ -632,7 +632,8 @@ namespace ix | |||||||
|                          uint32_t maxWaitBetweenReconnectionRetries, |                          uint32_t maxWaitBetweenReconnectionRetries, | ||||||
|                          const ix::SocketTLSOptions& tlsOptions, |                          const ix::SocketTLSOptions& tlsOptions, | ||||||
|                          const std::string& subprotocol, |                          const std::string& subprotocol, | ||||||
|                          int pingIntervalSecs); |                          int pingIntervalSecs, | ||||||
|  |                          bool decompressGzipMessages); | ||||||
|  |  | ||||||
|         void subscribe(const std::string& channel); |         void subscribe(const std::string& channel); | ||||||
|         void start(); |         void start(); | ||||||
| @@ -657,6 +658,7 @@ namespace ix | |||||||
|         bool _binaryMode; |         bool _binaryMode; | ||||||
|         std::atomic<int> _receivedBytes; |         std::atomic<int> _receivedBytes; | ||||||
|         std::atomic<int> _sentBytes; |         std::atomic<int> _sentBytes; | ||||||
|  |         bool _decompressGzipMessages; | ||||||
|  |  | ||||||
|         void log(const std::string& msg); |         void log(const std::string& msg); | ||||||
|         WebSocketHttpHeaders parseHeaders(const std::string& data); |         WebSocketHttpHeaders parseHeaders(const std::string& data); | ||||||
| @@ -670,12 +672,14 @@ namespace ix | |||||||
|                                        uint32_t maxWaitBetweenReconnectionRetries, |                                        uint32_t maxWaitBetweenReconnectionRetries, | ||||||
|                                        const ix::SocketTLSOptions& tlsOptions, |                                        const ix::SocketTLSOptions& tlsOptions, | ||||||
|                                        const std::string& subprotocol, |                                        const std::string& subprotocol, | ||||||
|                                        int pingIntervalSecs) |                                        int pingIntervalSecs, | ||||||
|  |                                        bool decompressGzipMessages) | ||||||
|         : _url(url) |         : _url(url) | ||||||
|         , _disablePerMessageDeflate(disablePerMessageDeflate) |         , _disablePerMessageDeflate(disablePerMessageDeflate) | ||||||
|         , _binaryMode(binaryMode) |         , _binaryMode(binaryMode) | ||||||
|         , _receivedBytes(0) |         , _receivedBytes(0) | ||||||
|         , _sentBytes(0) |         , _sentBytes(0) | ||||||
|  |         , _decompressGzipMessages(decompressGzipMessages) | ||||||
|     { |     { | ||||||
|         if (disableAutomaticReconnection) |         if (disableAutomaticReconnection) | ||||||
|         { |         { | ||||||
| @@ -784,7 +788,21 @@ namespace ix | |||||||
|             { |             { | ||||||
|                 spdlog::info("Received {} bytes", msg->wireSize); |                 spdlog::info("Received {} bytes", msg->wireSize); | ||||||
|  |  | ||||||
|                 ss << "ws_connect: received message: " << msg->str; |                 std::string payload = msg->str; | ||||||
|  |                 if (_decompressGzipMessages) | ||||||
|  |                 { | ||||||
|  |                     std::string decompressedBytes; | ||||||
|  |                     if (gzipDecompress(payload, decompressedBytes)) | ||||||
|  |                     { | ||||||
|  |                         payload = decompressedBytes; | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         spdlog::error("Error decompressing: {}", payload); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 ss << "ws_connect: received message: " << payload; | ||||||
|                 log(ss.str()); |                 log(ss.str()); | ||||||
|             } |             } | ||||||
|             else if (msg->type == ix::WebSocketMessageType::Error) |             else if (msg->type == ix::WebSocketMessageType::Error) | ||||||
| @@ -837,7 +855,8 @@ namespace ix | |||||||
|                         uint32_t maxWaitBetweenReconnectionRetries, |                         uint32_t maxWaitBetweenReconnectionRetries, | ||||||
|                         const ix::SocketTLSOptions& tlsOptions, |                         const ix::SocketTLSOptions& tlsOptions, | ||||||
|                         const std::string& subprotocol, |                         const std::string& subprotocol, | ||||||
|                         int pingIntervalSecs) |                         int pingIntervalSecs, | ||||||
|  |                         bool decompressGzipMessages) | ||||||
|     { |     { | ||||||
|         std::cout << "Type Ctrl-D to exit prompt..." << std::endl; |         std::cout << "Type Ctrl-D to exit prompt..." << std::endl; | ||||||
|         WebSocketConnect webSocketChat(url, |         WebSocketConnect webSocketChat(url, | ||||||
| @@ -848,7 +867,8 @@ namespace ix | |||||||
|                                        maxWaitBetweenReconnectionRetries, |                                        maxWaitBetweenReconnectionRetries, | ||||||
|                                        tlsOptions, |                                        tlsOptions, | ||||||
|                                        subprotocol, |                                        subprotocol, | ||||||
|                                        pingIntervalSecs); |                                        pingIntervalSecs, | ||||||
|  |                                        decompressGzipMessages); | ||||||
|         webSocketChat.start(); |         webSocketChat.start(); | ||||||
|  |  | ||||||
|         while (true) |         while (true) | ||||||
| @@ -2490,6 +2510,7 @@ int main(int argc, char** argv) | |||||||
|     uint32_t maxWaitBetweenReconnectionRetries = 10 * 1000; // 10 seconds |     uint32_t maxWaitBetweenReconnectionRetries = 10 * 1000; // 10 seconds | ||||||
|     int pingIntervalSecs = 30; |     int pingIntervalSecs = 30; | ||||||
|     int runCount = 1; |     int runCount = 1; | ||||||
|  |     bool decompressGzipMessages = false; | ||||||
|  |  | ||||||
|     auto addGenericOptions = [&pidfile](CLI::App* app) { |     auto addGenericOptions = [&pidfile](CLI::App* app) { | ||||||
|         app->add_option("--pidfile", pidfile, "Pid file"); |         app->add_option("--pidfile", pidfile, "Pid file"); | ||||||
| @@ -2552,6 +2573,7 @@ int main(int argc, char** argv) | |||||||
|                            "Max Wait Time between reconnection retries"); |                            "Max Wait Time between reconnection retries"); | ||||||
|     connectApp->add_option("--ping_interval", pingIntervalSecs, "Interval between sending pings"); |     connectApp->add_option("--ping_interval", pingIntervalSecs, "Interval between sending pings"); | ||||||
|     connectApp->add_option("--subprotocol", subprotocol, "Subprotocol"); |     connectApp->add_option("--subprotocol", subprotocol, "Subprotocol"); | ||||||
|  |     connectApp->add_flag("-g", decompressGzipMessages, "Decompress gziped messages"); | ||||||
|     addGenericOptions(connectApp); |     addGenericOptions(connectApp); | ||||||
|     addTLSOptions(connectApp); |     addTLSOptions(connectApp); | ||||||
|  |  | ||||||
| @@ -2740,7 +2762,8 @@ int main(int argc, char** argv) | |||||||
|                                   maxWaitBetweenReconnectionRetries, |                                   maxWaitBetweenReconnectionRetries, | ||||||
|                                   tlsOptions, |                                   tlsOptions, | ||||||
|                                   subprotocol, |                                   subprotocol, | ||||||
|                                   pingIntervalSecs); |                                   pingIntervalSecs, | ||||||
|  |                                   decompressGzipMessages); | ||||||
|     } |     } | ||||||
|     else if (app.got_subcommand("autoroute")) |     else if (app.got_subcommand("autoroute")) | ||||||
|     { |     { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user