1use bt_common::core::{Address, AddressType};
6use futures::channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};
7use futures::future::{ready, Ready};
8use futures::stream::{FusedStream, Stream};
9use parking_lot::Mutex;
10use std::collections::{HashMap, HashSet, VecDeque};
11use std::sync::Arc;
12use std::task::{Poll, Waker};
13
14use bt_common::{PeerId, Uuid};
15
16use crate::central::ScanResult;
17use crate::client::CharacteristicNotification;
18
19use crate::periodic_advertising::{PeriodicAdvertising, SyncReport};
20use crate::pii::GetPeerAddr;
21use crate::server::{
22 self, LocalService, NotificationType, ReadResponder, ServiceDefinition, WriteResponder,
23};
24use crate::{types::*, GattTypes, ServerTypes};
25
26#[derive(Default)]
27struct FakePeerServiceInner {
28 notifiers: HashMap<Handle, UnboundedSender<Result<CharacteristicNotification>>>,
30
31 characteristics: HashMap<Handle, (Characteristic, Vec<u8>)>,
34}
35
36#[derive(Clone)]
37pub struct FakePeerService {
38 inner: Arc<Mutex<FakePeerServiceInner>>,
39}
40
41impl FakePeerService {
42 pub fn new() -> Self {
43 Self { inner: Arc::new(Mutex::new(Default::default())) }
44 }
45
46 pub fn add_characteristic(&mut self, char: Characteristic, value: Vec<u8>) {
50 let mut lock = self.inner.lock();
51 let handle = char.handle;
52 lock.characteristics.insert(handle, (char, value.clone()));
53 if let Some(notifier) = lock.notifiers.get_mut(&handle) {
54 notifier
55 .unbounded_send(Ok(CharacteristicNotification {
56 handle,
57 value,
58 maybe_truncated: false,
59 }))
60 .expect("should succeed");
61 }
62 }
63
64 pub fn expect_characteristic_value(&mut self, handle: &Handle, value: Vec<u8>) {
67 let mut lock = self.inner.lock();
68 let Some(char) = lock.characteristics.get_mut(handle) else {
69 panic!("Can't find characteristic {handle:?} to set expected value");
70 };
71 char.1 = value;
72 }
73
74 pub fn notify(&self, handle: &Handle, notification: Result<CharacteristicNotification>) {
76 let mut lock = self.inner.lock();
77 if let Some(notifier) = lock.notifiers.get_mut(handle) {
78 notifier.unbounded_send(notification).expect("can send notification");
79 }
80 }
81
82 pub fn clear_notifier(&self, handle: &Handle) {
85 let mut lock = self.inner.lock();
86 let _ = lock.notifiers.remove(handle);
87 }
88}
89
90impl crate::client::PeerService<FakeTypes> for FakePeerService {
91 fn discover_characteristics(
92 &self,
93 uuid: Option<Uuid>,
94 ) -> <FakeTypes as GattTypes>::CharacteristicDiscoveryFut {
95 let lock = self.inner.lock();
96 let mut result = Vec::new();
97 for (_handle, (char, _value)) in &lock.characteristics {
98 match uuid {
99 Some(uuid) if uuid == char.uuid => result.push(char.clone()),
100 None => result.push(char.clone()),
101 _ => {}
102 }
103 }
104 ready(Ok(result))
105 }
106
107 fn read_characteristic<'a>(
108 &self,
109 handle: &Handle,
110 _offset: u16,
111 buf: &'a mut [u8],
112 ) -> <FakeTypes as GattTypes>::ReadFut<'a> {
113 let read_characteristics = &(*self.inner.lock()).characteristics;
114 let Some((_, value)) = read_characteristics.get(handle) else {
115 return ready(Err(Error::Gatt(GattError::InvalidHandle)));
116 };
117 buf[..value.len()].copy_from_slice(value.as_slice());
118 ready(Ok((value.len(), false)))
119 }
120
121 fn write_characteristic<'a>(
124 &self,
125 handle: &Handle,
126 _mode: WriteMode,
127 _offset: u16,
128 buf: &'a [u8],
129 ) -> <FakeTypes as GattTypes>::WriteFut<'a> {
130 let expected_characteristics = &(*self.inner.lock()).characteristics;
131 let Some((_, expected)) = expected_characteristics.get(handle) else {
133 panic!("Write operation to characteristic {handle:?} was not expected");
134 };
135 if buf.len() != expected.len() || &buf[..expected.len()] != expected.as_slice() {
137 panic!("Value written to characteristic {handle:?} was not expected: {buf:?}");
138 }
139 ready(Ok(()))
140 }
141
142 fn read_descriptor<'a>(
143 &self,
144 _handle: &Handle,
145 _offset: u16,
146 _buf: &'a mut [u8],
147 ) -> <FakeTypes as GattTypes>::ReadFut<'a> {
148 todo!()
149 }
150
151 fn write_descriptor<'a>(
152 &self,
153 _handle: &Handle,
154 _offset: u16,
155 _buf: &'a [u8],
156 ) -> <FakeTypes as GattTypes>::WriteFut<'a> {
157 todo!()
158 }
159
160 fn subscribe(&self, handle: &Handle) -> <FakeTypes as GattTypes>::NotificationStream {
161 let (sender, receiver) = unbounded();
162 (*self.inner.lock()).notifiers.insert(*handle, sender);
163 receiver
164 }
165}
166
167#[derive(Clone)]
168pub struct FakeServiceHandle {
169 pub uuid: Uuid,
170 pub is_primary: bool,
171 pub fake_service: FakePeerService,
172}
173
174impl crate::client::PeerServiceHandle<FakeTypes> for FakeServiceHandle {
175 fn uuid(&self) -> Uuid {
176 self.uuid
177 }
178
179 fn is_primary(&self) -> bool {
180 self.is_primary
181 }
182
183 fn connect(&self) -> <FakeTypes as GattTypes>::ServiceConnectFut {
184 futures::future::ready(Ok(self.fake_service.clone()))
185 }
186}
187
188#[derive(Default)]
189struct FakeClientInner {
190 fake_services: Vec<FakeServiceHandle>,
191}
192
193#[derive(Clone)]
194pub struct FakeClient {
195 inner: Arc<Mutex<FakeClientInner>>,
196}
197
198impl FakeClient {
199 pub fn new() -> Self {
200 FakeClient { inner: Arc::new(Mutex::new(FakeClientInner::default())) }
201 }
202
203 pub fn add_service(&mut self, uuid: Uuid, is_primary: bool, fake_service: FakePeerService) {
205 self.inner.lock().fake_services.push(FakeServiceHandle { uuid, is_primary, fake_service });
206 }
207}
208
209impl crate::Client<FakeTypes> for FakeClient {
210 fn peer_id(&self) -> PeerId {
211 todo!()
212 }
213
214 fn find_service(&self, uuid: Uuid) -> <FakeTypes as GattTypes>::FindServicesFut {
215 let fake_services = &self.inner.lock().fake_services;
216 let mut filtered_services = Vec::new();
217 for handle in fake_services {
218 if handle.uuid == uuid {
219 filtered_services.push(handle.clone());
220 }
221 }
222
223 futures::future::ready(Ok(filtered_services))
224 }
225}
226
227#[derive(Default, Debug)]
228struct ScannedResultStreamInner {
229 results: VecDeque<Result<ScanResult>>,
230 waker: Option<Waker>,
231}
232
233#[derive(Clone, Debug, Default)]
234pub struct ScannedResultStreamController(Arc<Mutex<ScannedResultStreamInner>>);
235
236impl ScannedResultStreamController {
237 pub fn add_scanned_result(&self, item: Result<ScanResult>) {
239 let mut lock = self.0.lock();
240 lock.results.push_back(item);
241 if let Some(waker) = lock.waker.take() {
242 waker.wake();
243 }
244 }
245}
246
247#[derive(Debug, Default)]
248pub struct ScannedResultStream {
249 inner: Arc<Mutex<ScannedResultStreamInner>>,
250}
251
252impl ScannedResultStream {
253 pub fn new() -> Self {
257 Self::default()
258 }
259
260 pub fn controller(&self) -> ScannedResultStreamController {
261 ScannedResultStreamController(self.inner.clone())
262 }
263}
264
265impl FusedStream for ScannedResultStream {
266 fn is_terminated(&self) -> bool {
267 self.inner.lock().results.is_empty()
268 }
269}
270
271impl Stream for ScannedResultStream {
272 type Item = Result<ScanResult>;
273
274 fn poll_next(
275 self: std::pin::Pin<&mut Self>,
276 cx: &mut std::task::Context<'_>,
277 ) -> Poll<Option<Self::Item>> {
278 let mut lock = self.inner.lock();
279 match lock.results.pop_front() {
280 Some(result) => Poll::Ready(Some(result)),
281 None => {
282 lock.waker = Some(cx.waker().clone());
283 Poll::Pending
284 }
285 }
286 }
287}
288
289pub struct FakeGetPeerAddr;
292
293impl GetPeerAddr for FakeGetPeerAddr {
294 async fn get_peer_address(&self, peer_id: PeerId) -> Result<(Address, AddressType)> {
295 Ok((
296 [
297 peer_id.0 as u8,
298 ((peer_id.0 >> 8) & 0xff) as u8,
299 ((peer_id.0 >> 16) & 0xff) as u8,
300 ((peer_id.0 >> 24) & 0xff) as u8,
301 ((peer_id.0 >> 32) & 0xff) as u8,
302 ((peer_id.0 >> 48) & 0xff) as u8,
303 ],
304 AddressType::Public,
305 ))
306 }
307}
308
309pub struct FakeTypes {}
310
311impl GattTypes for FakeTypes {
312 type Central = FakeCentral;
313 type ScanResultStream = ScannedResultStream;
314 type Client = FakeClient;
315 type ConnectFuture = Ready<Result<FakeClient>>;
316 type PeerServiceHandle = FakeServiceHandle;
317 type FindServicesFut = Ready<Result<Vec<FakeServiceHandle>>>;
318 type PeerService = FakePeerService;
319 type ServiceConnectFut = Ready<Result<FakePeerService>>;
320 type CharacteristicDiscoveryFut = Ready<Result<Vec<Characteristic>>>;
321 type NotificationStream = UnboundedReceiver<Result<CharacteristicNotification>>;
322 type ReadFut<'a> = Ready<Result<(usize, bool)>>;
323 type WriteFut<'a> = Ready<Result<()>>;
324 type PeriodicAdvertising = FakePeriodicAdvertising;
325}
326
327impl ServerTypes for FakeTypes {
328 type Server = FakeServer;
329 type LocalService = FakeLocalService;
330 type LocalServiceFut = Ready<Result<FakeLocalService>>;
331 type ServiceEventStream = UnboundedReceiver<Result<server::ServiceEvent<FakeTypes>>>;
332 type ServiceWriteType = Vec<u8>;
333 type ReadResponder = FakeResponder;
334 type WriteResponder = FakeResponder;
335 type IndicateConfirmationStream = UnboundedReceiver<Result<server::ConfirmationEvent>>;
336}
337
338#[derive(Default)]
339struct FakePeriodicAdvertisingInner {
340 sync_registry: HashMap<PeerId, UnboundedSender<Result<SyncReport>>>,
341}
342
343#[derive(Clone, Default)]
344pub struct FakePeriodicAdvertising {
345 inner: Arc<Mutex<FakePeriodicAdvertisingInner>>,
346}
347
348impl FakePeriodicAdvertising {
349 pub fn new() -> Self {
350 Self::default()
351 }
352
353 pub fn get_sender(&self, peer_id: PeerId) -> Option<UnboundedSender<Result<SyncReport>>> {
354 self.inner.lock().sync_registry.get(&peer_id).cloned()
355 }
356}
357
358impl PeriodicAdvertising for FakePeriodicAdvertising {
359 type SyncFut = Ready<Result<Self::SyncStream>>;
360 type SyncStream = UnboundedReceiver<Result<SyncReport>>;
361
362 fn sync_to_advertising_reports(
363 &self,
364 peer_id: PeerId,
365 _advertising_sid: u8,
366 _config: crate::periodic_advertising::SyncConfiguration,
367 ) -> Self::SyncFut {
368 let (tx, rx) = unbounded();
369 self.inner.lock().sync_registry.insert(peer_id, tx);
370 ready(Ok(rx))
371 }
372}
373
374#[derive(Default)]
375pub struct FakeCentralInner {
376 clients: HashMap<PeerId, FakeClient>,
377 pub(crate) periodic_advertising: FakePeriodicAdvertising,
378}
379
380#[derive(Clone)]
381pub struct FakeCentral {
382 inner: Arc<Mutex<FakeCentralInner>>,
383}
384
385impl FakeCentral {
386 pub fn new() -> Self {
387 Self { inner: Arc::new(Mutex::new(FakeCentralInner::default())) }
388 }
389
390 pub fn add_client(&mut self, peer_id: PeerId, client: FakeClient) {
391 let _ = self.inner.lock().clients.insert(peer_id, client);
392 }
393}
394
395impl crate::Central<FakeTypes> for FakeCentral {
396 fn scan(&self, _filters: &[crate::central::ScanFilter]) -> ScannedResultStream {
397 ScannedResultStream::default()
398 }
399
400 fn connect(&self, peer_id: PeerId) -> <FakeTypes as GattTypes>::ConnectFuture {
401 let clients = &self.inner.lock().clients;
402 let res = match clients.get(&peer_id) {
403 Some(client) => Ok(client.clone()),
404 None => Err(Error::PeerDisconnected(peer_id)),
405 };
406 futures::future::ready(res)
407 }
408
409 fn periodic_advertising(&self) -> Result<<FakeTypes as GattTypes>::PeriodicAdvertising> {
410 Ok(self.inner.lock().periodic_advertising.clone())
411 }
412}
413
414#[derive(Debug)]
415pub enum FakeServerEvent {
416 ReadResponded {
417 service_id: server::ServiceId,
418 handle: Handle,
419 value: Result<Vec<u8>>,
420 },
421 WriteResponded {
422 service_id: server::ServiceId,
423 handle: Handle,
424 value: Result<()>,
425 },
426 Notified {
427 service_id: server::ServiceId,
428 handle: Handle,
429 value: Vec<u8>,
430 peers: Vec<PeerId>,
431 },
432 Indicated {
433 service_id: server::ServiceId,
434 handle: Handle,
435 value: Vec<u8>,
436 peers: Vec<PeerId>,
437 confirmations: UnboundedSender<Result<server::ConfirmationEvent>>,
438 },
439 Unpublished {
440 id: server::ServiceId,
441 },
442 Published {
443 id: server::ServiceId,
444 definition: ServiceDefinition,
445 },
446}
447
448#[derive(Debug)]
449struct FakeServerInner {
450 services: HashMap<server::ServiceId, ServiceDefinition>,
451 service_senders:
452 HashMap<server::ServiceId, UnboundedSender<Result<server::ServiceEvent<FakeTypes>>>>,
453 sender: UnboundedSender<FakeServerEvent>,
454 notification_peers: HashSet<PeerId>,
455 indication_peers: HashSet<PeerId>,
456 next_prepare_result: Option<Result<()>>,
457}
458
459#[derive(Clone, Debug)]
460pub struct FakeServer {
461 inner: Arc<Mutex<FakeServerInner>>,
462}
463
464impl server::Server<FakeTypes> for FakeServer {
465 fn prepare(
466 &self,
467 service: server::ServiceDefinition,
468 ) -> <FakeTypes as ServerTypes>::LocalServiceFut {
469 let mut lock = self.inner.lock();
470 if let Some(Err(e)) = lock.next_prepare_result.take() {
471 return futures::future::ready(Err(e));
472 }
473 let id = service.id();
474 lock.services.insert(id, service);
475 futures::future::ready(Ok(FakeLocalService::new(id, self.inner.clone())))
476 }
477}
478
479impl FakeServer {
480 pub fn new() -> (Self, UnboundedReceiver<FakeServerEvent>) {
481 let (sender, receiver) = futures::channel::mpsc::unbounded();
482 (
483 Self {
484 inner: Arc::new(Mutex::new(FakeServerInner {
485 services: Default::default(),
486 service_senders: Default::default(),
487 sender,
488 notification_peers: HashSet::new(),
489 indication_peers: HashSet::new(),
490 next_prepare_result: None,
491 })),
492 },
493 receiver,
494 )
495 }
496
497 pub fn set_next_prepare_result(&self, res: Result<()>) {
498 self.inner.lock().next_prepare_result = Some(res);
499 }
500
501 pub fn service(&self, id: server::ServiceId) -> Option<ServiceDefinition> {
502 self.inner.lock().services.get(&id).cloned()
503 }
504
505 pub fn incoming_write(
506 &self,
507 peer_id: PeerId,
508 id: server::ServiceId,
509 handle: Handle,
510 offset: u32,
511 value: Vec<u8>,
512 ) {
513 let sender = self.inner.lock().sender.clone();
515 self.inner
516 .lock()
517 .service_senders
518 .get(&id)
519 .unwrap()
520 .unbounded_send(Ok(server::ServiceEvent::Write {
521 peer_id,
522 handle,
523 offset,
524 value,
525 responder: FakeResponder { sender, service_id: id, handle },
526 }))
527 .unwrap();
528 }
529
530 pub fn incoming_read(
531 &self,
532 peer_id: PeerId,
533 id: server::ServiceId,
534 handle: Handle,
535 offset: u32,
536 ) {
537 let sender = self.inner.lock().sender.clone();
539 self.inner
540 .lock()
541 .service_senders
542 .get(&id)
543 .unwrap()
544 .unbounded_send(Ok(server::ServiceEvent::Read {
545 peer_id,
546 handle,
547 offset,
548 responder: FakeResponder { sender, service_id: id, handle },
549 }))
550 .unwrap();
551 }
552
553 pub fn incoming_client_configuration(
554 &self,
555 peer_id: PeerId,
556 id: server::ServiceId,
557 handle: Handle,
558 notification_type: NotificationType,
559 ) {
560 let mut inner = self.inner.lock();
561 match notification_type {
562 NotificationType::Notify => {
563 inner.notification_peers.insert(peer_id);
564 }
565 NotificationType::Indicate => {
566 inner.indication_peers.insert(peer_id);
567 }
568 NotificationType::Disable => {
569 inner.notification_peers.remove(&peer_id);
570 inner.indication_peers.remove(&peer_id);
571 }
572 }
573 inner
574 .service_senders
575 .get(&id)
576 .unwrap()
577 .unbounded_send(Ok(server::ServiceEvent::ClientConfiguration {
578 peer_id,
579 handle,
580 notification_type,
581 }))
582 .unwrap();
583 }
584}
585
586pub struct FakeLocalService {
587 id: server::ServiceId,
588 inner: Arc<Mutex<FakeServerInner>>,
589}
590
591impl FakeLocalService {
592 fn new(id: server::ServiceId, inner: Arc<Mutex<FakeServerInner>>) -> Self {
593 Self { id, inner }
594 }
595}
596
597impl Drop for FakeLocalService {
598 fn drop(&mut self) {
599 self.inner.lock().services.remove(&self.id);
600 }
601}
602
603impl LocalService<FakeTypes> for FakeLocalService {
604 fn publish(&self) -> <FakeTypes as ServerTypes>::ServiceEventStream {
605 let (sender, receiver) = futures::channel::mpsc::unbounded();
606 let _ = self.inner.lock().service_senders.insert(self.id, sender);
607 let definition = self.inner.lock().services.get(&self.id).unwrap().clone();
608 self.inner
609 .lock()
610 .sender
611 .unbounded_send(FakeServerEvent::Published { id: self.id, definition })
612 .unwrap();
613 receiver
614 }
615
616 fn notify(&self, characteristic: &Handle, data: &[u8], peers: &[PeerId]) {
617 let inner = self.inner.lock();
618 let peers_to_notify: HashSet<_> = if peers.is_empty() {
619 inner.notification_peers.clone()
620 } else {
621 peers.iter().filter(|p| inner.notification_peers.contains(p)).cloned().collect()
622 };
623
624 if !peers_to_notify.is_empty() {
625 inner
626 .sender
627 .unbounded_send(FakeServerEvent::Notified {
628 service_id: self.id,
629 handle: *characteristic,
630 value: data.into(),
631 peers: peers_to_notify.into_iter().collect(),
632 })
633 .unwrap();
634 }
635 }
636
637 fn indicate(
638 &self,
639 characteristic: &Handle,
640 data: &[u8],
641 peers: &[PeerId],
642 ) -> <FakeTypes as ServerTypes>::IndicateConfirmationStream {
643 let (sender, receiver) = futures::channel::mpsc::unbounded();
644 let inner = self.inner.lock();
645 let peers_to_indicate: HashSet<_> = if peers.is_empty() {
646 inner.indication_peers.clone()
647 } else {
648 peers.iter().filter(|p| inner.indication_peers.contains(p)).cloned().collect()
649 };
650
651 if !peers_to_indicate.is_empty() {
652 inner
653 .sender
654 .unbounded_send(FakeServerEvent::Indicated {
655 service_id: self.id,
656 handle: *characteristic,
657 value: data.into(),
658 peers: peers_to_indicate.into_iter().collect(),
659 confirmations: sender,
660 })
661 .unwrap();
662 }
663 receiver
664 }
665}
666
667pub struct FakeResponder {
668 sender: UnboundedSender<FakeServerEvent>,
669 service_id: server::ServiceId,
670 handle: Handle,
671}
672
673impl ReadResponder for FakeResponder {
674 fn respond(self, value: &[u8]) {
675 self.sender
676 .unbounded_send(FakeServerEvent::ReadResponded {
677 service_id: self.service_id,
678 handle: self.handle,
679 value: Ok(value.into()),
680 })
681 .unwrap();
682 }
683
684 fn error(self, error: GattError) {
685 self.sender
686 .unbounded_send(FakeServerEvent::ReadResponded {
687 service_id: self.service_id,
688 handle: self.handle,
689 value: Err(Error::Gatt(error)),
690 })
691 .unwrap();
692 }
693}
694
695impl WriteResponder for FakeResponder {
696 fn acknowledge(self) {
697 self.sender
698 .unbounded_send(FakeServerEvent::WriteResponded {
699 service_id: self.service_id,
700 handle: self.handle,
701 value: Ok(()),
702 })
703 .unwrap();
704 }
705
706 fn error(self, error: GattError) {
707 self.sender
708 .unbounded_send(FakeServerEvent::WriteResponded {
709 service_id: self.service_id,
710 handle: self.handle,
711 value: Err(Error::Gatt(error)),
712 })
713 .unwrap();
714 }
715}