2022-12-27 09:32:52 +05:30
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Copyright (c) 2020-2022 Project CHIP Authors
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
use crate::data_model::sdm::noc::NocData;
|
|
|
|
use crate::utils::epoch::Epoch;
|
|
|
|
use crate::utils::rand::Rand;
|
2022-12-27 09:32:52 +05:30
|
|
|
use core::fmt;
|
2023-02-02 18:22:21 +00:00
|
|
|
use core::time::Duration;
|
|
|
|
use core::{
|
2022-12-27 09:32:52 +05:30
|
|
|
any::Any,
|
|
|
|
ops::{Deref, DerefMut},
|
|
|
|
};
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
error::*,
|
|
|
|
transport::{plain_hdr, proto_hdr},
|
|
|
|
utils::writebuf::WriteBuf,
|
|
|
|
};
|
|
|
|
use log::{info, trace};
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
use super::dedup::RxCtrState;
|
|
|
|
use super::{network::Address, packet::Packet};
|
2022-12-27 09:32:52 +05:30
|
|
|
|
2023-02-09 15:45:25 +05:30
|
|
|
pub const MAX_CAT_IDS_PER_NOC: usize = 3;
|
2023-02-12 10:14:47 +05:30
|
|
|
pub type NocCatIds = [u32; MAX_CAT_IDS_PER_NOC];
|
|
|
|
|
2022-12-27 09:32:52 +05:30
|
|
|
const MATTER_AES128_KEY_SIZE: usize = 16;
|
|
|
|
|
2023-02-09 15:45:25 +05:30
|
|
|
#[derive(Debug, Default, Copy, Clone, PartialEq)]
|
|
|
|
pub struct CaseDetails {
|
|
|
|
pub fab_idx: u8,
|
2023-02-12 10:14:47 +05:30
|
|
|
pub cat_ids: NocCatIds,
|
2023-02-09 15:45:25 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
impl CaseDetails {
|
2023-02-12 10:14:47 +05:30
|
|
|
pub fn new(fab_idx: u8, cat_ids: &NocCatIds) -> Self {
|
2023-02-09 15:45:25 +05:30
|
|
|
Self {
|
|
|
|
fab_idx,
|
|
|
|
cat_ids: *cat_ids,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
#[derive(Debug, PartialEq, Copy, Clone, Default)]
|
2022-12-27 09:32:52 +05:30
|
|
|
pub enum SessionMode {
|
|
|
|
// The Case session will capture the local fabric index
|
2023-02-09 15:45:25 +05:30
|
|
|
Case(CaseDetails),
|
2022-12-27 09:32:52 +05:30
|
|
|
Pase,
|
2023-02-02 18:22:21 +00:00
|
|
|
#[default]
|
2022-12-27 09:32:52 +05:30
|
|
|
PlainText,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Session {
|
|
|
|
peer_addr: Address,
|
|
|
|
local_nodeid: u64,
|
|
|
|
peer_nodeid: Option<u64>,
|
|
|
|
// I find the session initiator/responder role getting confused with exchange initiator/responder
|
|
|
|
// So, we might keep this as enc_key and dec_key for now
|
|
|
|
dec_key: [u8; MATTER_AES128_KEY_SIZE],
|
|
|
|
enc_key: [u8; MATTER_AES128_KEY_SIZE],
|
|
|
|
att_challenge: [u8; MATTER_AES128_KEY_SIZE],
|
|
|
|
local_sess_id: u16,
|
|
|
|
peer_sess_id: u16,
|
|
|
|
msg_ctr: u32,
|
2023-04-01 20:48:48 +08:00
|
|
|
rx_ctr_state: RxCtrState,
|
2022-12-27 09:32:52 +05:30
|
|
|
mode: SessionMode,
|
2023-02-02 18:22:21 +00:00
|
|
|
data: Option<NocData>,
|
|
|
|
last_use: Duration,
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct CloneData {
|
|
|
|
pub dec_key: [u8; MATTER_AES128_KEY_SIZE],
|
|
|
|
pub enc_key: [u8; MATTER_AES128_KEY_SIZE],
|
|
|
|
pub att_challenge: [u8; MATTER_AES128_KEY_SIZE],
|
|
|
|
local_sess_id: u16,
|
|
|
|
peer_sess_id: u16,
|
|
|
|
local_nodeid: u64,
|
|
|
|
peer_nodeid: u64,
|
|
|
|
peer_addr: Address,
|
|
|
|
mode: SessionMode,
|
|
|
|
}
|
2023-02-02 18:22:21 +00:00
|
|
|
|
2022-12-27 09:32:52 +05:30
|
|
|
impl CloneData {
|
|
|
|
pub fn new(
|
|
|
|
local_nodeid: u64,
|
|
|
|
peer_nodeid: u64,
|
|
|
|
peer_sess_id: u16,
|
|
|
|
local_sess_id: u16,
|
|
|
|
peer_addr: Address,
|
|
|
|
mode: SessionMode,
|
|
|
|
) -> CloneData {
|
|
|
|
CloneData {
|
|
|
|
dec_key: [0; MATTER_AES128_KEY_SIZE],
|
|
|
|
enc_key: [0; MATTER_AES128_KEY_SIZE],
|
|
|
|
att_challenge: [0; MATTER_AES128_KEY_SIZE],
|
|
|
|
local_nodeid,
|
|
|
|
peer_nodeid,
|
|
|
|
peer_addr,
|
|
|
|
peer_sess_id,
|
|
|
|
local_sess_id,
|
|
|
|
mode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const MATTER_MSG_CTR_RANGE: u32 = 0x0fffffff;
|
|
|
|
|
|
|
|
impl Session {
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn new(peer_addr: Address, peer_nodeid: Option<u64>, epoch: Epoch, rand: Rand) -> Self {
|
|
|
|
Self {
|
2022-12-27 09:32:52 +05:30
|
|
|
peer_addr,
|
|
|
|
local_nodeid: 0,
|
|
|
|
peer_nodeid,
|
|
|
|
dec_key: [0; MATTER_AES128_KEY_SIZE],
|
|
|
|
enc_key: [0; MATTER_AES128_KEY_SIZE],
|
|
|
|
att_challenge: [0; MATTER_AES128_KEY_SIZE],
|
|
|
|
peer_sess_id: 0,
|
|
|
|
local_sess_id: 0,
|
2023-02-02 18:22:21 +00:00
|
|
|
msg_ctr: Self::rand_msg_ctr(rand),
|
2023-04-01 20:48:48 +08:00
|
|
|
rx_ctr_state: RxCtrState::new(0),
|
2022-12-27 09:32:52 +05:30
|
|
|
mode: SessionMode::PlainText,
|
|
|
|
data: None,
|
2023-02-02 18:22:21 +00:00
|
|
|
last_use: epoch(),
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A new encrypted session always clones from a previous 'new' session
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn clone(clone_from: &CloneData, epoch: Epoch, rand: Rand) -> Session {
|
2022-12-27 09:32:52 +05:30
|
|
|
Session {
|
|
|
|
peer_addr: clone_from.peer_addr,
|
|
|
|
local_nodeid: clone_from.local_nodeid,
|
|
|
|
peer_nodeid: Some(clone_from.peer_nodeid),
|
|
|
|
dec_key: clone_from.dec_key,
|
|
|
|
enc_key: clone_from.enc_key,
|
|
|
|
att_challenge: clone_from.att_challenge,
|
|
|
|
local_sess_id: clone_from.local_sess_id,
|
|
|
|
peer_sess_id: clone_from.peer_sess_id,
|
2023-02-02 18:22:21 +00:00
|
|
|
msg_ctr: Self::rand_msg_ctr(rand),
|
2023-04-01 20:48:48 +08:00
|
|
|
rx_ctr_state: RxCtrState::new(0),
|
2022-12-27 09:32:52 +05:30
|
|
|
mode: clone_from.mode,
|
|
|
|
data: None,
|
2023-02-02 18:22:21 +00:00
|
|
|
last_use: epoch(),
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn set_noc_data(&mut self, data: NocData) {
|
2022-12-27 09:32:52 +05:30
|
|
|
self.data = Some(data);
|
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn clear_noc_data(&mut self) {
|
2022-12-27 09:32:52 +05:30
|
|
|
self.data = None;
|
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn get_noc_data<T: Any>(&mut self) -> Option<&mut NocData> {
|
|
|
|
self.data.as_mut()
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn take_noc_data(&mut self) -> Option<NocData> {
|
|
|
|
self.data.take()
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_local_sess_id(&self) -> u16 {
|
|
|
|
self.local_sess_id
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
pub fn set_local_sess_id(&mut self, sess_id: u16) {
|
|
|
|
self.local_sess_id = sess_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_peer_sess_id(&self) -> u16 {
|
|
|
|
self.peer_sess_id
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_peer_addr(&self) -> Address {
|
|
|
|
self.peer_addr
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_encrypted(&self) -> bool {
|
|
|
|
match self.mode {
|
|
|
|
SessionMode::Case(_) | SessionMode::Pase => true,
|
|
|
|
SessionMode::PlainText => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_peer_node_id(&self) -> Option<u64> {
|
|
|
|
self.peer_nodeid
|
|
|
|
}
|
|
|
|
|
2023-02-09 15:45:25 +05:30
|
|
|
pub fn get_peer_cat_ids(&self) -> Option<&NocCatIds> {
|
|
|
|
match &self.mode {
|
|
|
|
SessionMode::Case(a) => Some(&a.cat_ids),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-27 09:32:52 +05:30
|
|
|
pub fn get_local_fabric_idx(&self) -> Option<u8> {
|
|
|
|
match self.mode {
|
2023-02-09 15:45:25 +05:30
|
|
|
SessionMode::Case(a) => Some(a.fab_idx),
|
2022-12-27 09:32:52 +05:30
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_session_mode(&self) -> SessionMode {
|
|
|
|
self.mode
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_msg_ctr(&mut self) -> u32 {
|
|
|
|
let ctr = self.msg_ctr;
|
|
|
|
self.msg_ctr += 1;
|
|
|
|
ctr
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_dec_key(&self) -> Option<&[u8]> {
|
|
|
|
match self.mode {
|
|
|
|
SessionMode::Case(_) | SessionMode::Pase => Some(&self.dec_key),
|
|
|
|
SessionMode::PlainText => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_enc_key(&self) -> Option<&[u8]> {
|
|
|
|
match self.mode {
|
|
|
|
SessionMode::Case(_) | SessionMode::Pase => Some(&self.enc_key),
|
|
|
|
SessionMode::PlainText => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_att_challenge(&self) -> &[u8] {
|
|
|
|
&self.att_challenge
|
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn recv(&mut self, epoch: Epoch, rx: &mut Packet) -> Result<(), Error> {
|
|
|
|
self.last_use = epoch();
|
|
|
|
rx.proto_decode(self.peer_nodeid.unwrap_or_default(), self.get_dec_key())
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn pre_send(&mut self, tx: &mut Packet) -> Result<(), Error> {
|
|
|
|
tx.plain.sess_id = self.get_peer_sess_id();
|
|
|
|
tx.plain.ctr = self.get_msg_ctr();
|
2022-12-27 09:32:52 +05:30
|
|
|
if self.is_encrypted() {
|
2023-02-02 18:22:21 +00:00
|
|
|
tx.plain.sess_type = plain_hdr::SessionType::Encrypted;
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Most of this can now be moved into the 'Packet' module
|
2023-02-02 18:22:21 +00:00
|
|
|
fn do_send(&mut self, epoch: Epoch, tx: &mut Packet) -> Result<(), Error> {
|
|
|
|
self.last_use = epoch();
|
|
|
|
tx.peer = self.peer_addr;
|
2022-12-27 09:32:52 +05:30
|
|
|
|
|
|
|
// Generate encrypted header
|
2023-02-02 18:22:21 +00:00
|
|
|
let mut tmp_buf = [0_u8; proto_hdr::max_proto_hdr_len()];
|
|
|
|
let mut write_buf = WriteBuf::new(&mut tmp_buf);
|
|
|
|
tx.proto.encode(&mut write_buf)?;
|
2023-04-22 14:39:17 +00:00
|
|
|
tx.get_writebuf()?.prepend(write_buf.as_slice())?;
|
2022-12-27 09:32:52 +05:30
|
|
|
|
|
|
|
// Generate plain-text header
|
|
|
|
if self.mode == SessionMode::PlainText {
|
|
|
|
if let Some(d) = self.peer_nodeid {
|
2023-02-02 18:22:21 +00:00
|
|
|
tx.plain.set_dest_u64(d);
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
}
|
2023-02-02 18:22:21 +00:00
|
|
|
let mut tmp_buf = [0_u8; plain_hdr::max_plain_hdr_len()];
|
|
|
|
let mut write_buf = WriteBuf::new(&mut tmp_buf);
|
|
|
|
tx.plain.encode(&mut write_buf)?;
|
2023-04-22 14:39:17 +00:00
|
|
|
let plain_hdr_bytes = write_buf.as_slice();
|
2022-12-27 09:32:52 +05:30
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
trace!("unencrypted packet: {:x?}", tx.as_mut_slice());
|
|
|
|
let ctr = tx.plain.ctr;
|
2022-12-27 09:32:52 +05:30
|
|
|
let enc_key = self.get_enc_key();
|
|
|
|
if let Some(e) = enc_key {
|
|
|
|
proto_hdr::encrypt_in_place(
|
|
|
|
ctr,
|
|
|
|
self.local_nodeid,
|
|
|
|
plain_hdr_bytes,
|
2023-02-02 18:22:21 +00:00
|
|
|
tx.get_writebuf()?,
|
2022-12-27 09:32:52 +05:30
|
|
|
e,
|
|
|
|
)?;
|
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
tx.get_writebuf()?.prepend(plain_hdr_bytes)?;
|
|
|
|
trace!("Full encrypted packet: {:x?}", tx.as_mut_slice());
|
2022-12-27 09:32:52 +05:30
|
|
|
Ok(())
|
|
|
|
}
|
2023-02-02 18:22:21 +00:00
|
|
|
|
|
|
|
fn rand_msg_ctr(rand: Rand) -> u32 {
|
|
|
|
let mut buf = [0; 4];
|
|
|
|
rand(&mut buf);
|
|
|
|
u32::from_be_bytes(buf) & MATTER_MSG_CTR_RANGE
|
|
|
|
}
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for Session {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"peer: {:?}, peer_nodeid: {:?}, local: {}, remote: {}, msg_ctr: {}, mode: {:?}, ts: {:?}",
|
|
|
|
self.peer_addr,
|
|
|
|
self.peer_nodeid,
|
|
|
|
self.local_sess_id,
|
|
|
|
self.peer_sess_id,
|
|
|
|
self.msg_ctr,
|
|
|
|
self.mode,
|
|
|
|
self.last_use,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub const MAX_SESSIONS: usize = 16;
|
2023-02-02 18:22:21 +00:00
|
|
|
|
2022-12-27 09:32:52 +05:30
|
|
|
pub struct SessionMgr {
|
|
|
|
next_sess_id: u16,
|
|
|
|
sessions: [Option<Session>; MAX_SESSIONS],
|
2023-02-02 18:22:21 +00:00
|
|
|
epoch: Epoch,
|
|
|
|
rand: Rand,
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
impl SessionMgr {
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn new(epoch: Epoch, rand: Rand) -> Self {
|
|
|
|
const INIT: Option<Session> = None;
|
2022-12-27 09:32:52 +05:30
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
Self {
|
|
|
|
sessions: [INIT; MAX_SESSIONS],
|
|
|
|
next_sess_id: 1,
|
|
|
|
epoch,
|
|
|
|
rand,
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mut_by_index(&mut self, index: usize) -> Option<&mut Session> {
|
|
|
|
self.sessions[index].as_mut()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_next_sess_id(&mut self) -> u16 {
|
|
|
|
let mut next_sess_id: u16;
|
|
|
|
loop {
|
|
|
|
next_sess_id = self.next_sess_id;
|
|
|
|
|
|
|
|
// Increment next sess id
|
|
|
|
self.next_sess_id = self.next_sess_id.overflowing_add(1).0;
|
|
|
|
if self.next_sess_id == 0 {
|
|
|
|
self.next_sess_id = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure the currently selected id doesn't match any existing session
|
|
|
|
if self.get_with_id(next_sess_id).is_none() {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
next_sess_id
|
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn get_session_for_eviction(&self) -> Option<usize> {
|
|
|
|
if self.get_empty_slot().is_none() {
|
|
|
|
Some(self.get_lru())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-27 09:32:52 +05:30
|
|
|
fn get_empty_slot(&self) -> Option<usize> {
|
|
|
|
self.sessions.iter().position(|x| x.is_none())
|
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
fn get_lru(&self) -> usize {
|
2022-12-27 09:32:52 +05:30
|
|
|
let mut lru_index = 0;
|
2023-02-02 18:22:21 +00:00
|
|
|
let mut lru_ts = (self.epoch)();
|
2022-12-27 09:32:52 +05:30
|
|
|
for i in 0..MAX_SESSIONS {
|
|
|
|
if let Some(s) = &self.sessions[i] {
|
|
|
|
if s.last_use < lru_ts {
|
|
|
|
lru_ts = s.last_use;
|
|
|
|
lru_index = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lru_index
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add(&mut self, peer_addr: Address, peer_nodeid: Option<u64>) -> Result<usize, Error> {
|
2023-02-02 18:22:21 +00:00
|
|
|
let session = Session::new(peer_addr, peer_nodeid, self.epoch, self.rand);
|
2022-12-27 09:32:52 +05:30
|
|
|
self.add_session(session)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This assumes that the higher layer has taken care of doing anything required
|
|
|
|
/// as per the spec before the session is erased
|
|
|
|
pub fn remove(&mut self, idx: usize) {
|
|
|
|
self.sessions[idx] = None;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// We could have returned a SessionHandle here. But the borrow checker doesn't support
|
|
|
|
/// non-lexical lifetimes. This makes it harder for the caller of this function to take
|
|
|
|
/// action in the error return path
|
|
|
|
pub fn add_session(&mut self, session: Session) -> Result<usize, Error> {
|
|
|
|
if let Some(index) = self.get_empty_slot() {
|
|
|
|
self.sessions[index] = Some(session);
|
|
|
|
Ok(index)
|
|
|
|
} else {
|
|
|
|
Err(Error::NoSpace)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clone_session(&mut self, clone_data: &CloneData) -> Result<usize, Error> {
|
2023-02-02 18:22:21 +00:00
|
|
|
let session = Session::clone(clone_data, self.epoch, self.rand);
|
2022-12-27 09:32:52 +05:30
|
|
|
self.add_session(session)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn _get(
|
|
|
|
&self,
|
|
|
|
sess_id: u16,
|
|
|
|
peer_addr: Address,
|
|
|
|
peer_nodeid: Option<u64>,
|
|
|
|
is_encrypted: bool,
|
|
|
|
) -> Option<usize> {
|
|
|
|
self.sessions.iter().position(|x| {
|
|
|
|
if let Some(x) = x {
|
|
|
|
let mut nodeid_matches = true;
|
|
|
|
if x.peer_nodeid.is_some() && peer_nodeid.is_some() && x.peer_nodeid != peer_nodeid
|
|
|
|
{
|
|
|
|
nodeid_matches = false;
|
|
|
|
}
|
|
|
|
x.local_sess_id == sess_id
|
|
|
|
&& x.peer_addr == peer_addr
|
|
|
|
&& x.is_encrypted() == is_encrypted
|
|
|
|
&& nodeid_matches
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_with_id(&mut self, sess_id: u16) -> Option<SessionHandle> {
|
|
|
|
let index = self
|
|
|
|
.sessions
|
|
|
|
.iter_mut()
|
|
|
|
.position(|x| x.as_ref().map(|s| s.local_sess_id) == Some(sess_id))?;
|
|
|
|
Some(self.get_session_handle(index))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_or_add(
|
|
|
|
&mut self,
|
|
|
|
sess_id: u16,
|
|
|
|
peer_addr: Address,
|
|
|
|
peer_nodeid: Option<u64>,
|
|
|
|
is_encrypted: bool,
|
|
|
|
) -> Result<usize, Error> {
|
|
|
|
if let Some(index) = self._get(sess_id, peer_addr, peer_nodeid, is_encrypted) {
|
|
|
|
Ok(index)
|
|
|
|
} else if sess_id == 0 && !is_encrypted {
|
|
|
|
// We must create a new session for this case
|
|
|
|
info!("Creating new session");
|
|
|
|
self.add(peer_addr, peer_nodeid)
|
|
|
|
} else {
|
|
|
|
Err(Error::NotFound)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We will try to get a session for this Packet. If no session exists, we will try to add one
|
|
|
|
// If the session list is full we will return a None
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn post_recv(&mut self, rx: &Packet) -> Result<usize, Error> {
|
|
|
|
let sess_index = self.get_or_add(
|
2022-12-27 09:32:52 +05:30
|
|
|
rx.plain.sess_id,
|
|
|
|
rx.peer,
|
|
|
|
rx.plain.get_src_u64(),
|
|
|
|
rx.plain.is_encrypted(),
|
2023-02-02 18:22:21 +00:00
|
|
|
)?;
|
|
|
|
|
|
|
|
let session = self.sessions[sess_index].as_mut().unwrap();
|
|
|
|
let is_encrypted = session.is_encrypted();
|
|
|
|
let duplicate = session.rx_ctr_state.recv(rx.plain.ctr, is_encrypted);
|
|
|
|
if duplicate {
|
|
|
|
info!("Dropping duplicate packet");
|
|
|
|
Err(Error::Duplicate)
|
|
|
|
} else {
|
|
|
|
Ok(sess_index)
|
|
|
|
}
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn decode(&mut self, rx: &mut Packet) -> Result<(), Error> {
|
|
|
|
// let network = self.network.as_ref().ok_or(Error::NoNetworkInterface)?;
|
2022-12-27 09:32:52 +05:30
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
// let (len, src) = network.recv(rx.as_borrow_slice()).await?;
|
|
|
|
// rx.get_parsebuf()?.set_len(len);
|
|
|
|
// rx.peer = src;
|
2022-12-27 09:32:52 +05:30
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
// info!("{} from src: {}", "Received".blue(), src);
|
|
|
|
// trace!("payload: {:x?}", rx.as_borrow_slice());
|
2022-12-27 09:32:52 +05:30
|
|
|
|
|
|
|
// Read unencrypted packet header
|
2023-02-02 18:22:21 +00:00
|
|
|
rx.plain_hdr_decode()
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn send(&mut self, sess_idx: usize, tx: &mut Packet) -> Result<(), Error> {
|
2022-12-27 09:32:52 +05:30
|
|
|
self.sessions[sess_idx]
|
|
|
|
.as_mut()
|
|
|
|
.ok_or(Error::NoSession)?
|
2023-02-02 18:22:21 +00:00
|
|
|
.do_send(self.epoch, tx)?;
|
|
|
|
|
|
|
|
// let network = self.network.as_ref().ok_or(Error::NoNetworkInterface)?;
|
|
|
|
// let peer = proto_tx.peer;
|
|
|
|
// network.send(proto_tx.as_borrow_slice(), peer).await?;
|
|
|
|
// info!("Message Sent to {}", peer);
|
2022-12-27 09:32:52 +05:30
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_session_handle(&mut self, sess_idx: usize) -> SessionHandle {
|
|
|
|
SessionHandle {
|
|
|
|
sess_mgr: self,
|
|
|
|
sess_idx,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for SessionMgr {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
writeln!(f, "{{[")?;
|
|
|
|
for s in self.sessions.iter().flatten() {
|
|
|
|
writeln!(f, "{{ {}, }},", s)?;
|
|
|
|
}
|
|
|
|
write!(f, "], next_sess_id: {}", self.next_sess_id)?;
|
|
|
|
write!(f, "}}")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct SessionHandle<'a> {
|
|
|
|
sess_mgr: &'a mut SessionMgr,
|
|
|
|
sess_idx: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> SessionHandle<'a> {
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn session(&self) -> &Session {
|
|
|
|
self.sess_mgr.sessions[self.sess_idx].as_ref().unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn session_mut(&mut self) -> &mut Session {
|
|
|
|
self.sess_mgr.sessions[self.sess_idx].as_mut().unwrap()
|
|
|
|
}
|
|
|
|
|
2022-12-27 09:32:52 +05:30
|
|
|
pub fn reserve_new_sess_id(&mut self) -> u16 {
|
|
|
|
self.sess_mgr.get_next_sess_id()
|
|
|
|
}
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
pub fn send(&mut self, tx: &mut Packet) -> Result<(), Error> {
|
|
|
|
self.sess_mgr.send(self.sess_idx, tx)
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Deref for SessionHandle<'a> {
|
|
|
|
type Target = Session;
|
2023-02-02 18:22:21 +00:00
|
|
|
|
2022-12-27 09:32:52 +05:30
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
// There is no other option but to panic if this is None
|
2023-02-02 18:22:21 +00:00
|
|
|
self.session()
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> DerefMut for SessionHandle<'a> {
|
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
|
// There is no other option but to panic if this is None
|
2023-02-02 18:22:21 +00:00
|
|
|
self.session_mut()
|
2022-12-27 09:32:52 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
|
2023-02-02 18:22:21 +00:00
|
|
|
use crate::{
|
|
|
|
transport::network::Address,
|
|
|
|
utils::{epoch::dummy_epoch, rand::dummy_rand},
|
|
|
|
};
|
2022-12-27 09:32:52 +05:30
|
|
|
|
|
|
|
use super::SessionMgr;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_next_sess_id_doesnt_reuse() {
|
2023-02-02 18:22:21 +00:00
|
|
|
let mut sm = SessionMgr::new(dummy_epoch, dummy_rand);
|
2022-12-27 09:32:52 +05:30
|
|
|
let sess_idx = sm.add(Address::default(), None).unwrap();
|
|
|
|
let mut sess = sm.get_session_handle(sess_idx);
|
|
|
|
sess.set_local_sess_id(1);
|
|
|
|
assert_eq!(sm.get_next_sess_id(), 2);
|
|
|
|
assert_eq!(sm.get_next_sess_id(), 3);
|
|
|
|
let sess_idx = sm.add(Address::default(), None).unwrap();
|
|
|
|
let mut sess = sm.get_session_handle(sess_idx);
|
|
|
|
sess.set_local_sess_id(4);
|
|
|
|
assert_eq!(sm.get_next_sess_id(), 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_next_sess_id_overflows() {
|
2023-02-02 18:22:21 +00:00
|
|
|
let mut sm = SessionMgr::new(dummy_epoch, dummy_rand);
|
2022-12-27 09:32:52 +05:30
|
|
|
let sess_idx = sm.add(Address::default(), None).unwrap();
|
|
|
|
let mut sess = sm.get_session_handle(sess_idx);
|
|
|
|
sess.set_local_sess_id(1);
|
|
|
|
assert_eq!(sm.get_next_sess_id(), 2);
|
|
|
|
sm.next_sess_id = 65534;
|
|
|
|
assert_eq!(sm.get_next_sess_id(), 65534);
|
|
|
|
assert_eq!(sm.get_next_sess_id(), 65535);
|
|
|
|
assert_eq!(sm.get_next_sess_id(), 2);
|
|
|
|
}
|
|
|
|
}
|