bluetooth_mesh 0.1.4

Cross-platform, full Bluetooth Mesh stack implemented in Rust. Following the Bluetooth Mesh Spec Core v1.0 by SIG. Designed to work with any almost any BLE radio (uses https://github.com/AndrewGi/btle/ for platform dependent Bluetooth drivers). While a stack is provided by the library, all the primatives and objects needed to customize and create your own stack are provided. See https://github.com/AndrewGi/BluetoothMeshRust for more.
Documentation
//! Appliation layer.

use crate::address::{Address, UnicastAddress};
use crate::btle::RSSI;
use crate::crypto::aes::MicSize;
use crate::crypto::nonce::{AppNonce, AppNonceParts, DeviceNonce, DeviceNonceParts};
use crate::device_state::SeqRange;
use crate::lower::{SegO, SeqAuth};
use crate::mesh::{AppKeyIndex, ElementIndex, IVIndex, NetKeyIndex, SequenceNumber, TTL};
use crate::stack::segments;
use crate::upper::{AppPayload, EncryptedAppPayload};
use crate::{control, lower, net, segmenter, upper};

pub enum MessageKeys {
    Device(NetKeyIndex),
    App(AppKeyIndex),
}
pub struct OutgoingDestination {
    pub dst: Address,
    pub ttl: Option<TTL>,
    pub app_key_index: AppKeyIndex,
}
pub struct OutgoingMessage<Storage: AsRef<[u8]>> {
    pub app_payload: AppPayload<Storage>,
    pub mic_size: MicSize,
    pub force_segment: bool,
    pub encryption_key: MessageKeys,
    pub iv_index: IVIndex,
    pub source_element_index: ElementIndex,
    pub dst: Address,
    pub ttl: Option<TTL>,
}
pub struct OutgoingLowerTransportMessage {
    pub pdu: lower::PDU,
    pub src: UnicastAddress,
    pub dst: Address,
    pub ttl: Option<TTL>,
    pub seq: Option<SequenceNumber>,
    pub iv_index: IVIndex,
    pub net_key_index: NetKeyIndex,
}
impl<Storage: AsRef<[u8]>> OutgoingMessage<Storage> {
    pub fn data_with_mic_len(&self) -> usize {
        self.app_payload.0.as_ref().len() + self.mic_size.byte_size()
    }
    pub fn should_segment(&self) -> bool {
        self.force_segment || self.app_payload.should_segment(self.mic_size)
    }
    pub fn seg_o(&self) -> Option<SegO> {
        if !self.should_segment() {
            None
        } else {
            Some(upper::calculate_seg_o(
                self.data_with_mic_len(),
                lower::SegmentedAccessPDU::max_seg_len(),
            ))
        }
    }
}
pub struct OutgoingUpperTransportMessage<Storage: AsRef<[u8]>> {
    pub upper_pdu: upper::PDU<Storage>,
    pub iv_index: IVIndex,
    pub seq: SeqRange,
    pub seg_count: SegO,
    pub net_key_index: NetKeyIndex,
    pub src: UnicastAddress,
    pub dst: Address,
    pub ttl: Option<TTL>,
}
impl<Storage: AsRef<[u8]>> OutgoingUpperTransportMessage<Storage> {
    pub fn should_segment(&self) -> bool {
        self.upper_pdu.should_segment()
    }
    pub fn into_outgoing_segments(self) -> segments::OutgoingSegments<Storage> {
        debug_assert_eq!(
            self.seq.seqs_lefts(),
            u32::from(u8::from(self.seg_count)) + 1_u32,
            "wrong about of sequence numbers"
        );
        segments::OutgoingSegments {
            segments: segmenter::UpperSegmenter {
                upper_pdu: self.upper_pdu,
                seg_o: self.seg_count,
                seq_auth: SeqAuth::new(self.seq.start(), self.iv_index),
            },
            block_ack: Default::default(),
            net_key_index: self.net_key_index,
            src: self.src,
            dst: self.dst,
            ttl: self.ttl,
        }
    }
}
pub struct EncryptedIncomingMessage<Storage: AsRef<[u8]>> {
    pub encrypted_app_payload: EncryptedAppPayload<Storage>,
    pub seq: SequenceNumber,
    pub seg_count: u8,
    pub iv_index: IVIndex,
    pub net_key_index: NetKeyIndex,
    pub dst: Address,
    pub src: UnicastAddress,
    pub ttl: Option<TTL>,
    pub rssi: Option<RSSI>,
}
impl<Storage: AsRef<[u8]>> EncryptedIncomingMessage<Storage> {
    pub fn app_nonce_parts(&self) -> AppNonceParts {
        AppNonceParts {
            aszmic: self.szmic(),
            seq: self.seq,
            src: self.src,
            dst: self.dst,
            iv_index: self.iv_index,
        }
    }
    pub fn app_nonce(&self) -> AppNonce {
        self.app_nonce_parts().to_nonce()
    }
    pub fn szmic(&self) -> bool {
        self.encrypted_app_payload.mic().is_big()
    }
    pub fn device_nonce_parts(&self) -> DeviceNonceParts {
        DeviceNonceParts {
            aszmic: self.szmic(),
            seq: self.seq,
            src: self.src,
            dst: self.dst,
            iv_index: self.iv_index,
        }
    }
    pub fn device_nonce(&self) -> DeviceNonce {
        self.device_nonce_parts().to_nonce()
    }
}
pub struct IncomingControlMessage {
    pub control_pdu: control::ControlPDU,
    pub src: UnicastAddress,
    pub rssi: Option<RSSI>,
    pub ttl: Option<TTL>,
}
pub struct IncomingMessage<Storage: AsRef<[u8]>> {
    pub payload: Storage,
    pub src: UnicastAddress,
    pub dst: Address,
    pub seq: SequenceNumber,
    pub iv_index: IVIndex,
    pub net_key_index: NetKeyIndex,
    pub app_key_index: Option<AppKeyIndex>,
    pub ttl: Option<TTL>,
    pub rssi: Option<RSSI>,
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct IncomingNetworkPDU {
    pub pdu: net::PDU,
    pub net_key_index: NetKeyIndex,
    pub iv_index: IVIndex,
    pub rssi: Option<RSSI>,
}
pub struct IncomingTransportPDU<Storage: AsRef<[u8]> + AsMut<[u8]>> {
    pub upper_pdu: upper::PDU<Storage>,
    pub iv_index: IVIndex,
    pub seg_count: u8,
    pub seq: SequenceNumber,
    pub net_key_index: NetKeyIndex,
    pub ttl: Option<TTL>,
    pub rssi: Option<RSSI>,
    pub src: UnicastAddress,
    pub dst: Address,
}