Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 32 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,24 @@ set( IXWEBSOCKET_HEADERS

option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" OFF)
option(USE_TLS "Enable TLS support" FALSE)
option(USE_NETWORK_FRAMEWORK "Use Apple's Network.framework TLS backend (macOS 10.15+)" OFF)
if (USE_NETWORK_FRAMEWORK)
if (NOT APPLE OR NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
message(FATAL_ERROR "Network.framework backend currently supports macOS only")
endif()
if (USE_OPEN_SSL OR USE_LIBRE_SSL OR USE_MBED_TLS OR USE_SECURE_TRANSPORT)
message(FATAL_ERROR "USE_NETWORK_FRAMEWORK cannot be combined with another TLS backend")
endif()
if (CMAKE_OSX_DEPLOYMENT_TARGET AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS 10.15)
message(FATAL_ERROR "Network.framework backend requires macOS 10.15 or later")
endif()
set(USE_TLS ON)
endif()

if (USE_TLS)
# default to securetranport on Apple if nothing is configured
if (APPLE)
if (NOT USE_MBED_TLS AND NOT USE_OPEN_SSL AND NOT USE_LIBRE_SSL) # unless we want something else
if (NOT USE_MBED_TLS AND NOT USE_OPEN_SSL AND NOT USE_LIBRE_SSL AND NOT USE_NETWORK_FRAMEWORK) # unless we want something else
set(USE_SECURE_TRANSPORT ON)
endif()
# default to mbedtls on windows if nothing is configured
Expand All @@ -140,7 +153,10 @@ if (USE_TLS)
endif()
endif()

if (USE_MBED_TLS)
if (USE_NETWORK_FRAMEWORK)
list(APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSocketNetwork.h)
list(APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSocketNetwork.cpp)
elseif (USE_MBED_TLS)
list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSocketMbedTLS.h)
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSocketMbedTLS.cpp)
elseif (USE_SECURE_TRANSPORT)
Expand All @@ -156,7 +172,7 @@ endif()

if(BUILD_SHARED_LIBS)
# Building shared library

if(MSVC)
# Workaround for some projects
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
Expand All @@ -182,7 +198,9 @@ endif()

if (USE_TLS)
target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_TLS)
if (USE_MBED_TLS)
if (USE_NETWORK_FRAMEWORK)
target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_NETWORK_FRAMEWORK)
elseif (USE_MBED_TLS)
target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_MBED_TLS)
elseif (USE_OPEN_SSL)
target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_OPEN_SSL)
Expand All @@ -196,7 +214,11 @@ if (USE_TLS)
endif()

if (USE_TLS)
if (USE_OPEN_SSL)
if (USE_NETWORK_FRAMEWORK)
message(STATUS "TLS configured to use Network.framework")
target_compile_options(ixwebsocket PRIVATE -fblocks)
target_link_libraries(ixwebsocket PRIVATE "-framework Network" "-framework Security" "-framework CoreFoundation")
elseif (USE_OPEN_SSL)
message(STATUS "TLS configured to use openssl")

# Help finding Homebrew's OpenSSL on macOS
Expand Down Expand Up @@ -224,11 +246,11 @@ if (USE_TLS)
# This MBEDTLS_FOUND check is to help find a cmake manually configured MbedTLS
if (NOT MBEDTLS_FOUND)
find_package(MbedTLS REQUIRED)

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 PRIVATE ${MBEDTLS_LIBRARIES})
Expand Down Expand Up @@ -304,7 +326,7 @@ if (IXWEBSOCKET_INSTALL)

configure_file("${CMAKE_CURRENT_LIST_DIR}/ixwebsocket-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/ixwebsocket-config.cmake" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ixwebsocket-config.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ixwebsocket")

set(prefix ${CMAKE_INSTALL_PREFIX})
configure_file("${CMAKE_CURRENT_LIST_DIR}/ixwebsocket.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/ixwebsocket.pc" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ixwebsocket.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
Expand All @@ -331,7 +353,7 @@ if (USE_TEST)
add_subdirectory(test)
endif()

if (BUILD_DEMO)
if (BUILD_DEMO)
add_executable(demo main.cpp)
target_link_libraries(demo ixwebsocket)
target_link_libraries(demo ixwebsocket)
endif()
26 changes: 26 additions & 0 deletions docs/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Options for building:
* `-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_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_NETWORK_FRAMEWORK=ON` enables the experimental native macOS TLS backend and also enables `USE_TLS`. It requires macOS 10.15 or later and links Apple's Network, Security, and CoreFoundation frameworks, with no OpenSSL library dependency. It cannot be combined with another TLS backend; the make target below overrides cached backend selections. Client and server TLS, including mutual TLS, are supported. The existing Apple backend remains the default.
* `-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_TEST=1` will build the unittest
Expand Down Expand Up @@ -117,3 +118,28 @@ app@ca2340eb9106:~$ ws --help
ws is a websocket tool
...
```

### Native macOS TLS with Network.framework

The developer makefile builds the library, `ws`, and tests in `build`:

```sh
make -f makefile.dev ws_network_framework
make -f makefile.dev test_network_framework
```

Or invoke CMake directly:

```sh
cmake -S . -B build -DUSE_NETWORK_FRAMEWORK=ON \
-DUSE_OPEN_SSL=OFF -DUSE_LIBRE_SSL=OFF -DUSE_MBED_TLS=OFF -DUSE_SECURE_TRANSPORT=OFF
cmake --build build
```

To build the native backend's integration tests, add `-DUSE_TEST=ON`, then run
`ctest --test-dir build -R IXSocketNetworkTest --output-on-failure`.
The tests use the `openssl` command-line tool only to generate temporary credentials
inside the build directory. The library itself does not link OpenSSL. Tests never
modify the system keychain.

This backend currently targets macOS; iOS, tvOS, and watchOS builds are not enabled.
29 changes: 29 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -661,3 +661,32 @@ For a server, specifying `caFile` implies that:
1. It must be signed by one of the trusted roots in the file

By default, a destination's hostname is always validated against the certificate that it presents. To accept certificates with any hostname, set `ix::SocketTLSOptions::disable_hostname_validation` to `true`.

### Network.framework backend on macOS

Build with `USE_NETWORK_FRAMEWORK=ON` to use native TLS for `wss://` and `https://`
clients and TLS-enabled WebSocket/HTTP servers. Network.framework handles connection
setup, DNS, and TCP. Application HTTP and WebSocket handling stays in IXWebSocket.
TLS 1.2 is the minimum; TLS 1.3 is negotiated when supported by the peer.

The existing `SocketTLSOptions` fields apply:

- `certFile` and `keyFile` accept a PEM certificate chain (leaf first) and matching,
unencrypted PEM private key. Both are required for a TLS server and optional for a
client presenting a certificate. Credentials are imported in memory, without
installing them in a keychain.
- `caFile = "SYSTEM"` uses Apple's trust evaluation and configured system trust.
A PEM CA file or in-memory PEM bundle instead restricts trust to those anchors.
- `caFile = "NONE"` disables peer verification. On a server this also disables the
requirement for a client certificate. Other CA settings require client
authentication, matching the existing server options.
- `disable_hostname_validation` skips the client's hostname check while retaining
certificate trust evaluation. IP literals are checked against IP SAN entries.
- Custom `ciphers` strings are currently rejected; leave `ciphers` at `DEFAULT`.

The native server uses a Network.framework listener. `createSocket` cannot adopt an
existing BSD descriptor for TLS with this backend. The listener requires a numeric
bind address and uses the framework's TCP listen queue rather than the BSD backlog
setting. Pending connections are bounded by `maxConnections`. Server TLS handshakes
have a ten-second limit and are interrupted when the server stops. Client connection
timeouts use the caller's cancellation callback, including HTTP/WebSocket timeouts.
11 changes: 5 additions & 6 deletions ixwebsocket/IXSocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

#pragma once

#include "IXCancellationRequest.h"
#include "IXNetSystem.h"
#include "IXProgressCallback.h"
#include "IXSelectInterrupt.h"
#include <atomic>
#include <cstddef>
#include <cstdint>
Expand All @@ -14,11 +18,6 @@
#include <mutex>
#include <string>

#include "IXCancellationRequest.h"
#include "IXNetSystem.h"
#include "IXProgressCallback.h"
#include "IXSelectInterrupt.h"

namespace ix
{
enum class PollResultType
Expand All @@ -43,7 +42,6 @@ namespace ix
bool wakeUpFromPoll(uint64_t wakeUpCode);
bool isWakeUpFromPollSupported();

PollResultType isReadyToWrite(int timeoutMs);
PollResultType isReadyToRead(int timeoutMs);

// Virtual methods
Expand All @@ -58,6 +56,7 @@ namespace ix
virtual std::ptrdiff_t send(char* buffer, size_t length);
std::ptrdiff_t send(const std::string& buffer);
virtual std::ptrdiff_t recv(void* buffer, size_t length);
virtual PollResultType isReadyToWrite(int timeoutMs);

// Blocking and cancellable versions, working with socket that can be set
// to non blocking mode. Used during HTTP upgrade.
Expand Down
10 changes: 10 additions & 0 deletions ixwebsocket/IXSocketFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include "IXSocketMbedTLS.h"
#elif defined(IXWEBSOCKET_USE_OPEN_SSL) || defined(IXWEBSOCKET_USE_LIBRE_SSL)
#include "IXSocketOpenSSL.h"
#elif defined(IXWEBSOCKET_USE_NETWORK_FRAMEWORK)
#include "IXSocketNetwork.h"
#elif __APPLE__
#include "IXSocketAppleSSL.h"
#endif
Expand Down Expand Up @@ -45,6 +47,14 @@ namespace ix
socket = ix::make_unique<SocketMbedTLS>(tlsOptions, fd);
#elif defined(IXWEBSOCKET_USE_OPEN_SSL) || defined(IXWEBSOCKET_USE_LIBRE_SSL)
socket = ix::make_unique<SocketOpenSSL>(tlsOptions, fd);
#elif defined(IXWEBSOCKET_USE_NETWORK_FRAMEWORK)
if (fd != -1)
{
errorMsg =
"Network.framework requires a native listener; BSD sockets cannot be adopted";
return nullptr;
}
socket = ix::make_unique<SocketNetwork>(tlsOptions);
#elif defined(__APPLE__)
socket = ix::make_unique<SocketAppleSSL>(tlsOptions, fd);
#endif
Expand Down
Loading
Loading