/// This method handles CTAP packets (64 bytes), until it has assembled
/// a CTAP message, with which it then calls `dispatch_message`.
///
/// During these calls, we can be in states: Idle, Receiving, Dispatching.
This method handles CTAP packets (64 bytes), until it has assembled
a CTAP message, with which it then calls `dispatch_message`.

During these calls, we can be in states: Idle, Receiving, Dispatching.
This method handles CTAP packets ( 64 bytes ) until it has assembled a CTAP message with which it then calls ` dispatch_message ` . During these calls we can be in states : Idle Receiving Dispatching .
pub(crate) fn read_and_handle_packet(&mut self) {
        // info_now!("got a packet!");
        let mut packet = [0u8; PACKET_SIZE];
        match self.read_endpoint.read(&mut packet) {
            Ok(PACKET_SIZE) => {},
            Ok(_size) => {
                // error handling?
                // from spec: "Packets are always fixed size (defined by the endpoint and
                // HID report descriptors) and although all bytes may not be needed in a
                // particular packet, the full size always has to be sent.
                // Unused bytes SHOULD be set to zero."
                // !("OK but size {}", size);
                info!("error unexpected size {}", _size);
                return;
            },
            // usb-device lists WouldBlock or BufferOverflow as possible errors.
            // both should not occur here, and we can't do anything anyway.
            // Err(UsbError::WouldBlock) => { return; },
            // Err(UsbError::BufferOverflow) => { return; },
            Err(_error) => {
                info!("error no {}", _error as i32);
                return;
            },
        };
        info!(">> ");
        info!("{}", hex_str!(&packet[..16]));
        // packet is 64 bytes, reading 4 will not panic
        let channel = u32::from_be_bytes(packet[..4].try_into().unwrap());
        // info_now!("channel {}", channel);
        let is_initialization = (packet[4] >> 7) != 0;
        // info_now!("is_initialization {}", is_initialization);
        if is_initialization {
            // case of initialization packet
            info!("init");
            let command_number = packet[4] & !0x80;
            // info_now!("command number {}", command_number);
            let command = match Command::try_from(command_number) {
                Ok(command) => command,
                // `solo ls` crashes here as it uses command 0x86
                Err(_) => {
                    info!("Ignoring invalid command.");
                    return; },
            };
            // can't actually fail
            let length = u16::from_be_bytes(packet[5..][..2].try_into().unwrap());
            let timestamp = self.last_milliseconds;
            let current_request = Request { channel, command, length, timestamp};
            if !(self.state == State::Idle) {
                let request = match self.state {
                    State::WaitingOnAuthenticator(request) => {
                        request
                    },
                    State::Receiving((request, _message_state)) => {
                        request
                    },
                    _ => {
                        info!("Ignoring transaction as we're already transmitting.");
                        return;
                    },
                };
                if packet[4] == 0x86 {
                    info!("Resyncing!");
                    self.cancel_ongoing_activity();
                } else {
                    if channel == request.channel {
                        info!("Expected seq");
                        self.start_sending_error(request, AuthenticatorError::InvalidSeq);
                    } else {
                        info!("busy.");
                        self.send_error_now(current_request, AuthenticatorError::ChannelBusy);
                    }
                    return;
                }
            }
            if length > MESSAGE_SIZE as u16 {
                info!("Error message too big.");
                self.send_error_now(current_request, AuthenticatorError::InvalidLength);
                return;
            }
            if length > PACKET_SIZE as u16 - 7 {
                // store received part of payload,
                // prepare for continuation packets
                self.buffer[..PACKET_SIZE - 7]
                    .copy_from_slice(&packet[7..]);
                self.state = State::Receiving((current_request, {
                    let state = MessageState::default();
                    // info_now!("got {} so far", state.transmitted);
                    state
                }));
                // we're done... wait for next packet
                return;
            } else {
                // request fits in one packet
                self.buffer[..length as usize]
                    .copy_from_slice(&packet[7..][..length as usize]);
                self.dispatch_request(current_request);
                return;
            }
        } else {
            // case of continuation packet
            match self.state {
                State::Receiving((request, mut message_state)) => {
                    let sequence = packet[4];
                    // info_now!("receiving continuation packet {}", sequence);
                    if sequence != message_state.next_sequence {
                        // error handling?
                        // info_now!("wrong sequence for continuation packet, expected {} received {}",
                        //           message_state.next_sequence, sequence);
                        info!("Error invalid cont pkt");
                        self.start_sending_error(request, AuthenticatorError::InvalidSeq);
                        return;
                    }
                    if channel != request.channel {
                        // error handling?
                        // info_now!("wrong channel for continuation packet, expected {} received {}",
                        //           request.channel, channel);
                        info!("Ignore invalid channel");
                        return;
                    }
                    let payload_length = request.length as usize;
                    if message_state.transmitted + (PACKET_SIZE - 5) < payload_length {
                        // info_now!("transmitted {} + (PACKET_SIZE - 5) < {}",
                        //           message_state.transmitted, payload_length);
                        // store received part of payload
                        self.buffer[message_state.transmitted..][..PACKET_SIZE - 5]
                            .copy_from_slice(&packet[5..]);
                        message_state.absorb_packet();
                        self.state = State::Receiving((request, message_state));
                        // info_now!("absorbed packet, awaiting next");
                        return;
                    } else {
                        let missing = request.length as usize - message_state.transmitted;
                        self.buffer[message_state.transmitted..payload_length]
                            .copy_from_slice(&packet[5..][..missing]);
                        self.dispatch_request(request);
                    }
                },
                _ => {
                    // unexpected continuation packet
                    info!("Ignore unexpected cont pkt");
                    return;
                },
            }
        }
    }
pub ( crate ) fn read_and_handle_packet ( & mut self ) { // info_now!("got a packet!"); let mut packet = [ 0u8 ; PACKET_SIZE ] ; match self . read_endpoint . read ( & mut packet ) { Ok ( PACKET_SIZE ) => { } , Ok ( _size ) => { // error handling? // from spec: "Packets are always fixed size (defined by the endpoint and // HID report descriptors) and although all bytes may not be needed in a // particular packet, the full size always has to be sent. // Unused bytes SHOULD be set to zero." // !("OK but size {}", size); info ! ( " " _size ) ; return ; } , // usb-device lists WouldBlock or BufferOverflow as possible errors. // both should not occur here, and we can't do anything anyway. // Err(UsbError::WouldBlock) => { return; }, // Err(UsbError::BufferOverflow) => { return; }, Err ( _error ) => { info ! ( " " _error as i32 ) ; return ; } , } ; info ! ( " " ) ; info ! ( " " hex_str ( packet [ 16 ] ) ) ; // packet is 64 bytes, reading 4 will not panic let channel = u32 :: from_be_bytes ( packet [ .. 4 ] . try_into ( ) . unwrap ( ) ) ; // info_now!("channel {}", channel); let is_initialization = ( packet [ 4 ] >> 7 ) != 0 ; // info_now!("is_initialization {}", is_initialization); if is_initialization { // case of initialization packet info ! ( " " ) ; let command_number = packet [ 4 ] & ! 0x80 ; // info_now!("command number {}", command_number); let command = match Command :: try_from ( command_number ) { Ok ( command ) => command , // `solo ls` crashes here as it uses command 0x86 Err ( _ ) => { info ! ( " " ) ; return ; } , } ; // can't actually fail let length = u16 :: from_be_bytes ( packet [ 5 .. ] [ .. 2 ] . try_into ( ) . unwrap ( ) ) ; let timestamp = self . last_milliseconds ; let current_request = Request { channel , command , length , timestamp } ; if ! ( self . state == State :: Idle ) { let request = match self . state { State :: WaitingOnAuthenticator ( request ) => { request } , State :: Receiving ( ( request , _message_state ) ) => { request } , _ => { info ! ( " " ) ; return ; } , } ; if packet [ 4 ] == 0x86 { info ! ( " " ) ; self . cancel_ongoing_activity ( ) ; } else { if channel == request . channel { info ! ( " " ) ; self . start_sending_error ( request , AuthenticatorError :: InvalidSeq ) ; } else { info ! ( " " ) ; self . send_error_now ( current_request , AuthenticatorError :: ChannelBusy ) ; } return ; } } if length > MESSAGE_SIZE as u16 { info ! ( " " ) ; self . send_error_now ( current_request , AuthenticatorError :: InvalidLength ) ; return ; } if length > PACKET_SIZE as u16 - 7 { // store received part of payload, // prepare for continuation packets self . buffer [ .. PACKET_SIZE - 7 ] . copy_from_slice ( & packet [ 7 .. ] ) ; self . state = State :: Receiving ( ( current_request , { let state = MessageState :: default ( ) ; // info_now!("got {} so far", state.transmitted); state } ) ) ; // we're done... wait for next packet return ; } else { // request fits in one packet self . buffer [ .. length as usize ] . copy_from_slice ( & packet [ 7 .. ] [ .. length as usize ] ) ; self . dispatch_request ( current_request ) ; return ; } } else { // case of continuation packet match self . state { State :: Receiving ( ( request , mut message_state ) ) => { let sequence = packet [ 4 ] ; // info_now!("receiving continuation packet {}", sequence); if sequence != message_state . next_sequence { // error handling? // info_now!("wrong sequence for continuation packet, expected {} received {}", //           message_state.next_sequence, sequence); info ! ( " " ) ; self . start_sending_error ( request , AuthenticatorError :: InvalidSeq ) ; return ; } if channel != request . channel { // error handling? // info_now!("wrong channel for continuation packet, expected {} received {}", //           request.channel, channel); info ! ( " " ) ; return ; } let payload_length = request . length as usize ; if message_state . transmitted + ( PACKET_SIZE - 5 ) < payload_length { // info_now!("transmitted {} + (PACKET_SIZE - 5) < {}", //           message_state.transmitted, payload_length); // store received part of payload self . buffer [ message_state . transmitted .. ] [ .. PACKET_SIZE - 5 ] . copy_from_slice ( & packet [ 5 .. ] ) ; message_state . absorb_packet ( ) ; self . state = State :: Receiving ( ( request , message_state ) ) ; // info_now!("absorbed packet, awaiting next"); return ; } else { let missing = request . length as usize - message_state . transmitted ; self . buffer [ message_state . transmitted .. payload_length ] . copy_from_slice ( & packet [ 5 .. ] [ .. missing ] ) ; self . dispatch_request ( request ) ; } } , _ => { // unexpected continuation packet info ! ( " " ) ; return ; } , } } }
This method handles CTAP packets (64 bytes), until it has assembled
a CTAP message, with which it then calls `dispatch_message`.
This method handles CTAP packets ( 64 bytes ) until it has assembled a CTAP message with which it then calls ` dispatch_message ` .
&mut self