async fn on_inbound_frame(&self, raw_frame: &[u8]) -> Result<(), Error> {
        const RESET_RESPONSE_PREFIX: &[u8] = &[0x80, 0x06, 0x00];

        // Parse the header.
        let frame = SpinelFrameRef::try_unpack_from_slice(raw_frame).context("on_inbound_frame")?;

        fx_log_debug!("[NCP->] {:?}", frame);

        // If we are waiting for a reset and this frame doesn't
        // look like it might be a reset indication then we drop the frame.
        if self.driver_state.lock().init_state == InitState::WaitingForReset
            && !raw_frame.starts_with(RESET_RESPONSE_PREFIX)
        {
            fx_log_info!("on_inbound_frame: Waiting for reset, dropping {:?}", frame);
            return Ok(());
        }

        // We only support NLI zero for the foreseeable future.
        if frame.header.nli() != 0 {
            fx_log_info!("on_inbound_frame: Skipping unexpected NLI for frame {:?}", frame);
            return Ok(());
        }

        // Is the command `PropValueIs`, `PropValueInserted`, or `PropValueRemoved`?
        // If so, dispatch to state update.
        match frame.cmd {
            Cmd::PropValueIs => {
                let prop_value = SpinelPropValueRef::try_unpack_from_slice(frame.payload)
                    .context("on_inbound_frame:PropValueIs")?;

                if prop_value.prop == Prop::Stream(PropStream::Net) {
                    let network_packet = NetworkPacket::try_unpack_from_slice(prop_value.value)
                        .context("on_inbound_frame:parsing_net_packet")?;

                    self.net_if.inbound_packet_to_stack(network_packet.packet).await?;

                    let mut driver_state = self.driver_state.lock();
                    if driver_state.assisting_state.update_from_secure(network_packet.packet) {
                        fx_log_info!("on_inbound_frame: Commissioning session successfully migrated to mesh network: {:?}", Ipv6PacketDebug(network_packet.packet));
                    }
                } else if prop_value.prop == Prop::Stream(PropStream::NetInsecure) {
                    let network_packet = NetworkPacket::try_unpack_from_slice(prop_value.value)
                        .context("on_inbound_frame:parsing_insecure_net_packet")?;

                    fx_log_info!(
                        "on_inbound_frame: Commissioning packet: {:?}",
                        Ipv6PacketDebug(network_packet.packet)
                    );

                    let should_allow_from_insecure = {
                        let mut driver_state = self.driver_state.lock();
                        driver_state
                            .assisting_state
                            .should_allow_from_insecure(network_packet.packet)
                    };

                    if should_allow_from_insecure {
                        fx_log_info!("on_inbound_frame: Commissioning packet routed to stack");
                        self.net_if.inbound_packet_to_stack(network_packet.packet).await?;
                    } else {
                        fx_log_info!("on_inbound_frame: Dropping commissioning packet packet");
                    }
                } else {
                    self.on_prop_value_is(prop_value.prop, prop_value.value)?;
                }

                // We handle resets explicitly here.
                // An actionable reset is defined as an unsolicited (TID Zero/None)
                // `Prop::LastStatus` update with a status code in the reset range.
                // Solicited responses (TID 1-15) are not considered resets.
                if prop_value.prop == Prop::LastStatus && frame.header.tid().is_none() {
                    if let Status::Reset(x) = Status::try_unpack_from_slice(prop_value.value)? {
                        fx_log_info!("on_inbound_frame: Reset: {:?}", x);
                        self.frame_handler.clear();
                        {
                            let mut driver_state = self.driver_state.lock();
                            if driver_state.init_state != InitState::WaitingForReset {
                                let maybe_old_state = driver_state.prepare_for_init();

                                // Avoid holding the mutex for longer than we need to.
                                std::mem::drop(driver_state);

                                self.driver_state_change.trigger();

                                if let Some(old_state) = maybe_old_state {
                                    // Make sure we signal a connectivity state change.
                                    self.on_connectivity_state_change(
                                        ConnectivityState::Attaching,
                                        old_state,
                                    );
                                }
                            }
                        }
                        self.ncp_did_reset.trigger();
                    }
                }
            }

            Cmd::PropValueInserted => {
                let prop_value = SpinelPropValueRef::try_unpack_from_slice(frame.payload)
                    .context("on_inbound_frame:PropValueInserted")?;
                self.on_prop_value_inserted(prop_value.prop, prop_value.value)?;
            }

            Cmd::PropValueRemoved => {
                let prop_value = SpinelPropValueRef::try_unpack_from_slice(frame.payload)
                    .context("on_inbound_frame:PropValueRemoved")?;
                self.on_prop_value_removed(prop_value.prop, prop_value.value)?;
            }

            // Ignore all other commands for now.
            _ => {}
        }

        // Finally pass the frame to the response frame handler.
        self.frame_handler.handle_inbound_frame(frame)
    }
/// Method for handling inbound frames and pushing them
/// to where they need to go.
///
/// Specifically, all inbound frames that are property change notifications,
/// (PROP_IS, PROP_INSERTED, and PROP_REMOVED) are dispatched
/// to the appropriate `on_prop_value_*()` handler. Also, if the TID is
/// non-zero, the frame also is also sent to the frame handler for
/// response dispatch.
///
/// Resets are a special case and are handled directly.
/// Everything else is delegated as described above.
Method for handling inbound frames and pushing them
to where they need to go.

Specifically, all inbound frames that are property change notifications,
(PROP_IS, PROP_INSERTED, and PROP_REMOVED) are dispatched
to the appropriate `on_prop_value_*()` handler. Also, if the TID is
non-zero, the frame also is also sent to the frame handler for
response dispatch.

Resets are a special case and are handled directly.
Everything else is delegated as described above.
Method for handling inbound frames and pushing them to where they need to go . Specifically all inbound frames that are property change notifications ( PROP_IS PROP_INSERTED and PROP_REMOVED ) are dispatched to the appropriate ` on_prop_value_ * () ` handler . Also if the TID is non - zero the frame also is also sent to the frame handler for response dispatch . Resets are a special case and are handled directly . Everything else is delegated as described above .
async fn on_inbound_frame(&self, raw_frame: &[u8]) -> Result<(), Error> {
        const RESET_RESPONSE_PREFIX: &[u8] = &[0x80, 0x06, 0x00];
        // Parse the header.
        let frame = SpinelFrameRef::try_unpack_from_slice(raw_frame).context("on_inbound_frame")?;
        fx_log_debug!("[NCP->] {:?}", frame);
        // If we are waiting for a reset and this frame doesn't
        // look like it might be a reset indication then we drop the frame.
        if self.driver_state.lock().init_state == InitState::WaitingForReset
            && !raw_frame.starts_with(RESET_RESPONSE_PREFIX)
        {
            fx_log_info!("on_inbound_frame: Waiting for reset, dropping {:?}", frame);
            return Ok(());
        }
        // We only support NLI zero for the foreseeable future.
        if frame.header.nli() != 0 {
            fx_log_info!("on_inbound_frame: Skipping unexpected NLI for frame {:?}", frame);
            return Ok(());
        }
        // Is the command `PropValueIs`, `PropValueInserted`, or `PropValueRemoved`?
        // If so, dispatch to state update.
        match frame.cmd {
            Cmd::PropValueIs => {
                let prop_value = SpinelPropValueRef::try_unpack_from_slice(frame.payload)
                    .context("on_inbound_frame:PropValueIs")?;
                if prop_value.prop == Prop::Stream(PropStream::Net) {
                    let network_packet = NetworkPacket::try_unpack_from_slice(prop_value.value)
                        .context("on_inbound_frame:parsing_net_packet")?;
                    self.net_if.inbound_packet_to_stack(network_packet.packet).await?;
                    let mut driver_state = self.driver_state.lock();
                    if driver_state.assisting_state.update_from_secure(network_packet.packet) {
                        fx_log_info!("on_inbound_frame: Commissioning session successfully migrated to mesh network: {:?}", Ipv6PacketDebug(network_packet.packet));
                    }
                } else if prop_value.prop == Prop::Stream(PropStream::NetInsecure) {
                    let network_packet = NetworkPacket::try_unpack_from_slice(prop_value.value)
                        .context("on_inbound_frame:parsing_insecure_net_packet")?;
                    fx_log_info!(
                        "on_inbound_frame: Commissioning packet: {:?}",
                        Ipv6PacketDebug(network_packet.packet)
                    );
                    let should_allow_from_insecure = {
                        let mut driver_state = self.driver_state.lock();
                        driver_state
                            .assisting_state
                            .should_allow_from_insecure(network_packet.packet)
                    };
                    if should_allow_from_insecure {
                        fx_log_info!("on_inbound_frame: Commissioning packet routed to stack");
                        self.net_if.inbound_packet_to_stack(network_packet.packet).await?;
                    } else {
                        fx_log_info!("on_inbound_frame: Dropping commissioning packet packet");
                    }
                } else {
                    self.on_prop_value_is(prop_value.prop, prop_value.value)?;
                }
                // We handle resets explicitly here.
                // An actionable reset is defined as an unsolicited (TID Zero/None)
                // `Prop::LastStatus` update with a status code in the reset range.
                // Solicited responses (TID 1-15) are not considered resets.
                if prop_value.prop == Prop::LastStatus && frame.header.tid().is_none() {
                    if let Status::Reset(x) = Status::try_unpack_from_slice(prop_value.value)? {
                        fx_log_info!("on_inbound_frame: Reset: {:?}", x);
                        self.frame_handler.clear();
                        {
                            let mut driver_state = self.driver_state.lock();
                            if driver_state.init_state != InitState::WaitingForReset {
                                let maybe_old_state = driver_state.prepare_for_init();
                                // Avoid holding the mutex for longer than we need to.
                                std::mem::drop(driver_state);
                                self.driver_state_change.trigger();
                                if let Some(old_state) = maybe_old_state {
                                    // Make sure we signal a connectivity state change.
                                    self.on_connectivity_state_change(
                                        ConnectivityState::Attaching,
                                        old_state,
                                    );
                                }
                            }
                        }
                        self.ncp_did_reset.trigger();
                    }
                }
            }
            Cmd::PropValueInserted => {
                let prop_value = SpinelPropValueRef::try_unpack_from_slice(frame.payload)
                    .context("on_inbound_frame:PropValueInserted")?;
                self.on_prop_value_inserted(prop_value.prop, prop_value.value)?;
            }
            Cmd::PropValueRemoved => {
                let prop_value = SpinelPropValueRef::try_unpack_from_slice(frame.payload)
                    .context("on_inbound_frame:PropValueRemoved")?;
                self.on_prop_value_removed(prop_value.prop, prop_value.value)?;
            }
            // Ignore all other commands for now.
            _ => {}
        }
        // Finally pass the frame to the response frame handler.
        self.frame_handler.handle_inbound_frame(frame)
    }
async fn on_inbound_frame ( & self , raw_frame : & [ u8 ] ) -> Result < ( ) , Error > { const RESET_RESPONSE_PREFIX : & [ u8 ] = & [ 0x80 , 0x06 , 0x00 ] ; // Parse the header. let frame = SpinelFrameRef :: try_unpack_from_slice ( raw_frame ) . context ( " " ) ? ; fx_log_debug ! ( " " frame ) ; // If we are waiting for a reset and this frame doesn't // look like it might be a reset indication then we drop the frame. if self . driver_state . lock ( ) . init_state == InitState :: WaitingForReset && ! raw_frame . starts_with ( RESET_RESPONSE_PREFIX ) { fx_log_info ! ( " " frame ) ; return Ok ( ( ) ) ; } // We only support NLI zero for the foreseeable future. if frame . header . nli ( ) != 0 { fx_log_info ! ( " " frame ) ; return Ok ( ( ) ) ; } // Is the command `PropValueIs`, `PropValueInserted`, or `PropValueRemoved`? // If so, dispatch to state update. match frame . cmd { Cmd :: PropValueIs => { let prop_value = SpinelPropValueRef :: try_unpack_from_slice ( frame . payload ) . context ( " " ) ? ; if prop_value . prop == Prop :: Stream ( PropStream :: Net ) { let network_packet = NetworkPacket :: try_unpack_from_slice ( prop_value . value ) . context ( " " ) ? ; self . net_if . inbound_packet_to_stack ( network_packet . packet ) . await ? ; let mut driver_state = self . driver_state . lock ( ) ; if driver_state . assisting_state . update_from_secure ( network_packet . packet ) { fx_log_info ! ( " " Ipv6PacketDebug ( network_packet packet ) ) ; } } else if prop_value . prop == Prop :: Stream ( PropStream :: NetInsecure ) { let network_packet = NetworkPacket :: try_unpack_from_slice ( prop_value . value ) . context ( " " ) ? ; fx_log_info ! ( " " Ipv6PacketDebug ( network_packet packet ) ) ; let should_allow_from_insecure = { let mut driver_state = self . driver_state . lock ( ) ; driver_state . assisting_state . should_allow_from_insecure ( network_packet . packet ) } ; if should_allow_from_insecure { fx_log_info ! ( " " ) ; self . net_if . inbound_packet_to_stack ( network_packet . packet ) . await ? ; } else { fx_log_info ! ( " " ) ; } } else { self . on_prop_value_is ( prop_value . prop , prop_value . value ) ? ; } // We handle resets explicitly here. // An actionable reset is defined as an unsolicited (TID Zero/None) // `Prop::LastStatus` update with a status code in the reset range. // Solicited responses (TID 1-15) are not considered resets. if prop_value . prop == Prop :: LastStatus && frame . header . tid ( ) . is_none ( ) { if let Status :: Reset ( x ) = Status :: try_unpack_from_slice ( prop_value . value ) ? { fx_log_info ! ( " " x ) ; self . frame_handler . clear ( ) ; { let mut driver_state = self . driver_state . lock ( ) ; if driver_state . init_state != InitState :: WaitingForReset { let maybe_old_state = driver_state . prepare_for_init ( ) ; // Avoid holding the mutex for longer than we need to. std :: mem :: drop ( driver_state ) ; self . driver_state_change . trigger ( ) ; if let Some ( old_state ) = maybe_old_state { // Make sure we signal a connectivity state change. self . on_connectivity_state_change ( ConnectivityState :: Attaching , old_state , ) ; } } } self . ncp_did_reset . trigger ( ) ; } } } Cmd :: PropValueInserted => { let prop_value = SpinelPropValueRef :: try_unpack_from_slice ( frame . payload ) . context ( " " ) ? ; self . on_prop_value_inserted ( prop_value . prop , prop_value . value ) ? ; } Cmd :: PropValueRemoved => { let prop_value = SpinelPropValueRef :: try_unpack_from_slice ( frame . payload ) . context ( " " ) ? ; self . on_prop_value_removed ( prop_value . prop , prop_value . value ) ? ; } // Ignore all other commands for now. _ => { } } // Finally pass the frame to the response frame handler. self . frame_handler . handle_inbound_frame ( frame ) }
Method for handling inbound frames and pushing them
to where they need to go.
Method for handling inbound frames and pushing them to where they need to go .
&self
raw_frame
&[u8]
&self
raw_frame
&[u8]