use alloc::string::String;
use core::fmt;
use procmacros::BuilderLite;
use super::ScanMethod;
use crate::{
WifiError,
wifi::{AuthenticationMethod, Protocols, Ssid},
};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub struct EapFastConfig {
pub fast_provisioning: u8,
pub fast_max_pac_list_len: u8,
pub fast_pac_format_binary: bool,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub enum TtlsPhase2Method {
Eap,
Mschapv2,
Mschap,
Pap,
Chap,
}
impl TtlsPhase2Method {
pub(crate) fn to_raw(self) -> u32 {
match self {
TtlsPhase2Method::Eap => {
crate::sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_EAP
}
TtlsPhase2Method::Mschapv2 => {
crate::sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_MSCHAPV2
}
TtlsPhase2Method::Mschap => {
crate::sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_MSCHAP
}
TtlsPhase2Method::Pap => {
crate::sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_PAP
}
TtlsPhase2Method::Chap => {
crate::sys::include::esp_eap_ttls_phase2_types_ESP_EAP_TTLS_PHASE2_CHAP
}
}
}
}
type CertificateAndKey = (&'static [u8], &'static [u8], Option<&'static [u8]>);
#[derive(BuilderLite, Clone, PartialEq, Eq, Hash)]
#[instability::unstable]
pub struct EapStationConfig {
#[builder_lite(skip_setter)]
pub(crate) ssid: Ssid,
pub(crate) bssid: Option<[u8; 6]>,
pub(crate) auth_method: AuthenticationMethod,
#[builder_lite(reference)]
pub(crate) identity: Option<String>,
#[builder_lite(reference)]
pub(crate) username: Option<String>,
#[builder_lite(reference)]
pub(crate) password: Option<String>,
#[builder_lite(reference)]
pub(crate) new_password: Option<String>,
#[builder_lite(reference)]
pub(crate) eap_fast_config: Option<EapFastConfig>,
pub(crate) pac_file: Option<&'static [u8]>,
pub(crate) time_check: bool,
pub(crate) ca_cert: Option<&'static [u8]>,
pub(crate) certificate_and_key: Option<CertificateAndKey>,
#[builder_lite(reference)]
pub(crate) ttls_phase2_method: Option<TtlsPhase2Method>,
pub(crate) channel: Option<u8>,
pub(crate) protocols: Protocols,
#[builder_lite(unstable)]
pub(crate) listen_interval: u16,
#[builder_lite(unstable)]
pub(crate) beacon_timeout: u16,
#[builder_lite(unstable)]
pub(crate) failure_retry_cnt: u8,
#[builder_lite(unstable)]
pub(crate) scan_method: ScanMethod,
}
impl EapStationConfig {
#[instability::unstable]
pub fn with_ssid(mut self, ssid: impl Into<Ssid>) -> Self {
self.ssid = ssid.into();
self
}
pub(crate) fn validate(&self) -> Result<(), WifiError> {
if self.ssid.len() > 32 {
return Err(WifiError::InvalidArguments);
}
if self.identity.as_ref().unwrap_or(&String::new()).len() > 128 {
return Err(WifiError::InvalidArguments);
}
if self.username.as_ref().unwrap_or(&String::new()).len() > 128 {
return Err(WifiError::InvalidArguments);
}
if self.password.as_ref().unwrap_or(&String::new()).len() > 64 {
return Err(WifiError::InvalidArguments);
}
if self.new_password.as_ref().unwrap_or(&String::new()).len() > 64 {
return Err(WifiError::InvalidArguments);
}
if !(6..=31).contains(&self.beacon_timeout) {
return Err(WifiError::InvalidArguments);
}
Ok(())
}
}
impl Default for EapStationConfig {
fn default() -> Self {
EapStationConfig {
ssid: Ssid::default(),
bssid: None,
auth_method: AuthenticationMethod::Wpa2Enterprise,
identity: None,
username: None,
password: None,
channel: None,
eap_fast_config: None,
time_check: false,
new_password: None,
pac_file: None,
ca_cert: None,
certificate_and_key: None,
ttls_phase2_method: None,
protocols: Protocols::default(),
listen_interval: 3,
beacon_timeout: 6,
failure_retry_cnt: 1,
scan_method: ScanMethod::Fast,
}
}
}
impl fmt::Debug for EapStationConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EapStationConfig")
.field("ssid", &self.ssid)
.field("bssid", &self.bssid)
.field("auth_method", &self.auth_method)
.field("channel", &self.channel)
.field("identity", &self.identity)
.field("username", &self.username)
.field("password", &"**REDACTED**")
.field("new_password", &"**REDACTED**")
.field("eap_fast_config", &self.eap_fast_config)
.field("time_check", &self.time_check)
.field("pac_file set", &self.pac_file.is_some())
.field("ca_cert set", &self.ca_cert.is_some())
.field("certificate_and_key set", &"**REDACTED**")
.field("ttls_phase2_method", &self.ttls_phase2_method)
.field("protocols", &self.protocols)
.field("listen_interval", &self.listen_interval)
.field("beacon_timeout", &self.beacon_timeout)
.field("failure_retry_cnt", &self.failure_retry_cnt)
.field("scan_method", &self.scan_method)
.finish()
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for EapStationConfig {
fn format(&self, fmt: defmt::Formatter<'_>) {
defmt::write!(
fmt,
"EapStationConfig {{\
ssid: {}, \
bssid: {:?}, \
auth_method: {:?}, \
channel: {:?}, \
identity: {:?}, \
username: {:?}, \
password: **REDACTED**, \
new_password: **REDACTED**, \
eap_fast_config: {:?}, \
time_check: {}, \
pac_file: {}, \
ca_cert: {}, \
certificate_and_key: **REDACTED**, \
ttls_phase2_method: {:?}, \
protocols: {}, \
listen_interval: {}, \
beacon_timeout: {}, \
failure_retry_cnt: {}, \
scan_method: {},
}}",
self.ssid.as_str(),
self.bssid,
self.auth_method,
self.channel,
&self.identity.as_ref().map_or("", |v| v.as_str()),
&self.username.as_ref().map_or("", |v| v.as_str()),
self.eap_fast_config,
self.time_check,
self.pac_file,
self.ca_cert,
self.ttls_phase2_method,
self.protocols,
self.listen_interval,
self.beacon_timeout,
self.failure_retry_cnt,
self.scan_method
)
}
}