rust: bssl-tls: Move DTLS methods into the correct typestate


Update-Note: previously dtlsv1_handle_timeout and dtlsv1_get_timeout
are incorrectly associated with connections under all modes. This is a
design error and they have moved into the correct typestate to prevent
misuses.

Signed-off-by: Xiangfei Ding <xfding@google.com>
Change-Id: I0b3aafa6b97345eda994dbbc882edd506a6a6964
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/98789
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/rust/bssl-tls/src/connection/transport.rs b/rust/bssl-tls/src/connection/transport.rs
index 67bc9ca..30d44dd 100644
--- a/rust/bssl-tls/src/connection/transport.rs
+++ b/rust/bssl-tls/src/connection/transport.rs
@@ -15,7 +15,10 @@
 //! TLS Connection transport settings
 //!
 
-use core::mem::{MaybeUninit, transmute};
+use core::mem::{
+    MaybeUninit,
+    transmute, //
+};
 
 use crate::{
     check_lib_error,
@@ -26,6 +29,7 @@
         TlsConnectionBuilder,
         methods::HasTlsConnectionMethod, //
     },
+    context::DtlsMode,
     context::HasBasicIo,
     errors::Error,
     io::{
@@ -77,60 +81,6 @@
         Ok(self)
     }
 
-    /// **For DTLS only**, trigger timeout handling on the connection.
-    ///
-    /// On success, this method call returns `true` when a timeout is hit and successfully handled;
-    /// `false` when no timeout has expired yet.
-    pub fn dtlsv1_handle_timeout(&mut self) -> Result<bool, Error> {
-        let conn = self.ptr();
-        let rc = unsafe {
-            // Safety: the connection handle here is still valid.
-            bssl_sys::DTLSv1_handle_timeout(conn)
-        };
-        if rc == 0 {
-            return Ok(false);
-        }
-        let _ = check_tls_error!(conn, rc);
-        Ok(true)
-    }
-
-    /// **For DTLS only**, get connection's remaining timeout.
-    ///
-    /// If a timeout is in effect, this method call returns the remaining seconds,
-    /// followed by the remaining microseconds.
-    pub fn dtlsv1_get_timeout(&self) -> Option<(i64, i64)> {
-        #[cfg(windows)]
-        #[repr(C)]
-        struct timeval {
-            tv_sec: core::ffi::c_long,
-            tv_usec: core::ffi::c_long,
-        }
-        #[cfg(not(windows))]
-        use bssl_sys::timeval;
-
-        let mut timeval = MaybeUninit::<timeval>::zeroed();
-        let rc = unsafe {
-            // Safety:
-            // - the validity of the handle `self.0` is witnessed by `self`;
-            // - the buffer for timeval is valid.
-            // - on Windows, the timeval structure should match the winsock2.h definition precisely.
-            bssl_sys::DTLSv1_get_timeout(self.ptr(), transmute(timeval.as_mut_ptr()))
-        };
-        match rc {
-            1 => {
-                let timeval = unsafe {
-                    // Safety: timeval is now valid as per BoringSSL specification.
-                    timeval.assume_init()
-                };
-                Some((timeval.tv_sec as i64, timeval.tv_usec as i64))
-            }
-            0 => None,
-            rc => {
-                unreachable!("BoringSSL should never return {rc} when calling dtlsv1_get_timeout")
-            }
-        }
-    }
-
     /// Check if the underlying **transport** has closed its write end.
     pub fn is_write_closed(&self) -> bool {
         self.get_connection_methods_ref()
@@ -185,3 +135,60 @@
         Ok(self)
     }
 }
+
+/// # DTLS
+impl<R> TlsConnection<R, DtlsMode> {
+    /// Trigger timeout handling on the connection.
+    ///
+    /// On success, this method call returns `true` when a timeout is hit and successfully handled;
+    /// `false` when no timeout has expired yet.
+    pub fn dtlsv1_handle_timeout(&mut self) -> Result<bool, Error> {
+        let conn = self.ptr();
+        let rc = unsafe {
+            // Safety: the connection handle here is still valid.
+            bssl_sys::DTLSv1_handle_timeout(conn)
+        };
+        if rc == 0 {
+            return Ok(false);
+        }
+        let _ = check_tls_error!(conn, rc);
+        Ok(true)
+    }
+
+    /// Get connection's remaining timeout.
+    ///
+    /// If a timeout is in effect, this method call returns the remaining seconds,
+    /// followed by the remaining microseconds.
+    pub fn dtlsv1_get_timeout(&self) -> Option<(i64, i64)> {
+        #[cfg(windows)]
+        #[repr(C)]
+        struct timeval {
+            tv_sec: core::ffi::c_long,
+            tv_usec: core::ffi::c_long,
+        }
+        #[cfg(not(windows))]
+        use bssl_sys::timeval;
+
+        let mut timeval = MaybeUninit::<timeval>::zeroed();
+        let rc = unsafe {
+            // Safety:
+            // - the validity of the handle `self.0` is witnessed by `self`;
+            // - the buffer for timeval is valid.
+            // - on Windows, the timeval structure should match the winsock2.h definition precisely.
+            bssl_sys::DTLSv1_get_timeout(self.ptr(), transmute(timeval.as_mut_ptr()))
+        };
+        match rc {
+            1 => {
+                let timeval = unsafe {
+                    // Safety: timeval is now valid as per BoringSSL specification.
+                    timeval.assume_init()
+                };
+                Some((timeval.tv_sec as i64, timeval.tv_usec as i64))
+            }
+            0 => None,
+            rc => {
+                unreachable!("BoringSSL should never return {rc} when calling dtlsv1_get_timeout")
+            }
+        }
+    }
+}