mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-08-25 03:17:16 +00:00
A wss:// WebSocket enters a single TLS session from several threads: the read path, the application's send()/close(), and the heartbeat ping thread. The existing write_mutex_ only serializes writers, so a reader's SSL_read and a writer's SSL_write (plus the SSL_peek in is_peer_closed() on the write path) run concurrently on the same session. OpenSSL and the other backends forbid concurrent access to one session, so this corrupts the record layer: messages are silently dropped, and under ASan it shows up as a heap-buffer-overflow. It affects wss:// only; plain ws:// is unaffected because the kernel allows concurrent recv()/send() on a socket. Route wss:// through a new WebSocketSSLStream that serializes every TLS call with one per-stream mutex. The socket is kept non-blocking for the stream's lifetime and each read()/write() performs a single non-blocking TLS call under the lock, then waits for readiness with select() outside the lock. The lock is therefore held only for CPU-bound work, so a reader blocked waiting for data never stalls a concurrent sender. Because the socket is non-blocking, a TLS call can stop needing either direction, so read() also waits for writability on WantWrite and write() waits for readability on WantRead. A read that shares its session with the send path has to flush pending output before it can decrypt more input, and Mbed TLS surfaces this on every mbedtls_ssl_read(). The read timeouts are atomic since WebSocket::close() shortens them from the closing thread while the receive thread is inside wait_readable(). SSLSocketStream is left untouched, so ordinary HTTP/HTTPS keeps its exact code path and performance. The heartbeat ping thread also stays, so timer-driven pings keep working as before. Add test_websocket_thread_safety.cc, which drives send/close/heartbeat against a concurrent reader over wss://. Built with ASan in CI, a regression surfaces as a heap-buffer-overflow.
85 lines
1.4 KiB
Plaintext
85 lines
1.4 KiB
Plaintext
tags
|
|
AGENTS.md
|
|
docs-src/pages/AGENTS.md
|
|
plans/
|
|
work/
|
|
|
|
# Ignore executables (no extension) but not source files
|
|
example/server
|
|
!example/server.*
|
|
example/client
|
|
!example/client.*
|
|
example/hello
|
|
!example/hello.*
|
|
example/simplecli
|
|
!example/simplecli.*
|
|
example/simplesvr
|
|
!example/simplesvr.*
|
|
example/benchmark
|
|
!example/benchmark.*
|
|
example/redirect
|
|
!example/redirect.*
|
|
example/ssecli
|
|
!example/ssecli.*
|
|
example/ssecli-stream
|
|
!example/ssecli-stream.*
|
|
example/ssesvr
|
|
!example/ssesvr.*
|
|
example/upload
|
|
!example/upload.*
|
|
example/one_time_request
|
|
!example/one_time_request.*
|
|
example/server_and_client
|
|
!example/server_and_client.*
|
|
example/accept_header
|
|
!example/accept_header.*
|
|
example/wsecho
|
|
!example/wsecho.*
|
|
example/*.pem
|
|
test/httplib.cc
|
|
test/httplib.h
|
|
test/test
|
|
test/test_mbedtls
|
|
test/test_wolfssl
|
|
test/test_no_tls
|
|
test/server_fuzzer
|
|
test/client_fuzzer
|
|
test/header_parser_fuzzer
|
|
test/url_parser_fuzzer
|
|
test/test_proxy
|
|
test/test_proxy_mbedtls
|
|
test/test_proxy_wolfssl
|
|
test/test_split
|
|
test/test_split_mbedtls
|
|
test/test_split_wolfssl
|
|
test/test_split_no_tls
|
|
test/test_websocket_heartbeat
|
|
test/test_websocket_thread_safety
|
|
test/test_thread_pool
|
|
test/test_benchmark
|
|
test/test.xcodeproj/xcuser*
|
|
test/test.xcodeproj/*/xcuser*
|
|
test/*.o
|
|
test/*.pem
|
|
test/*.srl
|
|
test/*.log
|
|
test/_build_*
|
|
benchmark/server*
|
|
|
|
*.swp
|
|
|
|
build/
|
|
Debug
|
|
Release
|
|
*.vcxproj.user
|
|
*.sdf
|
|
*.suo
|
|
*.opensdf
|
|
*.db
|
|
ipch
|
|
*.dSYM
|
|
*.pyc
|
|
.*
|
|
!/.gitattributes
|
|
!/.github
|