trouble_host/
connection_manager.rs

1use core::cell::RefCell;
2use core::future::poll_fn;
3#[cfg(feature = "security")]
4use core::future::Future;
5use core::task::{Context, Poll};
6
7use bt_hci::param::{AddrKind, BdAddr, ConnHandle, DisconnectReason, LeConnRole, Status};
8use embassy_sync::blocking_mutex::raw::NoopRawMutex;
9use embassy_sync::channel::Channel;
10use embassy_sync::waitqueue::WakerRegistration;
11#[cfg(feature = "security")]
12use embassy_time::TimeoutError;
13
14use crate::connection::{Connection, ConnectionEvent, SecurityLevel};
15use crate::host::EventHandler;
16use crate::pdu::Pdu;
17use crate::prelude::sar::PacketReassembly;
18#[cfg(feature = "security")]
19use crate::security_manager::{SecurityEventData, SecurityManager};
20use crate::{config, Error, Identity, PacketPool};
21
22struct State<'d, P> {
23    connections: &'d mut [ConnectionStorage<P>],
24    central_waker: WakerRegistration,
25    peripheral_waker: WakerRegistration,
26    disconnect_waker: WakerRegistration,
27    default_link_credits: usize,
28    default_att_mtu: u16,
29}
30
31impl<P> State<'_, P> {
32    fn print(&self, verbose: bool) {
33        for (idx, storage) in self.connections.iter().enumerate() {
34            if verbose || storage.state != ConnectionState::Disconnected {
35                debug!("[link][idx = {}] state = {:?}", idx, storage);
36            }
37        }
38    }
39
40    fn inc_ref(&mut self, index: u8) {
41        let state = &mut self.connections[index as usize];
42        state.refcount = unwrap!(
43            state.refcount.checked_add(1),
44            "Too many references to the same connection"
45        );
46    }
47}
48
49type EventChannel = Channel<NoopRawMutex, ConnectionEvent, { config::CONNECTION_EVENT_QUEUE_SIZE }>;
50type GattChannel<P> = Channel<NoopRawMutex, Pdu<P>, { config::L2CAP_RX_QUEUE_SIZE }>;
51
52pub(crate) struct ConnectionManager<'d, P: PacketPool> {
53    state: RefCell<State<'d, P::Packet>>,
54    outbound: Channel<NoopRawMutex, (ConnHandle, Pdu<P::Packet>), { config::L2CAP_TX_QUEUE_SIZE }>,
55    #[cfg(feature = "security")]
56    pub(crate) security_manager: SecurityManager<{ crate::BI_COUNT }>,
57}
58
59impl<'d, P: PacketPool> ConnectionManager<'d, P> {
60    pub(crate) fn new(connections: &'d mut [ConnectionStorage<P::Packet>], default_att_mtu: u16) -> Self {
61        Self {
62            state: RefCell::new(State {
63                connections,
64                central_waker: WakerRegistration::new(),
65                peripheral_waker: WakerRegistration::new(),
66                disconnect_waker: WakerRegistration::new(),
67                default_link_credits: 0,
68                default_att_mtu,
69            }),
70            outbound: Channel::new(),
71            #[cfg(feature = "security")]
72            security_manager: SecurityManager::new(),
73        }
74    }
75
76    pub(crate) fn role(&self, index: u8) -> LeConnRole {
77        self.with_mut(|state| {
78            let state = &mut state.connections[index as usize];
79            state.role.unwrap()
80        })
81    }
82
83    pub(crate) fn handle(&self, index: u8) -> ConnHandle {
84        self.with_mut(|state| {
85            let state = &mut state.connections[index as usize];
86            state.handle.unwrap()
87        })
88    }
89
90    pub(crate) fn is_connected(&self, index: u8) -> bool {
91        self.with_mut(|state| {
92            let state = &mut state.connections[index as usize];
93            state.state == ConnectionState::Connected
94        })
95    }
96
97    pub(crate) async fn next(&self, index: u8) -> ConnectionEvent {
98        poll_fn(|cx| self.with_mut(|state| state.connections[index as usize].events.poll_receive(cx))).await
99    }
100
101    #[cfg(feature = "gatt")]
102    pub(crate) async fn next_gatt(&self, index: u8) -> Pdu<P::Packet> {
103        poll_fn(|cx| self.with_mut(|state| state.connections[index as usize].gatt.poll_receive(cx))).await
104    }
105
106    pub(crate) async fn post_event(&self, index: u8, event: ConnectionEvent) {
107        poll_fn(|cx| self.with_mut(|state| state.connections[index as usize].events.poll_ready_to_send(cx))).await;
108        self.with_mut(|state| state.connections[index as usize].events.try_send(event).unwrap());
109    }
110
111    pub(crate) fn post_handle_event(&self, handle: ConnHandle, event: ConnectionEvent) -> Result<(), Error> {
112        self.with_mut(|state| {
113            for entry in state.connections.iter() {
114                if entry.state == ConnectionState::Connected && Some(handle) == entry.handle {
115                    entry.events.try_send(event).map_err(|_| Error::OutOfMemory)?;
116                    return Ok(());
117                }
118            }
119            Err(Error::NotFound)
120        })
121    }
122
123    #[cfg(feature = "gatt")]
124    pub(crate) fn post_gatt(&self, handle: ConnHandle, pdu: Pdu<P::Packet>) -> Result<(), Error> {
125        self.with_mut(|state| {
126            for entry in state.connections.iter() {
127                if entry.state == ConnectionState::Connected && Some(handle) == entry.handle {
128                    entry.gatt.try_send(pdu).map_err(|_| Error::OutOfMemory)?;
129                    return Ok(());
130                }
131            }
132            Err(Error::NotFound)
133        })
134    }
135
136    pub(crate) fn peer_address(&self, index: u8) -> BdAddr {
137        self.with_mut(|state| {
138            let state = &mut state.connections[index as usize];
139            match state.peer_identity {
140                Some(identity) => identity.bd_addr, // TODO: If irk is used, this addr might be outdated.
141                _ => BdAddr::default(),
142            }
143        })
144    }
145
146    pub(crate) fn peer_identity(&self, index: u8) -> Identity {
147        self.with_mut(|state| {
148            let state = &mut state.connections[index as usize];
149            state.peer_identity.unwrap()
150        })
151    }
152
153    pub(crate) fn set_att_mtu(&self, index: u8, mtu: u16) {
154        self.with_mut(|state| {
155            state.connections[index as usize].att_mtu = mtu;
156        })
157    }
158
159    pub(crate) fn request_disconnect(&self, index: u8, reason: DisconnectReason) {
160        self.with_mut(|state| {
161            let entry = &mut state.connections[index as usize];
162            if entry.state == ConnectionState::Connected {
163                entry.state = ConnectionState::DisconnectRequest(reason);
164                state.disconnect_waker.wake();
165            }
166        })
167    }
168
169    pub(crate) fn request_handle_disconnect(&self, handle: ConnHandle, reason: DisconnectReason) {
170        self.with_mut(|state| {
171            for entry in state.connections.iter_mut() {
172                if entry.state == ConnectionState::Connected && Some(handle) == entry.handle {
173                    entry.state = ConnectionState::DisconnectRequest(reason);
174                    state.disconnect_waker.wake();
175                    break;
176                }
177            }
178        })
179    }
180
181    pub(crate) fn poll_disconnecting<'m>(
182        &'m self,
183        cx: Option<&mut Context<'_>>,
184    ) -> Poll<DisconnectRequest<'m, 'd, P::Packet>> {
185        let mut state = self.state.borrow_mut();
186        if let Some(cx) = cx {
187            state.disconnect_waker.register(cx.waker());
188        }
189        for (idx, storage) in state.connections.iter().enumerate() {
190            if let ConnectionState::DisconnectRequest(reason) = storage.state {
191                return Poll::Ready(DisconnectRequest {
192                    index: idx,
193                    handle: storage.handle.unwrap(),
194                    reason,
195                    state: &self.state,
196                });
197            }
198        }
199        Poll::Pending
200    }
201
202    pub(crate) fn get_connected_handle(&'d self, h: ConnHandle) -> Option<Connection<'d, P>> {
203        let mut state = self.state.borrow_mut();
204        for (index, storage) in state.connections.iter().enumerate() {
205            match (storage.handle, &storage.state) {
206                (Some(handle), ConnectionState::Connected) if handle == h => {
207                    state.inc_ref(index as u8);
208                    return Some(Connection::new(index as u8, self));
209                }
210                _ => {}
211            }
212        }
213        None
214    }
215
216    pub(crate) fn with_connected_handle<F: FnOnce(&mut ConnectionStorage<P::Packet>) -> Result<R, Error>, R>(
217        &self,
218        h: ConnHandle,
219        f: F,
220    ) -> Result<R, Error> {
221        let mut state = self.state.borrow_mut();
222        for storage in state.connections.iter_mut() {
223            match (storage.handle, &storage.state) {
224                (Some(handle), ConnectionState::Connected) if handle == h => {
225                    return f(storage);
226                }
227                (Some(handle), ConnectionState::Connecting) if handle == h => {
228                    return f(storage);
229                }
230                _ => {}
231            }
232        }
233        Err(Error::Disconnected)
234    }
235
236    pub(crate) fn received(&self, h: ConnHandle) -> Result<(), Error> {
237        self.with_connected_handle(h, |storage| {
238            #[cfg(feature = "connection-metrics")]
239            storage.metrics.received(1);
240            Ok(())
241        })
242    }
243
244    pub(crate) fn is_handle_connected(&self, h: ConnHandle) -> bool {
245        self.with_connected_handle(h, |_storage| Ok(())).is_ok()
246    }
247
248    pub(crate) fn reassembly<F: FnOnce(&mut PacketReassembly<P::Packet>) -> Result<R, Error>, R>(
249        &self,
250        h: ConnHandle,
251        f: F,
252    ) -> Result<R, Error> {
253        self.with_connected_handle(h, |storage| f(&mut storage.reassembly))
254    }
255
256    pub(crate) fn disconnected(&self, h: ConnHandle, reason: Status) -> Result<(), Error> {
257        let mut state = self.state.borrow_mut();
258        for (idx, storage) in state.connections.iter_mut().enumerate() {
259            if Some(h) == storage.handle && storage.state != ConnectionState::Disconnected {
260                storage.state = ConnectionState::Disconnected;
261                storage.reassembly.clear();
262                let _ = storage.events.try_send(ConnectionEvent::Disconnected { reason });
263                #[cfg(feature = "gatt")]
264                storage.gatt.clear();
265                #[cfg(feature = "connection-metrics")]
266                storage.metrics.reset();
267                #[cfg(feature = "security")]
268                {
269                    storage.security_level = SecurityLevel::NoEncryption;
270                    storage.bondable = false;
271                    let _ = self.security_manager.disconnect(h, storage.peer_identity);
272                }
273                return Ok(());
274            }
275        }
276        warn!("[link][disconnect] connection handle {:?} not found", h);
277        Err(Error::NotFound)
278    }
279
280    pub(crate) fn connect(
281        &self,
282        handle: ConnHandle,
283        peer_addr_kind: AddrKind,
284        peer_addr: BdAddr,
285        role: LeConnRole,
286    ) -> Result<(), Error> {
287        let mut state = self.state.borrow_mut();
288        let default_credits = state.default_link_credits;
289        let default_att_mtu = state.default_att_mtu;
290        for (idx, storage) in state.connections.iter_mut().enumerate() {
291            if ConnectionState::Disconnected == storage.state && storage.refcount == 0 {
292                storage.events.clear();
293                storage.reassembly.clear();
294                storage.state = ConnectionState::Connecting;
295                storage.link_credits = default_credits;
296                // Default ATT MTU is 23
297                storage.att_mtu = 23;
298                storage.handle.replace(handle);
299                storage.peer_addr_kind.replace(peer_addr_kind);
300                storage.peer_identity.replace(Identity {
301                    bd_addr: peer_addr,
302                    #[cfg(feature = "security")]
303                    irk: None,
304                });
305                storage.role.replace(role);
306
307                match role {
308                    LeConnRole::Central => {
309                        state.central_waker.wake();
310                    }
311                    LeConnRole::Peripheral => {
312                        state.peripheral_waker.wake();
313                    }
314                }
315                return Ok(());
316            }
317        }
318        warn!("[link][connect] no available slot found for handle {:?}", handle);
319        Err(Error::NotFound)
320    }
321
322    pub(crate) fn poll_accept(
323        &'d self,
324        role: LeConnRole,
325        peers: &[(AddrKind, &BdAddr)],
326        cx: Option<&mut Context<'_>>,
327    ) -> Poll<Connection<'d, P>> {
328        let mut state = self.state.borrow_mut();
329        if let Some(cx) = cx {
330            match role {
331                LeConnRole::Central => {
332                    state.central_waker.register(cx.waker());
333                }
334                LeConnRole::Peripheral => {
335                    state.peripheral_waker.register(cx.waker());
336                }
337            }
338        }
339        for (idx, storage) in state.connections.iter_mut().enumerate() {
340            if let ConnectionState::Connecting = storage.state {
341                let handle = storage.handle.unwrap();
342                let r = storage.role.unwrap();
343                if r == role {
344                    if !peers.is_empty() {
345                        for peer in peers.iter() {
346                            // TODO: Accept advertsing peers which use IRK
347                            if storage.peer_addr_kind.unwrap() == peer.0
348                                && storage.peer_identity.unwrap().bd_addr == *peer.1
349                            {
350                                storage.state = ConnectionState::Connected;
351                                debug!("[link][poll_accept] connection accepted: state: {:?}", storage);
352                                assert_eq!(storage.refcount, 0);
353                                state.inc_ref(idx as u8);
354                                return Poll::Ready(Connection::new(idx as u8, self));
355                            }
356                        }
357                    } else {
358                        storage.state = ConnectionState::Connected;
359                        assert_eq!(storage.refcount, 0);
360                        debug!("[link][poll_accept] connection accepted: state: {:?}", storage);
361
362                        assert_eq!(storage.refcount, 0);
363                        state.inc_ref(idx as u8);
364                        return Poll::Ready(Connection::new(idx as u8, self));
365                    }
366                }
367            }
368        }
369        Poll::Pending
370    }
371
372    fn with_mut<F: FnOnce(&mut State<'d, P::Packet>) -> R, R>(&self, f: F) -> R {
373        let mut state = self.state.borrow_mut();
374        f(&mut state)
375    }
376
377    pub(crate) fn log_status(&self, verbose: bool) {
378        let state = self.state.borrow();
379        state.print(verbose);
380    }
381
382    pub(crate) fn inc_ref(&self, index: u8) {
383        self.with_mut(|state| {
384            state.inc_ref(index);
385        });
386    }
387
388    pub(crate) fn dec_ref(&self, index: u8) {
389        self.with_mut(|state| {
390            let conn = &mut state.connections[index as usize];
391            conn.refcount = unwrap!(
392                conn.refcount.checked_sub(1),
393                "bug: dropping a connection with refcount 0"
394            );
395            if conn.refcount == 0 && conn.state == ConnectionState::Connected {
396                conn.state = ConnectionState::DisconnectRequest(DisconnectReason::RemoteUserTerminatedConn);
397                state.disconnect_waker.wake();
398            }
399        });
400    }
401
402    pub(crate) async fn accept(&'d self, role: LeConnRole, peers: &[(AddrKind, &BdAddr)]) -> Connection<'d, P> {
403        poll_fn(|cx| self.poll_accept(role, peers, Some(cx))).await
404    }
405
406    pub(crate) fn set_link_credits(&self, credits: usize) {
407        let mut state = self.state.borrow_mut();
408        state.default_link_credits = credits;
409        for storage in state.connections.iter_mut() {
410            storage.link_credits = credits;
411        }
412    }
413
414    pub(crate) fn set_default_att_mtu(&self, att_mtu: u16) {
415        let mut state = self.state.borrow_mut();
416        state.default_att_mtu = att_mtu;
417    }
418
419    pub(crate) fn confirm_sent(&self, handle: ConnHandle, packets: usize) -> Result<(), Error> {
420        let mut state = self.state.borrow_mut();
421        for storage in state.connections.iter_mut() {
422            match storage.state {
423                ConnectionState::Connected if handle == storage.handle.unwrap() => {
424                    storage.link_credits += packets;
425                    storage.link_credit_waker.wake();
426                    return Ok(());
427                }
428                _ => {}
429            }
430        }
431        Err(Error::NotFound)
432    }
433
434    pub(crate) fn poll_request_to_send(
435        &self,
436        handle: ConnHandle,
437        packets: usize,
438        cx: Option<&mut Context<'_>>,
439    ) -> Poll<Result<PacketGrant<'_, 'd, P::Packet>, Error>> {
440        let mut state = self.state.borrow_mut();
441        for storage in state.connections.iter_mut() {
442            match storage.state {
443                ConnectionState::Connected if storage.handle.unwrap() == handle => {
444                    if packets <= storage.link_credits {
445                        storage.link_credits -= packets;
446
447                        return Poll::Ready(Ok(PacketGrant::new(&self.state, handle, packets)));
448                    } else {
449                        if let Some(cx) = cx {
450                            storage.link_credit_waker.register(cx.waker());
451                        }
452                        #[cfg(feature = "connection-metrics")]
453                        storage.metrics.blocked_send();
454
455                        return Poll::Pending;
456                    }
457                }
458                _ => {}
459            }
460        }
461        warn!("[link][pool_request_to_send] connection {:?} not found", handle);
462        Poll::Ready(Err(Error::NotFound))
463    }
464
465    pub(crate) fn get_att_mtu(&self, index: u8) -> u16 {
466        self.with_mut(|state| state.connections[index as usize].att_mtu)
467    }
468
469    pub(crate) async fn send(&self, index: u8, pdu: Pdu<P::Packet>) {
470        let handle = self.with_mut(|state| state.connections[index as usize].handle.unwrap());
471        self.outbound.send((handle, pdu)).await
472    }
473
474    pub(crate) fn try_send(&self, index: u8, pdu: Pdu<P::Packet>) -> Result<(), Error> {
475        let handle = self.with_mut(|state| state.connections[index as usize].handle.unwrap());
476        self.outbound.try_send((handle, pdu)).map_err(|_| Error::OutOfMemory)
477    }
478
479    pub(crate) fn try_outbound(&self, handle: ConnHandle, pdu: Pdu<P::Packet>) -> Result<(), Error> {
480        self.outbound.try_send((handle, pdu)).map_err(|_| Error::OutOfMemory)
481    }
482
483    pub(crate) async fn outbound(&self) -> (ConnHandle, Pdu<P::Packet>) {
484        self.outbound.receive().await
485    }
486
487    pub(crate) fn get_att_mtu_handle(&self, conn: ConnHandle) -> u16 {
488        let mut state = self.state.borrow_mut();
489        for storage in state.connections.iter_mut() {
490            match storage.state {
491                ConnectionState::Connected if storage.handle.unwrap() == conn => {
492                    return storage.att_mtu;
493                }
494                _ => {}
495            }
496        }
497        state.default_att_mtu
498    }
499
500    pub(crate) fn exchange_att_mtu(&self, conn: ConnHandle, mtu: u16) -> u16 {
501        let mut state = self.state.borrow_mut();
502        debug!("exchange_att_mtu: {}, current default: {}", mtu, state.default_att_mtu);
503        let default_att_mtu = state.default_att_mtu;
504        for storage in state.connections.iter_mut() {
505            match storage.state {
506                ConnectionState::Connected if storage.handle.unwrap() == conn => {
507                    storage.att_mtu = default_att_mtu.min(mtu);
508                    return storage.att_mtu;
509                }
510                _ => {}
511            }
512        }
513        mtu
514    }
515
516    pub(crate) fn pass_key_confirm(&self, index: u8, confirm: bool) -> Result<(), Error> {
517        #[cfg(feature = "security")]
518        {
519            if self.state.borrow_mut().connections[index as usize].state == ConnectionState::Connected {
520                self.security_manager.handle_pass_key_confirm(
521                    confirm,
522                    self,
523                    &self.state.borrow().connections[index as usize],
524                )
525            } else {
526                Err(Error::Disconnected)
527            }
528        }
529        #[cfg(not(feature = "security"))]
530        Err(Error::NotSupported)
531    }
532
533    pub(crate) fn pass_key_input(&self, index: u8, pass_key: u32) -> Result<(), Error> {
534        #[cfg(feature = "security")]
535        {
536            if self.state.borrow_mut().connections[index as usize].state == ConnectionState::Connected {
537                self.security_manager.handle_pass_key_input(
538                    pass_key,
539                    self,
540                    &self.state.borrow().connections[index as usize],
541                )
542            } else {
543                Err(Error::Disconnected)
544            }
545        }
546        #[cfg(not(feature = "security"))]
547        Err(Error::NotSupported)
548    }
549
550    pub(crate) fn request_security(&self, index: u8) -> Result<(), Error> {
551        #[cfg(feature = "security")]
552        {
553            let current_level = self.get_security_level(index)?;
554            if current_level != SecurityLevel::NoEncryption {
555                return Err(Error::NotSupported);
556            }
557            self.security_manager
558                .initiate(self, &self.state.borrow().connections[index as usize])
559        }
560        #[cfg(not(feature = "security"))]
561        Err(Error::NotSupported)
562    }
563
564    pub(crate) fn get_security_level(&self, index: u8) -> Result<SecurityLevel, Error> {
565        let state = self.state.borrow();
566        match state.connections[index as usize].state {
567            ConnectionState::Connected => {
568                #[cfg(feature = "security")]
569                {
570                    Ok(state.connections[index as usize].security_level)
571                }
572                #[cfg(not(feature = "security"))]
573                Ok(SecurityLevel::NoEncryption)
574            }
575            _ => Err(Error::Disconnected),
576        }
577    }
578
579    pub(crate) fn get_bondable(&self, index: u8) -> Result<bool, Error> {
580        let state = self.state.borrow();
581        match state.connections[index as usize].state {
582            ConnectionState::Connected => {
583                #[cfg(feature = "security")]
584                {
585                    Ok(state.connections[index as usize].bondable)
586                }
587                #[cfg(not(feature = "security"))]
588                Ok(false)
589            }
590            _ => Err(Error::Disconnected),
591        }
592    }
593
594    pub(crate) fn set_bondable(&self, index: u8, bondable: bool) -> Result<(), Error> {
595        #[cfg(feature = "security")]
596        {
597            let mut state = self.state.borrow_mut();
598            match state.connections[index as usize].state {
599                ConnectionState::Connected => {
600                    state.connections[index as usize].bondable = bondable;
601                    Ok(())
602                }
603                _ => Err(Error::Disconnected),
604            }
605        }
606        #[cfg(not(feature = "security"))]
607        Err(Error::NotSupported)
608    }
609
610    pub(crate) fn handle_security_channel(
611        &self,
612        handle: ConnHandle,
613        pdu: Pdu<P::Packet>,
614        event_handler: &dyn EventHandler,
615    ) -> Result<(), Error> {
616        #[cfg(feature = "security")]
617        {
618            let state = self.state.borrow();
619            for storage in state.connections.iter() {
620                match storage.state {
621                    ConnectionState::Connected if storage.handle.unwrap() == handle => {
622                        if let Err(error) = self.security_manager.handle_l2cap_command(pdu, self, storage) {
623                            error!("Failed to handle security manager packet, {:?}", error);
624                            return Err(error);
625                        }
626                        break;
627                    }
628                    _ => (),
629                }
630            }
631        }
632        Ok(())
633    }
634
635    pub(crate) fn handle_security_hci_event(&self, event: bt_hci::event::EventPacket) -> Result<(), Error> {
636        #[cfg(feature = "security")]
637        {
638            self.security_manager.handle_hci_event(event, self)?;
639        }
640        Ok(())
641    }
642
643    pub(crate) fn handle_security_hci_le_event(&self, event: bt_hci::event::le::LeEventPacket) -> Result<(), Error> {
644        #[cfg(feature = "security")]
645        {
646            self.security_manager.handle_hci_le_event(event, self)?;
647        }
648        Ok(())
649    }
650
651    #[cfg(feature = "security")]
652    pub(crate) async fn handle_security_event<'h, C>(
653        &self,
654        host: &crate::host::BleHost<'h, C, P>,
655        _event: crate::security_manager::SecurityEventData,
656    ) -> Result<(), crate::BleHostError<C::Error>>
657    where
658        C: crate::ControllerCmdSync<bt_hci::cmd::le::LeLongTermKeyRequestReply>
659            + crate::ControllerCmdAsync<bt_hci::cmd::le::LeEnableEncryption>
660            + crate::ControllerCmdSync<bt_hci::cmd::link_control::Disconnect>,
661    {
662        use bt_hci::cmd::le::{LeEnableEncryption, LeLongTermKeyRequestReply};
663        use bt_hci::cmd::link_control::Disconnect;
664
665        match _event {
666            crate::security_manager::SecurityEventData::SendLongTermKey(handle) => {
667                let conn_info = self.state.borrow().connections.iter().find_map(|connection| {
668                    match (connection.handle, connection.peer_identity) {
669                        (Some(connection_handle), Some(identity)) => {
670                            if handle == connection_handle {
671                                Some((connection_handle, identity))
672                            } else {
673                                None
674                            }
675                        }
676                        (_, _) => None,
677                    }
678                });
679
680                if let Some((conn, identity)) = conn_info {
681                    if let Some(ltk) = self.security_manager.get_peer_long_term_key(&identity) {
682                        let _ = host
683                            .command(LeLongTermKeyRequestReply::new(handle, ltk.to_le_bytes()))
684                            .await?;
685                    } else {
686                        warn!("[host] Long term key request reply failed, no long term key");
687                        // Send disconnect event to the controller
688                        host.command(Disconnect::new(conn, DisconnectReason::AuthenticationFailure))
689                            .await?;
690                        unwrap!(self.disconnected(conn, Status::AUTHENTICATION_FAILURE));
691                    }
692                } else {
693                    warn!("[host] Long term key request reply failed, unknown peer")
694                }
695            }
696            crate::security_manager::SecurityEventData::EnableEncryption(handle, bond_info) => {
697                let connection_data =
698                    self.state
699                        .borrow()
700                        .connections
701                        .iter()
702                        .enumerate()
703                        .find_map(
704                            |(index, connection)| match (connection.handle, connection.peer_identity) {
705                                (Some(connection_handle), Some(identity)) => {
706                                    if handle == connection_handle {
707                                        Some((index, connection.role, identity))
708                                    } else {
709                                        None
710                                    }
711                                }
712                                (_, _) => None,
713                            },
714                        );
715                if let Some((index, role, identity)) = connection_data {
716                    if let Some(ltk) = self.security_manager.get_peer_long_term_key(&identity) {
717                        if let Some(LeConnRole::Central) = role {
718                            host.async_command(LeEnableEncryption::new(handle, [0; 8], 0, ltk.to_le_bytes()))
719                                .await?;
720                        }
721                    } else {
722                        warn!("[host] Enable encryption failed, no long term key")
723                    }
724                } else {
725                    warn!("[host] Enable encryption failed, unknown peer")
726                }
727            }
728            crate::security_manager::SecurityEventData::Timeout => {
729                warn!("[host] Pairing timeout");
730                self.security_manager.cancel_timeout();
731            }
732            crate::security_manager::SecurityEventData::TimerChange => (),
733        }
734        Ok(())
735    }
736
737    #[cfg(feature = "security")]
738    pub(crate) fn poll_security_events(
739        &self,
740    ) -> impl Future<Output = Result<SecurityEventData, TimeoutError>> + use<'_, P> {
741        self.security_manager.poll_events()
742    }
743
744    #[cfg(feature = "connection-metrics")]
745    pub(crate) fn metrics<F: FnOnce(&Metrics) -> R, R>(&self, index: u8, f: F) -> R {
746        self.with_mut(|state| {
747            let state = &state.connections[index as usize];
748            f(&state.metrics)
749        })
750    }
751}
752
753pub struct DisconnectRequest<'a, 'd, P> {
754    index: usize,
755    handle: ConnHandle,
756    reason: DisconnectReason,
757    state: &'a RefCell<State<'d, P>>,
758}
759
760impl<P> DisconnectRequest<'_, '_, P> {
761    pub fn handle(&self) -> ConnHandle {
762        self.handle
763    }
764
765    pub fn reason(&self) -> DisconnectReason {
766        self.reason
767    }
768
769    pub fn confirm(self) {
770        let mut state = self.state.borrow_mut();
771        state.connections[self.index].state = ConnectionState::Disconnecting(self.reason);
772    }
773}
774pub struct ConnectionStorage<P> {
775    pub state: ConnectionState,
776    pub handle: Option<ConnHandle>,
777    pub role: Option<LeConnRole>,
778    pub peer_addr_kind: Option<AddrKind>,
779    pub peer_identity: Option<Identity>,
780    pub att_mtu: u16,
781    pub link_credits: usize,
782    pub link_credit_waker: WakerRegistration,
783    pub refcount: u8,
784    #[cfg(feature = "connection-metrics")]
785    pub metrics: Metrics,
786    #[cfg(feature = "security")]
787    pub security_level: SecurityLevel,
788    #[cfg(feature = "security")]
789    pub bondable: bool,
790    pub events: EventChannel,
791    pub reassembly: PacketReassembly<P>,
792    #[cfg(feature = "gatt")]
793    pub gatt: GattChannel<P>,
794}
795
796/// Connection metrics
797#[cfg(feature = "connection-metrics")]
798#[derive(Debug)]
799pub struct Metrics {
800    /// Number of ACL packets sent for this connection.
801    pub num_sent: usize,
802    /// Number of ACL packets received on this connection.
803    pub num_received: usize,
804    /// Time of last sent packet.
805    pub last_sent: embassy_time::Instant,
806    /// Time of last received packet.
807    pub last_received: embassy_time::Instant,
808    /// Number of times a sender was blocked from sending.
809    pub blocked_sends: usize,
810}
811
812#[cfg(feature = "connection-metrics")]
813impl Metrics {
814    pub(crate) const fn new() -> Self {
815        Self {
816            num_sent: 0,
817            num_received: 0,
818            last_sent: embassy_time::Instant::MIN,
819            last_received: embassy_time::Instant::MIN,
820            blocked_sends: 0,
821        }
822    }
823    pub(crate) fn sent(&mut self, num: usize) {
824        self.num_sent = self.num_sent.wrapping_add(num);
825        self.last_sent = embassy_time::Instant::now();
826    }
827
828    pub(crate) fn received(&mut self, num: usize) {
829        self.num_received = self.num_received.wrapping_add(num);
830        self.last_received = embassy_time::Instant::now();
831    }
832
833    pub(crate) fn blocked_send(&mut self) {
834        self.blocked_sends = self.blocked_sends.wrapping_add(1);
835    }
836
837    pub(crate) fn reset(&mut self) {
838        *self = Self::new();
839    }
840}
841
842#[cfg(feature = "connection-metrics")]
843#[cfg(feature = "defmt")]
844impl defmt::Format for Metrics {
845    fn format(&self, f: defmt::Formatter<'_>) {
846        defmt::write!(
847            f,
848            "sent = {}, since_sent = {} ms, recvd = {}, since_recvd = {} ms, blocked sends = {}",
849            self.num_sent,
850            self.last_sent.elapsed().as_millis(),
851            self.num_received,
852            self.last_received.elapsed().as_millis(),
853            self.blocked_sends,
854        );
855    }
856}
857
858impl<P> ConnectionStorage<P> {
859    pub(crate) const fn new() -> ConnectionStorage<P> {
860        ConnectionStorage {
861            state: ConnectionState::Disconnected,
862            handle: None,
863            role: None,
864            peer_addr_kind: None,
865            peer_identity: None,
866            att_mtu: 23,
867            link_credits: 0,
868            link_credit_waker: WakerRegistration::new(),
869            refcount: 0,
870            #[cfg(feature = "connection-metrics")]
871            metrics: Metrics::new(),
872            #[cfg(feature = "security")]
873            security_level: SecurityLevel::NoEncryption,
874            events: EventChannel::new(),
875            #[cfg(feature = "gatt")]
876            gatt: GattChannel::new(),
877            reassembly: PacketReassembly::new(),
878            #[cfg(feature = "security")]
879            bondable: false,
880        }
881    }
882}
883
884impl<P> core::fmt::Debug for ConnectionStorage<P> {
885    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
886        let mut d = f.debug_struct("ConnectionStorage");
887        let d = d
888            .field("state", &self.state)
889            .field("handle", &self.handle)
890            .field("role", &self.role)
891            .field("peer_identity", &self.peer_identity)
892            .field("refcount", &self.refcount);
893        #[cfg(feature = "connection-metrics")]
894        let d = d.field("metrics", &self.metrics);
895        d.finish()
896    }
897}
898
899#[cfg(feature = "defmt")]
900impl<P> defmt::Format for ConnectionStorage<P> {
901    fn format(&self, f: defmt::Formatter<'_>) {
902        defmt::write!(
903            f,
904            "state = {}, conn = {}, flow = {}",
905            self.state,
906            self.handle,
907            self.link_credits,
908        );
909
910        defmt::write!(
911            f,
912            ", role = {}, peer = {}, ref = {}, sar = {}",
913            self.role,
914            self.peer_identity,
915            self.refcount,
916            self.reassembly,
917        );
918
919        #[cfg(feature = "connection-metrics")]
920        defmt::write!(f, ", {}", self.metrics);
921    }
922}
923
924#[derive(Debug, PartialEq)]
925#[cfg_attr(feature = "defmt", derive(defmt::Format))]
926pub enum ConnectionState {
927    DisconnectRequest(DisconnectReason),
928    Disconnecting(DisconnectReason),
929    Disconnected,
930    Connecting,
931    Connected,
932}
933
934pub struct PacketGrant<'a, 'd, P> {
935    state: &'a RefCell<State<'d, P>>,
936    handle: ConnHandle,
937    packets: usize,
938}
939
940impl<'a, 'd, P> PacketGrant<'a, 'd, P> {
941    fn new(state: &'a RefCell<State<'d, P>>, handle: ConnHandle, packets: usize) -> Self {
942        Self { state, handle, packets }
943    }
944
945    pub(crate) fn confirm(&mut self, sent: usize) {
946        self.packets = self.packets.saturating_sub(sent);
947        #[cfg(feature = "connection-metrics")]
948        {
949            let mut state = self.state.borrow_mut();
950            for storage in state.connections.iter_mut() {
951                match storage.state {
952                    ConnectionState::Connected if self.handle == storage.handle.unwrap() => {
953                        storage.metrics.sent(sent);
954                        break;
955                    }
956                    _ => {}
957                }
958            }
959        }
960    }
961}
962
963impl<P> Drop for PacketGrant<'_, '_, P> {
964    fn drop(&mut self) {
965        if self.packets > 0 {
966            let mut state = self.state.borrow_mut();
967            for storage in state.connections.iter_mut() {
968                match storage.state {
969                    ConnectionState::Connected if self.handle == storage.handle.unwrap() => {
970                        storage.link_credits += self.packets;
971                        storage.link_credit_waker.wake();
972                        return;
973                    }
974                    _ => {}
975                }
976            }
977            // make it an assert?
978            warn!("[link] connection {:?} not found", self.handle);
979        }
980    }
981}
982
983#[cfg(test)]
984pub(crate) mod tests {
985    use super::*;
986    extern crate std;
987
988    use std::boxed::Box;
989
990    use embassy_futures::block_on;
991
992    use crate::prelude::*;
993
994    pub const ADDR_1: [u8; 6] = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66];
995    pub const ADDR_2: [u8; 6] = [0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff];
996
997    pub fn setup() -> &'static ConnectionManager<'static, DefaultPacketPool> {
998        let storage = Box::leak(Box::new([const { ConnectionStorage::new() }; 3]));
999        let mgr = ConnectionManager::new(&mut storage[..], 23);
1000        Box::leak(Box::new(mgr))
1001    }
1002
1003    #[test]
1004    fn peripheral_connection_established() {
1005        let mgr = setup();
1006        assert!(mgr.poll_accept(LeConnRole::Peripheral, &[], None).is_pending());
1007
1008        unwrap!(mgr.connect(
1009            ConnHandle::new(0),
1010            AddrKind::RANDOM,
1011            BdAddr::new(ADDR_1),
1012            LeConnRole::Peripheral
1013        ));
1014
1015        let Poll::Ready(handle) = mgr.poll_accept(LeConnRole::Peripheral, &[], None) else {
1016            panic!("expected connection to be accepted");
1017        };
1018        assert_eq!(handle.role(), LeConnRole::Peripheral);
1019        assert_eq!(handle.peer_address(), BdAddr::new(ADDR_1));
1020
1021        handle.disconnect();
1022    }
1023
1024    #[test]
1025    fn central_connection_established() {
1026        let mgr = setup();
1027
1028        assert!(mgr.poll_accept(LeConnRole::Central, &[], None).is_pending());
1029
1030        unwrap!(mgr.connect(
1031            ConnHandle::new(0),
1032            AddrKind::RANDOM,
1033            BdAddr::new(ADDR_2),
1034            LeConnRole::Central
1035        ));
1036
1037        let Poll::Ready(handle) = mgr.poll_accept(LeConnRole::Central, &[], None) else {
1038            panic!("expected connection to be accepted");
1039        };
1040        assert_eq!(handle.role(), LeConnRole::Central);
1041        assert_eq!(handle.peer_address(), BdAddr::new(ADDR_2));
1042    }
1043
1044    #[test]
1045    fn controller_disconnects_before_host() {
1046        let mgr = setup();
1047
1048        unwrap!(mgr.connect(
1049            ConnHandle::new(3),
1050            AddrKind::RANDOM,
1051            BdAddr::new(ADDR_1),
1052            LeConnRole::Central
1053        ));
1054
1055        unwrap!(mgr.connect(
1056            ConnHandle::new(2),
1057            AddrKind::RANDOM,
1058            BdAddr::new(ADDR_2),
1059            LeConnRole::Peripheral
1060        ));
1061
1062        let Poll::Ready(central) = mgr.poll_accept(LeConnRole::Central, &[], None) else {
1063            panic!("expected connection to be accepted");
1064        };
1065
1066        let Poll::Ready(peripheral) = mgr.poll_accept(LeConnRole::Peripheral, &[], None) else {
1067            panic!("expected connection to be accepted");
1068        };
1069
1070        assert_eq!(ConnHandle::new(3), central.handle());
1071        assert_eq!(ConnHandle::new(2), peripheral.handle());
1072
1073        // Disconnect request from us
1074        peripheral.disconnect();
1075
1076        // Polling should return the disconnecting handle
1077        let Poll::Ready(req) = mgr.poll_disconnecting(None) else {
1078            panic!("expected connection to be accepted");
1079        };
1080
1081        // If nothing happens, polling should behave the same way
1082        let Poll::Ready(req) = mgr.poll_disconnecting(None) else {
1083            panic!("expected connection to be accepted");
1084        };
1085
1086        // Disconnection event from host arrives before we confirm
1087        unwrap!(mgr.disconnected(ConnHandle::new(2), Status::UNSPECIFIED));
1088
1089        // This should be a noop
1090        req.confirm();
1091
1092        // Polling should not return anything
1093        assert!(mgr.poll_disconnecting(None).is_pending());
1094    }
1095
1096    #[test]
1097    fn controller_disconnects_after_host() {
1098        let mgr = setup();
1099
1100        unwrap!(mgr.connect(
1101            ConnHandle::new(3),
1102            AddrKind::RANDOM,
1103            BdAddr::new(ADDR_1),
1104            LeConnRole::Central
1105        ));
1106
1107        unwrap!(mgr.connect(
1108            ConnHandle::new(2),
1109            AddrKind::RANDOM,
1110            BdAddr::new(ADDR_2),
1111            LeConnRole::Peripheral
1112        ));
1113
1114        let Poll::Ready(central) = mgr.poll_accept(LeConnRole::Central, &[], None) else {
1115            panic!("expected connection to be accepted");
1116        };
1117
1118        let Poll::Ready(peripheral) = mgr.poll_accept(LeConnRole::Peripheral, &[], None) else {
1119            panic!("expected connection to be accepted");
1120        };
1121
1122        assert_eq!(ConnHandle::new(3), central.handle());
1123        assert_eq!(ConnHandle::new(2), peripheral.handle());
1124
1125        // Disconnect request from us
1126        peripheral.disconnect();
1127
1128        // Polling should return the disconnecting handle
1129        let Poll::Ready(req) = mgr.poll_disconnecting(None) else {
1130            panic!("expected connection to be accepted");
1131        };
1132
1133        // This should remove it from the list
1134        req.confirm();
1135
1136        // Polling should not return anything
1137        assert!(mgr.poll_disconnecting(None).is_pending());
1138
1139        // Disconnection event from host arrives before we confirm
1140        unwrap!(mgr.disconnected(ConnHandle::new(2), Status::UNSPECIFIED));
1141
1142        // Check that we get an event
1143        use crate::connection::ConnectionEvent;
1144        assert!(matches!(
1145            block_on(peripheral.next()),
1146            ConnectionEvent::Disconnected {
1147                reason: Status::UNSPECIFIED
1148            }
1149        ));
1150
1151        // Polling should not return anything
1152        assert!(mgr.poll_disconnecting(None).is_pending());
1153    }
1154
1155    #[test]
1156    fn referenced_handle_not_reused() {
1157        let mgr = setup();
1158
1159        assert!(mgr.poll_accept(LeConnRole::Peripheral, &[], None).is_pending());
1160
1161        let handle = ConnHandle::new(42);
1162        unwrap!(mgr.connect(handle, AddrKind::RANDOM, BdAddr::new(ADDR_1), LeConnRole::Peripheral));
1163
1164        let Poll::Ready(conn) = mgr.poll_accept(LeConnRole::Peripheral, &[], None) else {
1165            panic!("expected connection to be accepted");
1166        };
1167        assert_eq!(conn.role(), LeConnRole::Peripheral);
1168        assert_eq!(conn.peer_address(), BdAddr::new(ADDR_1));
1169
1170        unwrap!(mgr.disconnected(handle, Status::UNSPECIFIED));
1171
1172        // New incoming connection reusing handle
1173        let handle = ConnHandle::new(42);
1174        unwrap!(mgr.connect(handle, AddrKind::RANDOM, BdAddr::new(ADDR_2), LeConnRole::Peripheral));
1175
1176        let Poll::Ready(conn2) = mgr.poll_accept(LeConnRole::Peripheral, &[], None) else {
1177            panic!("expected connection to be accepted");
1178        };
1179
1180        // Ensure existing connection doesnt panic things
1181        assert_eq!(conn.handle(), ConnHandle::new(42));
1182        assert_eq!(conn.role(), LeConnRole::Peripheral);
1183        assert_eq!(conn.peer_address(), BdAddr::new(ADDR_1));
1184        assert!(!conn.is_connected());
1185
1186        assert_eq!(conn2.handle(), ConnHandle::new(42));
1187        assert_eq!(conn2.role(), LeConnRole::Peripheral);
1188        assert_eq!(conn2.peer_address(), BdAddr::new(ADDR_2));
1189        assert!(conn2.is_connected());
1190    }
1191
1192    #[test]
1193    fn disconnect_correct_handle() {
1194        let mgr = setup();
1195
1196        assert!(mgr.poll_accept(LeConnRole::Peripheral, &[], None).is_pending());
1197
1198        let handle = ConnHandle::new(42);
1199        unwrap!(mgr.connect(handle, AddrKind::RANDOM, BdAddr::new(ADDR_1), LeConnRole::Peripheral));
1200
1201        let Poll::Ready(conn) = mgr.poll_accept(LeConnRole::Peripheral, &[], None) else {
1202            panic!("expected connection to be accepted");
1203        };
1204        assert_eq!(conn.role(), LeConnRole::Peripheral);
1205        assert_eq!(conn.peer_address(), BdAddr::new(ADDR_1));
1206
1207        unwrap!(mgr.disconnected(handle, Status::UNSPECIFIED));
1208
1209        // New incoming connection reusing handle
1210        let handle = ConnHandle::new(42);
1211        unwrap!(mgr.connect(handle, AddrKind::RANDOM, BdAddr::new(ADDR_2), LeConnRole::Peripheral));
1212
1213        let Poll::Ready(conn2) = mgr.poll_accept(LeConnRole::Peripheral, &[], None) else {
1214            panic!("expected connection to be accepted");
1215        };
1216
1217        assert_eq!(conn2.handle(), ConnHandle::new(42));
1218        assert_eq!(conn2.role(), LeConnRole::Peripheral);
1219        assert_eq!(conn2.peer_address(), BdAddr::new(ADDR_2));
1220        assert!(conn2.is_connected());
1221
1222        unwrap!(mgr.disconnected(handle, Status::UNSPECIFIED));
1223
1224        assert!(!conn2.is_connected());
1225    }
1226
1227    #[test]
1228    fn disconnecting_iterator_invalid() {
1229        let mgr = setup();
1230
1231        assert!(mgr.poll_accept(LeConnRole::Peripheral, &[], None).is_pending());
1232
1233        unwrap!(mgr.connect(
1234            ConnHandle::new(3),
1235            AddrKind::RANDOM,
1236            BdAddr::new(ADDR_1),
1237            LeConnRole::Peripheral
1238        ));
1239
1240        let Poll::Ready(handle) = mgr.poll_accept(LeConnRole::Peripheral, &[], None) else {
1241            panic!("expected connection to be accepted");
1242        };
1243        assert_eq!(handle.role(), LeConnRole::Peripheral);
1244        assert_eq!(handle.peer_address(), BdAddr::new(ADDR_1));
1245
1246        assert!(mgr.poll_disconnecting(None).is_pending());
1247
1248        // Disconnect request from us
1249        drop(handle);
1250
1251        // Polling should return the disconnecting handle
1252        let Poll::Ready(req) = mgr.poll_disconnecting(None) else {
1253            panic!("expected connection to be accepted");
1254        };
1255
1256        //        unwrap!(mgr.disconnected(ConnHandle::new(3)));
1257
1258        req.confirm();
1259
1260        assert!(mgr.poll_disconnecting(None).is_pending());
1261    }
1262
1263    #[test]
1264    fn nonexisting_handle_is_disconnected() {
1265        let mgr = setup();
1266
1267        assert!(!mgr.is_handle_connected(ConnHandle::new(5)));
1268
1269        unwrap!(mgr.connect(
1270            ConnHandle::new(3),
1271            AddrKind::RANDOM,
1272            BdAddr::new(ADDR_1),
1273            LeConnRole::Peripheral
1274        ));
1275
1276        assert!(mgr.is_handle_connected(ConnHandle::new(3)));
1277
1278        let Poll::Ready(handle) = mgr.poll_accept(LeConnRole::Peripheral, &[], None) else {
1279            panic!("expected connection to be accepted");
1280        };
1281
1282        assert!(mgr.is_handle_connected(ConnHandle::new(3)));
1283
1284        handle.disconnect();
1285
1286        assert!(!mgr.is_handle_connected(ConnHandle::new(3)));
1287    }
1288}