// Copyright 2026 The BoringSSL Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! TLS Connection lifecycle controls

use alloc::boxed::Box;
use core::{
    ffi::c_int,
    future::poll_fn,
    ops::{
        Deref,
        DerefMut, //
    },
    ptr::NonNull,
    task::Poll, //
};

use crate::{
    HandshakeCompleteMethods,
    Methods,
    abort_on_panic,
    alerts::AlertDescription,
    connection::{
        Client,
        Server,
        TlsConnection,
        TlsConnectionBuilder,
        methods::HasTlsConnectionMethod, //
    },
    context::{
        HasShutdown,
        SupportedMode,
        TlsMode, //
    },
    credentials::TlsCredential,
    errors::{
        Error,
        TlsErrorReason,
        TlsRetryReason, //
    }, //
};

/// # Connection shutdown
impl<R, M> TlsConnection<R, M> {
    /// Set whether shutting down this connection sends out a `close_notify` alert.
    pub fn set_quiet_shutdown(&mut self, quiet: bool) -> &mut Self {
        unsafe {
            // Safety: the validity of the handle `self.0` is witnessed by `self`.
            bssl_sys::SSL_set_quiet_shutdown(self.ptr(), if quiet { 1 } else { 0 });
        }
        self
    }

    /// Check whether shutting down this connection sends out a `close_notify` alert.
    pub fn get_quiet_shutdown(&self) -> bool {
        let rc = unsafe {
            // Safety: the validity of the handle `self.0` is witnessed by `self`.
            bssl_sys::SSL_get_quiet_shutdown(self.ptr())
        };
        rc == 1
    }
}

/// # Connection initialisation state
///
/// There are methods and accessors that become available only when the connection is in the right
/// state.
///
/// Please refer to [`EstablishedTlsConnection`] and [`TlsConnectionInHandshake`] for allowed
/// operations.
impl<R, M> TlsConnection<R, M> {
    /// Access handshake-related options if the connection is in handshake mode.
    pub fn in_handshake<'a>(&'a mut self) -> Option<TlsConnectionInHandshake<'a, R, M>> {
        if self.is_in_handshake() {
            Some(TlsConnectionInHandshake(self))
        } else {
            None
        }
    }

    /// Access handshake-related options if a handshake is completed and
    /// the connection is initialised.
    pub fn established<'a>(&'a mut self) -> Option<EstablishedTlsConnection<'a, R, M>> {
        (!self.is_in_handshake()).then_some(EstablishedTlsConnection(self))
    }
}

/// # Alerts
impl<R, M> TlsConnection<R, M>
where
    M: HasTlsConnectionMethod,
{
    fn translate_lifecycle_result(&mut self, rc: c_int) -> Result<Option<TlsRetryReason>, Error> {
        let code = unsafe {
            // Safety: inspecting the last error on an existing valid connection.
            bssl_sys::SSL_get_error(self.ptr(), rc)
        };
        match code {
            // Handshake or alert transmission completed cleanly; here it returns `Ok(None)` to indicate
            // that no further progress or retry is required.
            bssl_sys::SSL_ERROR_NONE => Ok(None),

            // TODO(crbug.com/42290000): This should be handled within the library.
            // A `close_notify` received mid-handshake or during fatal alert sending means the peer closed
            // the connection before completing the handshake, which is a terminal error.
            bssl_sys::SSL_ERROR_ZERO_RETURN => {
                Err(Error::TlsReason(TlsErrorReason::Sslv3AlertCloseNotify))
            }

            // The handshake paused due to pending network I/O or an asynchronous callback such as private
            // key operations.
            // Returning `Ok(Some(reason))` preserves the exact suspension reason so the caller or async
            // reactor can resolve it before driving the handshake again.
            _ if let Ok(reason) = TlsRetryReason::try_from(code) => Ok(Some(reason)),
            _ => Err(self.extract_tls_error(code)),
        }
    }

    /// Send fatal alert.
    ///
    /// This would usually lead to termination of the connection.
    pub fn send_fatal_alert(
        &mut self,
        alert: AlertDescription,
    ) -> Result<Option<TlsRetryReason>, Error> {
        let rc = unsafe {
            // Safety: `self.0` is still a valid handle and `alert` is valid by construction.
            bssl_sys::SSL_send_fatal_alert(self.ptr(), alert as u8)
        };
        self.translate_lifecycle_result(rc)
    }

    /// Send fatal alert asynchronously.
    pub fn async_send_fatal_alert<'a>(
        &'a mut self,
        alert: AlertDescription,
    ) -> impl 'a + Send + Future<Output = Result<(), Error>> {
        poll_fn(move |cx| {
            self.set_waker(cx.waker());
            match self.send_fatal_alert(alert) {
                Ok(Some(TlsRetryReason::WantRead | TlsRetryReason::WantWrite)) => Poll::Pending,
                Ok(None) => Poll::Ready(Ok(())),
                Ok(Some(reason)) => unreachable!("unexpected retry reason {reason:?}"),
                Err(e) => Poll::Ready(Err(e)),
            }
        })
    }
}

impl<R> TlsConnection<R, TlsMode> {
    /// Inspect if the connection is suspended for which reason, after invocation of I/O methods.
    pub fn take_pending_reason(&mut self) -> Option<TlsRetryReason> {
        self.get_connection_methods().take_pending_reason()
    }
}

/// A handle to the connection that is valid only during handshake.
// NOTE(@xfding): this type is strictly for configuration of the connection during the handshake,
// and no methods should be allowed to drive the TLS state machine.
#[repr(transparent)]
pub struct TlsConnectionInHandshake<'a, R, M>(pub(crate) &'a mut TlsConnection<R, M>);

impl<R, M> TlsConnectionInHandshake<'_, R, M> {
    pub(crate) fn ptr(&self) -> *mut bssl_sys::SSL {
        self.0.ptr()
    }
}

/// # Handshake
impl<R, M> TlsConnection<R, M>
where
    M: SupportedMode,
{
    /// Drive the handshake.
    ///
    /// Call this method after the initial [`Self::accept`] or [`Self::connect`],
    /// should the handshake be suspended.
    ///
    /// This method returns `Ok(None)` to signal handshake completion;
    /// otherwise, `Ok(Some(reason))` is returned and the suspension `reason` must be resolved first
    /// before this method can make progress again.
    pub fn do_handshake(&mut self) -> Result<Option<TlsRetryReason>, Error> {
        let rc = unsafe {
            // Safety: driving the handshake on a valid connection handle.
            bssl_sys::SSL_do_handshake(self.ptr())
        };
        self.translate_lifecycle_result(rc)
    }
}

impl<M> TlsConnection<Server, M>
where
    M: SupportedMode,
{
    /// Accept a connection by responding to `ClientHello` with `ServerHello`.
    ///
    /// This method returns `Ok(None)` to signal handshake completion;
    /// otherwise, given `Ok(Some(reason))` the suspension `reason` must be resolved first
    /// before calling [`Self::do_handshake`] can make progress again.
    pub fn accept(&mut self) -> Result<Option<TlsRetryReason>, Error> {
        self.do_handshake()
    }
}

impl<M> TlsConnection<Client, M>
where
    M: SupportedMode,
{
    /// Initiate a connection by sending a `ClientHello`.
    ///
    /// This method returns `Ok(None)` to signal handshake completion;
    /// otherwise, given `Ok(Some(reason))` the suspension `reason` must be resolved first
    /// before calling [`Self::do_handshake`] can make progress again.
    pub fn connect(&mut self) -> Result<Option<TlsRetryReason>, Error> {
        self.do_handshake()
    }
}

/// A handle to the connection that is valid only after initialization, or in other words after
/// handshake.
#[repr(transparent)]
pub struct EstablishedTlsConnection<'a, R, M = TlsMode>(&'a mut TlsConnection<R, M>);

impl<R, M> Deref for EstablishedTlsConnection<'_, R, M> {
    type Target = TlsConnection<R, M>;
    fn deref(&self) -> &Self::Target {
        &*self.0
    }
}

impl<R, M> DerefMut for EstablishedTlsConnection<'_, R, M> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut *self.0
    }
}

impl<R, M> EstablishedTlsConnection<'_, R, M>
where
    M: HasTlsConnectionMethod + HasShutdown,
{
    /// Perform shutdown on the write end.
    ///
    /// If the method returns `Ok(Some(reason))`, the shutdown will not progress until I/O makes
    /// progress.
    pub fn sync_shutdown(&mut self) -> Result<Option<TlsRetryReason>, Error> {
        // SSL_shutdown has two stages, sending close_notify and waiting for close_notify.
        // We now believe that only the sending call, aka the first call, is useful.
        // This method only sends close_notify, so it skips calling SSL_shutdown if close_notify has
        // already been sent.
        let rc = unsafe {
            // Safety: we have exclusive access to the connection state.
            bssl_sys::SSL_get_shutdown(self.ptr())
        };
        if rc & bssl_sys::SSL_SENT_SHUTDOWN != 0 {
            return Ok(None);
        }
        let rc = unsafe {
            // Safety: we have exclusive access to the connection state.
            bssl_sys::SSL_shutdown(self.ptr())
        };
        if matches!(rc, 0 | 1) {
            return Ok(None);
        }
        self.translate_lifecycle_result(rc)
    }
}

impl<R, M> TlsConnection<R, M>
where
    M: SupportedMode,
{
    /// Perform asynchronous handshake, until completion or until pending on non-I/O operations.
    ///
    /// The caller needs to ensure that any pending operations during the handshake are resolved,
    /// before polling [`Self::async_handshake`] again.
    pub fn async_handshake(
        &mut self,
    ) -> impl Send + Future<Output = Result<Option<TlsRetryReason>, Error>> + '_ {
        poll_fn(move |cx| {
            self.set_waker(cx.waker());
            match self.do_handshake() {
                Ok(Some(TlsRetryReason::WantRead | TlsRetryReason::WantWrite)) => Poll::Pending,
                Ok(Some(reason)) => Poll::Ready(Ok(Some(reason))),
                Ok(None) => Poll::Ready(Ok(None)),
                Err(e) => Poll::Ready(Err(e)),
            }
        })
    }

    /// Perform asynchronous handshake, until completion, knowing that all possible pending reasons
    /// will resolve themselves.
    ///
    /// The caller needs to ensure that any pending operations due to asynchronous operations such as
    /// certificate verification and private key operations will eventually resolve and wake up
    /// the handshake task.
    /// Otherwise the handshake task will never complete.
    pub fn async_nonstop_handshake(
        &mut self,
    ) -> impl Send + Future<Output = Result<(), Error>> + '_ {
        poll_fn(move |cx| {
            self.set_waker(cx.waker());
            match self.do_handshake() {
                Ok(Some(_)) => Poll::Pending,
                Ok(None) => Poll::Ready(Ok(())),
                Err(e) => Poll::Ready(Err(e)),
            }
        })
    }
}

bssl_macros::bssl_enum! {
    enum InfoCallbackConnectionState : i32 {
        ReadAlert = bssl_sys::SSL_CB_READ_ALERT as i32,
        WriteAlert = bssl_sys::SSL_CB_WRITE_ALERT as i32,
        HandshakeStart = bssl_sys::SSL_CB_HANDSHAKE_START as i32,
        HandshakeDone = bssl_sys::SSL_CB_HANDSHAKE_DONE as i32,
    }
}

/// A callback that allows you to inspect the handshake information when the handshake concludes
/// successfully.
pub trait HandshakeComplete: Send {
    /// The callback to be called when handshake is complete with success.
    fn handshake_complete(&mut self, hs: &HandshakeInfo);
}

/// A handle to extract handshake information, such as credential.
pub struct HandshakeInfo(NonNull<bssl_sys::SSL>);

impl HandshakeInfo {
    /// Return the selected credential for the connection.
    pub fn get_selected_credential(&self) -> Option<TlsCredential> {
        let cred = unsafe {
            // Safety: by BoringSSL invariant, `self.0` is still a valid connection handle.
            bssl_sys::SSL_get0_selected_credential(self.0.as_ptr())
        };
        NonNull::new(cred as *mut _).map(TlsCredential::from_raw_and_upref)
    }
}

unsafe extern "C" fn info_callback<M: Methods + HandshakeCompleteMethods>(
    ssl: *const bssl_sys::SSL,
    ty: c_int,
    _: c_int,
) {
    // Safety: the const-to-mut cast is safe; we only mutate our own method table, not SSL.
    let Some(ssl) = NonNull::new(ssl as *mut _) else {
        return;
    };
    let Some(state) = InfoCallbackConnectionState::try_from(ty).ok() else {
        return;
    };
    abort_on_panic(move || {
        match state {
            InfoCallbackConnectionState::HandshakeDone => {
                let Some(mut callback) = (unsafe {
                    // Safety: `ssl` is a valid handle passed in from BoringSSL.
                    M::from_ssl(ssl.as_ptr())
                })
                .and_then(|methods| methods.handshake_complete_methods()) else {
                    return;
                };
                callback.handshake_complete(&HandshakeInfo(ssl));
            }
            InfoCallbackConnectionState::ReadAlert
            | InfoCallbackConnectionState::WriteAlert
            | InfoCallbackConnectionState::HandshakeStart => {}
        }
    });
}

/// # Handshake-complete callback
impl<R, M> TlsConnectionBuilder<R, M>
where
    M: HasTlsConnectionMethod,
{
    /// Set a callback to be called when the handshake completes successfully.
    ///
    /// The callback receives a [`HandshakeInfo`] handle that can be used to
    /// inspect the result of the handshake, such as the selected credential.
    pub fn with_handshake_complete_callback(
        &mut self,
        callback: impl HandshakeComplete + 'static,
    ) -> &mut Self {
        self.as_in_handshake()
            .set_handshake_complete_callback(callback);
        self
    }
}

/// # Handshake completion notification callback
impl<R, M> TlsConnectionInHandshake<'_, R, M>
where
    M: HasTlsConnectionMethod,
{
    /// Set a callback to be called when the handshake completes successfully.
    pub fn set_handshake_complete_callback(
        &mut self,
        callback: impl HandshakeComplete + 'static,
    ) -> &mut Self {
        unsafe {
            // Safety: we only install our own callback function.
            bssl_sys::SSL_set_info_callback(
                self.ptr(),
                Some(info_callback::<super::methods::RustConnectionMethods<M>>),
            );
        }
        self.0.get_connection_methods().handshake_complete = Some(Box::new(callback));
        self
    }
}
