wlan_sme/
lib.rs

1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Turn on additional lints that could lead to unexpected crashes in production code
6#![warn(clippy::indexing_slicing)]
7#![cfg_attr(test, allow(clippy::indexing_slicing))]
8#![warn(clippy::unwrap_used)]
9#![cfg_attr(test, allow(clippy::unwrap_used))]
10#![warn(clippy::expect_used)]
11#![cfg_attr(test, allow(clippy::expect_used))]
12#![warn(clippy::unreachable)]
13#![cfg_attr(test, allow(clippy::unreachable))]
14#![warn(clippy::unimplemented)]
15#![cfg_attr(test, allow(clippy::unimplemented))]
16
17pub mod ap;
18pub mod client;
19pub mod serve;
20#[cfg(test)]
21pub mod test_utils;
22
23use fidl_fuchsia_wlan_mlme::{self as fidl_mlme, MlmeEvent};
24use futures::channel::mpsc;
25use thiserror::Error;
26use wlan_common::sink::UnboundedSink;
27use wlan_common::timer;
28use {fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_stats as fidl_stats};
29
30#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
31pub struct Config {
32    pub wep_supported: bool,
33    pub wpa1_supported: bool,
34}
35
36impl Config {
37    pub fn with_wep(mut self) -> Self {
38        self.wep_supported = true;
39        self
40    }
41
42    pub fn with_wpa1(mut self) -> Self {
43        self.wpa1_supported = true;
44        self
45    }
46}
47
48#[derive(Debug)]
49pub enum MlmeRequest {
50    Scan(fidl_mlme::ScanRequest),
51    AuthResponse(fidl_mlme::AuthenticateResponse),
52    AssocResponse(fidl_mlme::AssociateResponse),
53    Connect(fidl_mlme::ConnectRequest),
54    Reconnect(fidl_mlme::ReconnectRequest),
55    Roam(fidl_mlme::RoamRequest),
56    Deauthenticate(fidl_mlme::DeauthenticateRequest),
57    Disassociate(fidl_mlme::DisassociateRequest),
58    Eapol(fidl_mlme::EapolRequest),
59    SetKeys(fidl_mlme::SetKeysRequest),
60    SetCtrlPort(fidl_mlme::SetControlledPortRequest),
61    Start(fidl_mlme::StartRequest),
62    Stop(fidl_mlme::StopRequest),
63    GetIfaceStats(responder::Responder<fidl_mlme::GetIfaceStatsResponse>),
64    GetIfaceHistogramStats(responder::Responder<fidl_mlme::GetIfaceHistogramStatsResponse>),
65    ListMinstrelPeers(responder::Responder<fidl_mlme::MinstrelListResponse>),
66    GetMinstrelStats(
67        fidl_mlme::MinstrelStatsRequest,
68        responder::Responder<fidl_mlme::MinstrelStatsResponse>,
69    ),
70    SaeHandshakeResp(fidl_mlme::SaeHandshakeResponse),
71    SaeFrameTx(fidl_mlme::SaeFrame),
72    WmmStatusReq,
73    FinalizeAssociation(fidl_mlme::NegotiatedCapabilities),
74    QueryDeviceInfo(responder::Responder<fidl_mlme::DeviceInfo>),
75    QueryDiscoverySupport(responder::Responder<fidl_common::DiscoverySupport>),
76    QueryMacSublayerSupport(responder::Responder<fidl_common::MacSublayerSupport>),
77    QuerySecuritySupport(responder::Responder<fidl_common::SecuritySupport>),
78    QuerySpectrumManagementSupport(responder::Responder<fidl_common::SpectrumManagementSupport>),
79    QueryTelemetrySupport(responder::Responder<Result<fidl_stats::TelemetrySupport, i32>>),
80}
81
82impl MlmeRequest {
83    pub fn name(&self) -> &'static str {
84        match self {
85            Self::Scan(_) => "Scan",
86            Self::AuthResponse(_) => "AuthResponse",
87            Self::AssocResponse(_) => "AssocResponse",
88            Self::Connect(_) => "Connect",
89            Self::Reconnect(_) => "Reconnect",
90            Self::Roam(_) => "Roam",
91            Self::Deauthenticate(_) => "Deauthenticate",
92            Self::Disassociate(_) => "Disassociate",
93            Self::Eapol(_) => "Eapol",
94            Self::SetKeys(_) => "SetKeys",
95            Self::SetCtrlPort(_) => "SetCtrlPort",
96            Self::Start(_) => "Start",
97            Self::Stop(_) => "Stop",
98            Self::GetIfaceStats(_) => "GetIfaceStats",
99            Self::GetIfaceHistogramStats(_) => "GetIfaceHistogramStats",
100            Self::ListMinstrelPeers(_) => "ListMinstrelPeers",
101            Self::GetMinstrelStats(_, _) => "GetMinstrelStats",
102            Self::SaeHandshakeResp(_) => "SaeHandshakeResp",
103            Self::SaeFrameTx(_) => "SaeFrameTx",
104            Self::WmmStatusReq => "WmmStatusReq",
105            Self::FinalizeAssociation(_) => "FinalizeAssociation",
106            Self::QueryDeviceInfo(_) => "QueryDeviceInfo",
107            Self::QueryDiscoverySupport(_) => "QueryDiscoverySupport",
108            Self::QueryMacSublayerSupport(_) => "QueryMacSublayerSupport",
109            Self::QuerySecuritySupport(_) => "QuerySecuritySupport",
110            Self::QuerySpectrumManagementSupport(_) => "QuerySpectrumManagementSupport",
111            Self::QueryTelemetrySupport(_) => "QueryTelemetrySupport",
112        }
113    }
114}
115
116pub trait Station {
117    type Event;
118
119    fn on_mlme_event(&mut self, event: fidl_mlme::MlmeEvent);
120    fn on_timeout(&mut self, timed_event: timer::Event<Self::Event>);
121}
122
123pub type MlmeStream = mpsc::UnboundedReceiver<MlmeRequest>;
124pub type MlmeEventStream = mpsc::UnboundedReceiver<MlmeEvent>;
125pub type MlmeSink = UnboundedSink<MlmeRequest>;
126pub type MlmeEventSink = UnboundedSink<MlmeEvent>;
127
128pub mod responder {
129    use futures::channel::oneshot;
130
131    #[derive(Debug)]
132    pub struct Responder<T>(oneshot::Sender<T>);
133
134    impl<T> Responder<T> {
135        pub fn new() -> (Self, oneshot::Receiver<T>) {
136            let (sender, receiver) = oneshot::channel();
137            (Responder(sender), receiver)
138        }
139
140        pub fn respond(self, result: T) {
141            #[allow(
142                clippy::unnecessary_lazy_evaluations,
143                reason = "mass allow for https://fxbug.dev/381896734"
144            )]
145            self.0.send(result).unwrap_or_else(|_| ());
146        }
147    }
148}
149
150/// Safely log MlmeEvents without printing private information.
151fn mlme_event_name(event: &MlmeEvent) -> &str {
152    match event {
153        MlmeEvent::OnScanResult { .. } => "OnScanResult",
154        MlmeEvent::OnScanEnd { .. } => "OnScanEnd",
155        MlmeEvent::ConnectConf { .. } => "ConnectConf",
156        MlmeEvent::RoamConf { .. } => "RoamConf",
157        MlmeEvent::RoamStartInd { .. } => "RoamStartInd",
158        MlmeEvent::RoamResultInd { .. } => "RoamResultInd",
159        MlmeEvent::AuthenticateInd { .. } => "AuthenticateInd",
160        MlmeEvent::DeauthenticateConf { .. } => "DeauthenticateConf",
161        MlmeEvent::DeauthenticateInd { .. } => "DeauthenticateInd",
162        MlmeEvent::AssociateInd { .. } => "AssociateInd",
163        MlmeEvent::DisassociateConf { .. } => "DisassociateConf",
164        MlmeEvent::DisassociateInd { .. } => "DisassociateInd",
165        MlmeEvent::SetKeysConf { .. } => "SetKeysConf",
166        MlmeEvent::StartConf { .. } => "StartConf",
167        MlmeEvent::StopConf { .. } => "StopConf",
168        MlmeEvent::EapolConf { .. } => "EapolConf",
169        MlmeEvent::SignalReport { .. } => "SignalReport",
170        MlmeEvent::EapolInd { .. } => "EapolInd",
171        MlmeEvent::RelayCapturedFrame { .. } => "RelayCapturedFrame",
172        MlmeEvent::OnChannelSwitched { .. } => "OnChannelSwitched",
173        MlmeEvent::OnPmkAvailable { .. } => "OnPmkAvailable",
174        MlmeEvent::OnSaeHandshakeInd { .. } => "OnSaeHandshakeInd",
175        MlmeEvent::OnSaeFrameRx { .. } => "OnSaeFrameRx",
176        MlmeEvent::OnWmmStatusResp { .. } => "OnWmmStatusResp",
177    }
178}
179
180#[derive(Debug, Error)]
181pub enum Error {
182    #[error("scan end while not scanning")]
183    ScanEndNotScanning,
184    #[error("scan end with wrong txn id")]
185    ScanEndWrongTxnId,
186    #[error("scan result while not scanning")]
187    ScanResultNotScanning,
188    #[error("scan result with wrong txn id")]
189    ScanResultWrongTxnId,
190}