protocol: resolve TLS transport from the bound session, not thread-local io_ssl
file_send.c chose between sendfile() and the TLS-aware buffered path by calling io_get_ssl(), which reads the thread-local io_ssl. A worker thread that bound a TLS ProtocolSession via protocol_session_bind() never ran the handshake in that thread, so io_ssl is NULL there and a TLS + --threads transfer took the raw sendfile() path on an encrypted socket. Add protocol_current_ssl(), which prefers the bound session's SSL and falls back to io_ssl on the fd-shim path, and use it in file_send.c. Un-xfail test_tls_with_multithreading.
This commit is contained in:
@@ -124,8 +124,12 @@ bool file_send_sendfile_with_skip(File* file, int file_descriptor, bool use_meta
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* sendfile cannot encrypt TLS records. Keep the framing identical but
|
/* sendfile cannot encrypt TLS records. Keep the framing identical but
|
||||||
route encrypted transfers through the deadline-aware IO layer. */
|
route encrypted transfers through the deadline-aware IO layer. Resolve
|
||||||
if (io_get_ssl() != NULL) {
|
the transport from the bound session, not the thread-local io_ssl: a
|
||||||
|
worker thread running a TLS transfer has its SSL only on the session it
|
||||||
|
bound, so io_get_ssl() would be NULL there and the raw sendfile() path
|
||||||
|
would be taken on an encrypted socket. */
|
||||||
|
if (protocol_current_ssl() != NULL) {
|
||||||
unsigned char buffer[64 * 1024];
|
unsigned char buffer[64 * 1024];
|
||||||
unsigned long long remaining = file_size;
|
unsigned long long remaining = file_size;
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
|||||||
@@ -270,6 +270,17 @@ SSL* io_get_ssl(void) {
|
|||||||
return io_ssl;
|
return io_ssl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSL* protocol_current_ssl(void) {
|
||||||
|
/* The bound session is the authoritative transport for a worker thread: it
|
||||||
|
* was explicitly handed to protocol_session_bind() and carries its own SSL,
|
||||||
|
* whereas io_ssl is thread-local and NULL in a thread that never performed
|
||||||
|
* the handshake. With no session bound (the fd-shim path), fall back to the
|
||||||
|
* legacy thread-local SSL. */
|
||||||
|
if (bound_session)
|
||||||
|
return bound_session->ssl;
|
||||||
|
return io_ssl;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long long protocol_bytes_written(void) {
|
unsigned long long protocol_bytes_written(void) {
|
||||||
return atomic_load(&io_bytes_written);
|
return atomic_load(&io_bytes_written);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,6 +216,15 @@ void io_set_bwlimit(unsigned long long bytes_per_sec);
|
|||||||
unsigned long long io_get_bwlimit(void);
|
unsigned long long io_get_bwlimit(void);
|
||||||
void io_set_ssl(SSL* ssl);
|
void io_set_ssl(SSL* ssl);
|
||||||
SSL* io_get_ssl(void);
|
SSL* io_get_ssl(void);
|
||||||
|
/* SSL object of the transport in effect on this thread: the currently bound
|
||||||
|
* session's SSL when a session is bound, otherwise the legacy thread-local
|
||||||
|
* io_ssl. NULL for a plaintext transport. Unlike io_get_ssl(), this resolves
|
||||||
|
* worker threads that bound a TLS session via protocol_session_set_ssl()/
|
||||||
|
* protocol_session_bind() but never called io_set_ssl() themselves (C11
|
||||||
|
* _Thread_local state is not inherited by a new thread). Callers that must
|
||||||
|
* choose a TLS-only code path (e.g. file_send.c's sendfile fallback) must use
|
||||||
|
* this instead of io_get_ssl(). */
|
||||||
|
SSL* protocol_current_ssl(void);
|
||||||
|
|
||||||
/* Process-wide wire byte counters. protocol_send_n_data/protocol_receive_n_data
|
/* Process-wide wire byte counters. protocol_send_n_data/protocol_receive_n_data
|
||||||
* update them; the zero-copy sendfile path reports through
|
* update them; the zero-copy sendfile path reports through
|
||||||
|
|||||||
@@ -146,7 +146,6 @@ class TestTLSBasic:
|
|||||||
assert not missing, f"Missing files: {missing}"
|
assert not missing, f"Missing files: {missing}"
|
||||||
assert not mismatches, f"Mismatched files: {mismatches}"
|
assert not mismatches, f"Mismatched files: {mismatches}"
|
||||||
|
|
||||||
@pytest.mark.xfail(reason="TLS multithreading has architectural limitations with per-thread SSL context")
|
|
||||||
def test_tls_with_multithreading(self, certs):
|
def test_tls_with_multithreading(self, certs):
|
||||||
"""TLS + multithreading."""
|
"""TLS + multithreading."""
|
||||||
clean_dir(DEST_DIR)
|
clean_dir(DEST_DIR)
|
||||||
|
|||||||
Reference in New Issue
Block a user