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