async fn starting_state(
    proxy: fidl_sme::ApSmeProxy,
    mut next_req: NextReqFut,
    mut req: ApConfig,
    remaining_retries: u16,
    responder: Option<oneshot::Sender<()>>,
    sender: ApListenerMessageSender,
) -> Result<State, ExitReason> {
    // Create an initial AP state
    let mut state =
        ApStateUpdate::new(req.id.clone(), types::OperatingState::Starting, req.mode, req.band);

    // Apply default PHY, CBW, and channel settings.
    let _ = req.radio_config.phy.get_or_insert(DEFAULT_PHY);
    let _ = req.radio_config.cbw.get_or_insert(DEFAULT_CBW);
    let _ = req.radio_config.primary_chan.get_or_insert(DEFAULT_CHANNEL);

    // Send a stop request to ensure that the AP begins in an unstarting state.
    let stop_result = match proxy.stop().await {
        Ok(fidl_sme::StopApResultCode::Success) => Ok(()),
        Ok(code) => Err(format_err!("Unexpected StopApResultCode: {:?}", code)),
        Err(e) => Err(format_err!("Failed to send a stop command to wlanstack: {}", e)),
    };

    // If the stop operation failed, send a failure update and exit the state machine.
    if stop_result.is_err() {
        let mut failed_state = state.clone();
        failed_state.state = types::OperatingState::Failed;
        send_state_update(&sender, failed_state)
            .map_err(|e| ExitReason(Err(anyhow::Error::from(e))))?;

        stop_result.map_err(|e| ExitReason(Err(e)))?;
    }

    // If the stop operation was successful, update all listeners that the AP is stopped.
    send_ap_stopped_update(&sender).map_err(|e| ExitReason(Err(anyhow::Error::from(e))))?;

    // Update all listeners that a new AP is starting if this is the first attempt to start the AP.
    if remaining_retries == AP_START_MAX_RETRIES {
        send_state_update(&sender, state.clone())
            .map_err(|e| ExitReason(Err(anyhow::Error::from(e))))?;
    }

    let mut ap_config = fidl_sme::ApConfig::from(req.clone());
    let start_result = match proxy.start(&mut ap_config).await {
        Ok(fidl_sme::StartApResultCode::Success) => Ok(()),
        Ok(code) => {
            // For any non-Success response, attempt to retry the start operation.  A successful
            // stop operation followed by an unsuccessful start operation likely indicates that the
            // PHY associated with this AP interface is busy scanning.  A future attempt to start
            // may succeed.
            if remaining_retries > 0 {
                let retry_timer = fasync::Timer::new(AP_START_RETRY_INTERVAL.seconds().after_now());

                // To ensure that the state machine remains responsive, process any incoming
                // requests while waiting for the timer to expire.
                select! {
                    () = retry_timer.fuse() => {
                        return transition_to_starting(
                            proxy,
                            next_req,
                            req,
                            remaining_retries - 1,
                            responder,
                            sender,
                        );
                    },
                    (req, req_stream) = next_req => {
                        // If a new request comes in, clear out the current AP state.
                        send_ap_stopped_update(&sender)
                            .map_err(|e| ExitReason(Err(anyhow::Error::from(e))))?;
                        return perform_manual_request(proxy, req, req_stream, sender);
                    }
                }
            }

            // Return an error if all retries have been exhausted.
            Err(format_err!("Failed to start AP: {:?}", code))
        }
        Err(e) => {
            // If communicating with the SME fails, further attempts to start the AP are guaranteed
            // to fail.
            Err(format_err!("Failed to send a start command to wlanstack: {}", e))
        }
    };

    start_result.map_err(|e| {
        // Send a failure notification.
        state.state = types::OperatingState::Failed;
        let _ = send_state_update(&sender, state.clone());
        ExitReason(Err(e))
    })?;

    match responder {
        Some(responder) => responder.send(()).unwrap_or_else(|_| ()),
        None => {}
    }

    state.state = types::OperatingState::Active;
    send_state_update(&sender, state.clone())
        .map_err(|e| ExitReason(Err(anyhow::Error::from(e))))?;
    return Ok(started_state(proxy, next_req, req, state, sender).into_state());
}
/// In the starting state, a request to ApSmeProxy::Start is made.  If the start request fails,
/// the state machine exits with an error.  On success, the state machine transitions into the
/// started state to monitor the SME.
///
/// The starting state can be entered in the following ways.
/// 1. When the state machine is stopped and it is asked to start an AP.
/// 2. When the state machine is started and the AP fails.
/// 3. When retrying a failed start attempt.
///
/// The starting state can be exited in the following ways.
/// 1. If stopping the AP SME fails, exit the state machine.  The stop operation should be a very
///    brief interaction with the firmware.  Failure can only occur if the SME layer times out the
///    operation or the driver crashes.  Either scenario should be considered fatal.
/// 2. If the start request fails because the AP state machine cannot communicate with the SME,
///    the state machine will exit with an error.
/// 3. If the start request fails due to an error reported by the SME, it's possible that a client
///    interface associated with the same PHY is scanning.  In this case, allow the operation to be
///    retried by transitioning back through the starting state.  Once the retries are exhausted,
///    exit the state machine with an error.
/// 4. When the start request finishes, transition into the started state.
In the starting state, a request to ApSmeProxy::Start is made.  If the start request fails,
the state machine exits with an error.  On success, the state machine transitions into the
started state to monitor the SME.

The starting state can be entered in the following ways.
1. When the state machine is stopped and it is asked to start an AP.
2. When the state machine is started and the AP fails.
3. When retrying a failed start attempt.

The starting state can be exited in the following ways.
1. If stopping the AP SME fails, exit the state machine.  The stop operation should be a very
brief interaction with the firmware.  Failure can only occur if the SME layer times out the
operation or the driver crashes.  Either scenario should be considered fatal.
2. If the start request fails because the AP state machine cannot communicate with the SME,
the state machine will exit with an error.
3. If the start request fails due to an error reported by the SME, it's possible that a client
interface associated with the same PHY is scanning.  In this case, allow the operation to be
retried by transitioning back through the starting state.  Once the retries are exhausted,
exit the state machine with an error.
4. When the start request finishes, transition into the started state.
In the starting state a request to ApSmeProxy :: Start is made . If the start request fails the state machine exits with an error . On success the state machine transitions into the started state to monitor the SME . The starting state can be entered in the following ways . 1 . When the state machine is stopped and it is asked to start an AP . 2 . When the state machine is started and the AP fails . 3 . When retrying a failed start attempt . The starting state can be exited in the following ways . 1 . If stopping the AP SME fails exit the state machine . The stop operation should be a very brief interaction with the firmware . Failure can only occur if the SME layer times out the operation or the driver crashes . Either scenario should be considered fatal . 2 . If the start request fails because the AP state machine cannot communicate with the SME the state machine will exit with an error . 3 . If the start request fails due to an error reported by the SME it ' s possible that a client interface associated with the same PHY is scanning . In this case allow the operation to be retried by transitioning back through the starting state . Once the retries are exhausted exit the state machine with an error . 4 . When the start request finishes transition into the started state .
async fn starting_state(
    proxy: fidl_sme::ApSmeProxy,
    mut next_req: NextReqFut,
    mut req: ApConfig,
    remaining_retries: u16,
    responder: Option<oneshot::Sender<()>>,
    sender: ApListenerMessageSender,
) -> Result<State, ExitReason> {
    // Create an initial AP state
    let mut state =
        ApStateUpdate::new(req.id.clone(), types::OperatingState::Starting, req.mode, req.band);
    // Apply default PHY, CBW, and channel settings.
    let _ = req.radio_config.phy.get_or_insert(DEFAULT_PHY);
    let _ = req.radio_config.cbw.get_or_insert(DEFAULT_CBW);
    let _ = req.radio_config.primary_chan.get_or_insert(DEFAULT_CHANNEL);
    // Send a stop request to ensure that the AP begins in an unstarting state.
    let stop_result = match proxy.stop().await {
        Ok(fidl_sme::StopApResultCode::Success) => Ok(()),
        Ok(code) => Err(format_err!("Unexpected StopApResultCode: {:?}", code)),
        Err(e) => Err(format_err!("Failed to send a stop command to wlanstack: {}", e)),
    };
    // If the stop operation failed, send a failure update and exit the state machine.
    if stop_result.is_err() {
        let mut failed_state = state.clone();
        failed_state.state = types::OperatingState::Failed;
        send_state_update(&sender, failed_state)
            .map_err(|e| ExitReason(Err(anyhow::Error::from(e))))?;
        stop_result.map_err(|e| ExitReason(Err(e)))?;
    }
    // If the stop operation was successful, update all listeners that the AP is stopped.
    send_ap_stopped_update(&sender).map_err(|e| ExitReason(Err(anyhow::Error::from(e))))?;
    // Update all listeners that a new AP is starting if this is the first attempt to start the AP.
    if remaining_retries == AP_START_MAX_RETRIES {
        send_state_update(&sender, state.clone())
            .map_err(|e| ExitReason(Err(anyhow::Error::from(e))))?;
    }
    let mut ap_config = fidl_sme::ApConfig::from(req.clone());
    let start_result = match proxy.start(&mut ap_config).await {
        Ok(fidl_sme::StartApResultCode::Success) => Ok(()),
        Ok(code) => {
            // For any non-Success response, attempt to retry the start operation.  A successful
            // stop operation followed by an unsuccessful start operation likely indicates that the
            // PHY associated with this AP interface is busy scanning.  A future attempt to start
            // may succeed.
            if remaining_retries > 0 {
                let retry_timer = fasync::Timer::new(AP_START_RETRY_INTERVAL.seconds().after_now());
                // To ensure that the state machine remains responsive, process any incoming
                // requests while waiting for the timer to expire.
                select! {
                    () = retry_timer.fuse() => {
                        return transition_to_starting(
                            proxy,
                            next_req,
                            req,
                            remaining_retries - 1,
                            responder,
                            sender,
                        );
                    },
                    (req, req_stream) = next_req => {
                        // If a new request comes in, clear out the current AP state.
                        send_ap_stopped_update(&sender)
                            .map_err(|e| ExitReason(Err(anyhow::Error::from(e))))?;
                        return perform_manual_request(proxy, req, req_stream, sender);
                    }
                }
            }
            // Return an error if all retries have been exhausted.
            Err(format_err!("Failed to start AP: {:?}", code))
        }
        Err(e) => {
            // If communicating with the SME fails, further attempts to start the AP are guaranteed
            // to fail.
            Err(format_err!("Failed to send a start command to wlanstack: {}", e))
        }
    };
    start_result.map_err(|e| {
        // Send a failure notification.
        state.state = types::OperatingState::Failed;
        let _ = send_state_update(&sender, state.clone());
        ExitReason(Err(e))
    })?;
    match responder {
        Some(responder) => responder.send(()).unwrap_or_else(|_| ()),
        None => {}
    }
    state.state = types::OperatingState::Active;
    send_state_update(&sender, state.clone())
        .map_err(|e| ExitReason(Err(anyhow::Error::from(e))))?;
    return Ok(started_state(proxy, next_req, req, state, sender).into_state());
}
async fn starting_state ( proxy : fidl_sme :: ApSmeProxy , mut next_req : NextReqFut , mut req : ApConfig , remaining_retries : u16 , responder : Option < oneshot :: Sender < ( ) > > , sender : ApListenerMessageSender , ) -> Result < State , ExitReason > { // Create an initial AP state let mut state = ApStateUpdate :: new ( req . id . clone ( ) , types :: OperatingState :: Starting , req . mode , req . band ) ; // Apply default PHY, CBW, and channel settings. let _ = req . radio_config . phy . get_or_insert ( DEFAULT_PHY ) ; let _ = req . radio_config . cbw . get_or_insert ( DEFAULT_CBW ) ; let _ = req . radio_config . primary_chan . get_or_insert ( DEFAULT_CHANNEL ) ; // Send a stop request to ensure that the AP begins in an unstarting state. let stop_result = match proxy . stop ( ) . await { Ok ( fidl_sme :: StopApResultCode :: Success ) => Ok ( ( ) ) , Ok ( code ) => Err ( format_err ! ( " " code ) ) , Err ( e ) => Err ( format_err ! ( " " e ) ) , } ; // If the stop operation failed, send a failure update and exit the state machine. if stop_result . is_err ( ) { let mut failed_state = state . clone ( ) ; failed_state . state = types :: OperatingState :: Failed ; send_state_update ( & sender , failed_state ) . map_err ( | e | ExitReason ( Err ( anyhow :: Error :: from ( e ) ) ) ) ? ; stop_result . map_err ( | e | ExitReason ( Err ( e ) ) ) ? ; } // If the stop operation was successful, update all listeners that the AP is stopped. send_ap_stopped_update ( & sender ) . map_err ( | e | ExitReason ( Err ( anyhow :: Error :: from ( e ) ) ) ) ? ; // Update all listeners that a new AP is starting if this is the first attempt to start the AP. if remaining_retries == AP_START_MAX_RETRIES { send_state_update ( & sender , state . clone ( ) ) . map_err ( | e | ExitReason ( Err ( anyhow :: Error :: from ( e ) ) ) ) ? ; } let mut ap_config = fidl_sme :: ApConfig :: from ( req . clone ( ) ) ; let start_result = match proxy . start ( & mut ap_config ) . await { Ok ( fidl_sme :: StartApResultCode :: Success ) => Ok ( ( ) ) , Ok ( code ) => { // For any non-Success response, attempt to retry the start operation.  A successful // stop operation followed by an unsuccessful start operation likely indicates that the // PHY associated with this AP interface is busy scanning.  A future attempt to start // may succeed. if remaining_retries > 0 { let retry_timer = fasync :: Timer :: new ( AP_START_RETRY_INTERVAL . seconds ( ) . after_now ( ) ) ; // To ensure that the state machine remains responsive, process any incoming // requests while waiting for the timer to expire. select ! { ( ) retry_timer fuse ( ) { return transition_to_starting ( proxy next_req req remaining_retries 1 responder sender ) } ( req req_stream ) next_req { // If a new request comes in, clear out the current AP state. send_ap_stopped_update ( sender ) map_err ( e ExitReason ( Err ( anyhow Error from ( e ) ) ) ) return perform_manual_request ( proxy req req_stream sender ) } } } // Return an error if all retries have been exhausted. Err ( format_err ! ( " " code ) ) } Err ( e ) => { // If communicating with the SME fails, further attempts to start the AP are guaranteed // to fail. Err ( format_err ! ( " " e ) ) } } ; start_result . map_err ( | e | { // Send a failure notification. state . state = types :: OperatingState :: Failed ; let _ = send_state_update ( & sender , state . clone ( ) ) ; ExitReason ( Err ( e ) ) } ) ? ; match responder { Some ( responder ) => responder . send ( ( ) ) . unwrap_or_else ( | _ | ( ) ) , None => { } } state . state = types :: OperatingState :: Active ; send_state_update ( & sender , state . clone ( ) ) . map_err ( | e | ExitReason ( Err ( anyhow :: Error :: from ( e ) ) ) ) ? ; return Ok ( started_state ( proxy , next_req , req , state , sender ) . into_state ( ) ) ; }
In the starting state, a request to ApSmeProxy::Start is made.
In the starting state a request to ApSmeProxy :: Start is made .
proxy
fidl_sme::ApSmeProxy
next_req
NextReqFut
req
ApConfig
remaining_retries
u16
responder
Option<oneshot::Sender<()>>
sender
ApListenerMessageSender
proxy
fidl_sme::ApSmeProxy
next_req
NextReqFut
req
ApConfig
remaining_retries
u16
responder
Option<oneshot::Sender<()>>
sender
ApListenerMessageSender