This is an automated email from the ASF dual-hosted git repository.

HTHou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iotdb-client-rust.git


The following commit(s) were added to refs/heads/main by this push:
     new 54bfa1f  Upgrade Thrift to 0.25.0 (#13)
54bfa1f is described below

commit 54bfa1fa65c8d80ca9952dd5dcd1e5d16ef9105d
Author: Haonan <[email protected]>
AuthorDate: Mon Oct 5 20:34:50 2026 +0800

    Upgrade Thrift to 0.25.0 (#13)
    
    * Upgrade Thrift to 0.25.0
    
    * Use Thrift native TLS channel
---
 Cargo.toml            | 13 ++++++---
 src/connection/mod.rs | 74 +++++++++------------------------------------------
 2 files changed, 22 insertions(+), 65 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index 5b58379..50579e6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -32,11 +32,11 @@ categories = ["database"]
 name = "iotdb_client"
 
 [dependencies]
-thrift = "0.23"
+thrift = "0.25"
 byteorder = "1.5"
 chrono = "0.4"
 log = "0.4"
-# thrift 0.23 allows any uuid 1.x; 1.21+ raises MSRV to Rust 1.85.
+# thrift 0.25 allows any uuid 1.x; 1.21+ raises MSRV to Rust 1.85.
 uuid = "=1.20.0"
 rustls = { version = "0.23", default-features = false, features = ["ring", 
"std", "tls12"], optional = true }
 rustls-pemfile = { version = "2.2", optional = true }
@@ -55,4 +55,11 @@ env_logger = "0.11"
 default = []
 # TLS 1.2/1.3 via rustls, using the ring crypto provider and platform
 # trust roots with consistent WebPKI verification. Adds `use_ssl` & friends to 
SessionConfig.
-tls = ["dep:rustls", "dep:rustls-pemfile", "dep:rustls-native-certs", 
"dep:zeroize", "dep:security-framework"]
+tls = [
+    "thrift/rustls",
+    "dep:rustls",
+    "dep:rustls-pemfile",
+    "dep:rustls-native-certs",
+    "dep:zeroize",
+    "dep:security-framework",
+]
diff --git a/src/connection/mod.rs b/src/connection/mod.rs
index 7bcdf81..33f9a7c 100644
--- a/src/connection/mod.rs
+++ b/src/connection/mod.rs
@@ -35,15 +35,14 @@ use rustls::crypto::WebPkiSupportedAlgorithms;
 #[cfg(feature = "tls")]
 use rustls::pki_types::{CertificateDer, ServerName, UnixTime};
 #[cfg(feature = "tls")]
-use rustls::{
-    ClientConfig, ClientConnection, DigitallySignedStruct, RootCertStore, 
SignatureScheme,
-    StreamOwned,
-};
+use rustls::{ClientConfig, DigitallySignedStruct, RootCertStore, 
SignatureScheme};
 
 use thrift::protocol::{
     TBinaryInputProtocol, TBinaryOutputProtocol, TCompactInputProtocol, 
TCompactOutputProtocol,
     TInputProtocol, TOutputProtocol,
 };
+#[cfg(feature = "tls")]
+use thrift::transport::TTlsClientChannel;
 use thrift::transport::{TFramedReadTransport, TFramedWriteTransport, 
TIoChannel, TTcpChannel};
 
 use crate::error::{Error, Result};
@@ -197,9 +196,9 @@ impl Connection {
 
         #[cfg(feature = "tls")]
         if let Some(tls) = &options.tls {
-            let stream = tls_handshake(&endpoint, stream, tls)?;
-            let shared = SharedTlsStream::new(stream);
-            let (input, output) = build_protocols(shared.clone(), shared, 
options.protocol);
+            let channel = tls_channel(&endpoint, stream, tls)?;
+            let (read_half, write_half) = channel.split()?;
+            let (input, output) = build_protocols(read_half, write_half, 
options.protocol);
             return Ok(Self {
                 endpoint,
                 protocol: options.protocol,
@@ -275,28 +274,19 @@ fn connect_stream(endpoint: &Endpoint, connect_timeout: 
Duration) -> Result<TcpS
     })
 }
 
-/// Run the TLS handshake over an established TCP stream.
+/// Wrap an established TCP stream in Thrift's TLS channel and run the 
handshake.
 #[cfg(feature = "tls")]
-fn tls_handshake(
+fn tls_channel(
     endpoint: &Endpoint,
-    mut stream: TcpStream,
+    stream: TcpStream,
     tls: &TlsOptions,
-) -> Result<StreamOwned<ClientConnection, TcpStream>> {
+) -> Result<TTlsClientChannel> {
     let config = tls_client_config(tls)?;
     let domain = tls.domain_override.as_deref().unwrap_or(&endpoint.host);
     let server_name = ServerName::try_from(domain.to_owned())
         .map_err(|e| Error::Client(format!("invalid TLS server name 
'{domain}': {e}")))?;
-    let mut connection =
-        ClientConnection::new(config, server_name).map_err(|e| 
Error::Tls(e.to_string()))?;
-
-    connection
-        .complete_io(&mut stream)
-        .map_err(|e| Error::Tls(e.to_string()))?;
-    if connection.is_handshaking() {
-        return Err(Error::Tls("TLS handshake did not complete".into()));
-    }
-
-    Ok(StreamOwned::new(connection, stream))
+    TTlsClientChannel::with_stream(stream, server_name, config)
+        .map_err(|e| Error::Tls(e.to_string()))
 }
 
 #[cfg(feature = "tls")]
@@ -445,46 +435,6 @@ impl ServerCertVerifier for NoCertificateVerification {
     }
 }
 
-/// A `TlsStream` shared between the read and write transports.
-///
-/// `TTcpChannel::split` clones the underlying OS socket, but a TLS stream
-/// cannot be split that way (record layer state is shared), so both framed
-/// transports hold the same stream behind a mutex. The generated sync
-/// client fully writes + flushes a request before reading the response, so
-/// read and write never contend.
-#[cfg(feature = "tls")]
-#[derive(Clone)]
-struct 
SharedTlsStream(std::sync::Arc<std::sync::Mutex<StreamOwned<ClientConnection, 
TcpStream>>>);
-
-#[cfg(feature = "tls")]
-impl SharedTlsStream {
-    fn new(stream: StreamOwned<ClientConnection, TcpStream>) -> Self {
-        Self(std::sync::Arc::new(std::sync::Mutex::new(stream)))
-    }
-
-    fn lock(&self) -> std::sync::MutexGuard<'_, StreamOwned<ClientConnection, 
TcpStream>> {
-        self.0.lock().unwrap_or_else(|p| p.into_inner())
-    }
-}
-
-#[cfg(feature = "tls")]
-impl Read for SharedTlsStream {
-    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
-        self.lock().read(buf)
-    }
-}
-
-#[cfg(feature = "tls")]
-impl Write for SharedTlsStream {
-    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
-        self.lock().write(buf)
-    }
-
-    fn flush(&mut self) -> std::io::Result<()> {
-        self.lock().flush()
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;

Reply via email to