///|
/// The StartTLS extended operation OID (RFC 4511 4.14, RFC 2830).
pub const STARTTLS_OID : String = "1.3.6.1.4.1.1466.20037"

///|
pub fn[T] Session::is_tls_active(self : Session[T]) -> Bool {
  self.tls_active
}

///|
/// Issue the StartTLS extended operation (RFC 2830). On success the session
/// is marked as having a TLS-protected channel so that `require_tls`
/// configurations allow subsequent binds.
///
/// Note: this method performs the protocol negotiation; installing a real
/// TLS transport on top of an existing socket is the responsibility of the
/// native transport adapter (`hbYlj/moonldap/socket`).
pub async fn[T : LdapTransport] Session::start_tls(
  self : Session[T],
) -> Result[ExtendedResponse, LdapError] {
  let message = match
    self.round_trip(ExtendedRequest(ExtendedRequest::new(STARTTLS_OID, None))) {
    Ok(m) => m
    Err(e) => return Err(e)
  }
  let response = match message.op {
    ExtendedResponse(resp) => resp
    _ => return Err(LdapError::UnexpectedOp(protocol_op_tag(message.op)))
  }
  if response.result.result_code.is_success() {
    self.tls_active = true
  }
  Ok(response)
}

///|
/// Issue StartTLS on the client's session and record the outcome in the
/// diagnostic trace.
pub async fn[T : LdapTransport] LdapClient::start_tls(
  self : LdapClient[T],
) -> Result[ExtendedResponse, LdapError] {
  let response = match self.session.start_tls() {
    Ok(r) => r
    Err(e) => return Err(e)
  }
  self.trace.record_step(
    LdapStep::new(
      "starttls",
      response.result.result_code.to_int(),
      response.result.diagnostic_message,
    ),
  )
  if !response.result.result_code.is_success() {
    self.trace.record_result(response.result)
  }
  Ok(response)
}