1pub mod adapter;
6pub mod bluetooth;
7pub mod test;
8
9use std::borrow::ToOwned;
10use std::collections::{HashMap, HashSet};
11use std::string::String;
12use std::thread;
13use std::time::Duration;
14
15use bitflags::bitflags;
16use embedder_traits::{BluetoothDeviceDescription, EmbedderMsg, EmbedderProxy};
17use log::warn;
18use rand::{self, RngExt};
19#[cfg(not(feature = "native-bluetooth"))]
20use servo_base::generic_channel::GenericReceiver;
21use servo_base::generic_channel::{self, GenericSender};
22use servo_base::id::WebViewId;
23use servo_bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted};
24use servo_bluetooth_traits::scanfilter::{
25 BluetoothScanfilter, BluetoothScanfilterSequence, RequestDeviceoptions,
26};
27use servo_bluetooth_traits::{
28 BluetoothCharacteristicMsg, BluetoothDescriptorMsg, BluetoothDeviceMsg, BluetoothError,
29 BluetoothRequest, BluetoothResponse, BluetoothResponseResult, BluetoothResult,
30 BluetoothServiceMsg, GATTType,
31};
32use servo_config::pref;
33
34use crate::bluetooth::{
35 BluetoothAdapter, BluetoothDevice, BluetoothGATTCharacteristic, BluetoothGATTDescriptor,
36 BluetoothGATTService,
37};
38
39const MAXIMUM_TRANSACTION_TIME: u8 = 30;
42const CONNECTION_TIMEOUT_MS: u64 = 1000;
43const DISCOVERY_TIMEOUT_MS: u64 = 1500;
45
46bitflags! {
47 struct Flags: u32 {
48 const BROADCAST = 0b000000001;
49 const READ = 0b000000010;
50 const WRITE_WITHOUT_RESPONSE = 0b000000100;
51 const WRITE = 0b000001000;
52 const NOTIFY = 0b000010000;
53 const INDICATE = 0b000100000;
54 const AUTHENTICATED_SIGNED_WRITES = 0b001000000;
55 const RELIABLE_WRITE = 0b010000000;
56 const WRITABLE_AUXILIARIES = 0b100000000;
57 }
58}
59
60pub trait BluetoothThreadFactory {
61 fn new(embedder_proxy: EmbedderProxy) -> Self;
62}
63
64impl BluetoothThreadFactory for GenericSender<BluetoothRequest> {
65 #[cfg(feature = "native-bluetooth")]
66 fn new(embedder_proxy: EmbedderProxy) -> GenericSender<BluetoothRequest> {
67 let (sender, receiver) = generic_channel::channel().unwrap();
68
69 thread::Builder::new()
70 .name("Bluetooth".to_owned())
71 .spawn(move || {
72 let runtime = tokio::runtime::Builder::new_current_thread()
73 .enable_all()
74 .build()
75 .expect("Failed to create bluetooth tokio runtime");
76
77 let adapter = runtime.block_on(async {
78 if pref!(dom_bluetooth_enabled) {
79 BluetoothAdapter::new().await.ok()
80 } else {
81 BluetoothAdapter::new_mock().ok()
82 }
83 });
84
85 let (async_sender, async_receiver) = tokio::sync::mpsc::unbounded_channel();
87 thread::Builder::new()
88 .name("BluetoothTokioBridge".to_owned())
89 .spawn(move || {
90 while let Ok(message) = receiver.recv() {
91 if async_sender.send(message).is_err() {
92 break;
93 }
94 }
95 })
96 .expect("BT Tokio Bridge thread spawning failed");
97
98 let mut manager = BluetoothManager::new(adapter, embedder_proxy);
99 runtime.block_on(manager.start(async_receiver));
100 })
101 .expect("Thread spawning failed");
102 sender
103 }
104
105 #[cfg(not(feature = "native-bluetooth"))]
106 fn new(embedder_proxy: EmbedderProxy) -> GenericSender<BluetoothRequest> {
107 let (sender, receiver) = generic_channel::channel().unwrap();
108 let adapter = if pref!(dom_bluetooth_enabled) {
109 BluetoothAdapter::new()
110 } else {
111 BluetoothAdapter::new_mock()
112 }
113 .ok();
114 thread::Builder::new()
115 .name("Bluetooth".to_owned())
116 .spawn(move || {
117 BluetoothManager::new(adapter, embedder_proxy).start_sync(receiver);
118 })
119 .expect("Thread spawning failed");
120 sender
121 }
122}
123
124async fn matches_filter(device: &BluetoothDevice, filter: &BluetoothScanfilter) -> bool {
126 if filter.is_empty_or_invalid() {
127 return false;
128 }
129
130 if let Some(name) = filter.get_name() &&
132 device.get_name().await.ok() != Some(name.to_string())
133 {
134 return false;
135 }
136
137 if !filter.get_name_prefix().is_empty() {
139 if let Ok(device_name) = device.get_name().await {
140 if !device_name.starts_with(filter.get_name_prefix()) {
141 return false;
142 }
143 } else {
144 return false;
145 }
146 }
147
148 if !filter.get_services().is_empty() &&
150 let Ok(device_uuids) = device.get_uuids().await
151 {
152 for service in filter.get_services() {
153 if !device_uuids.iter().any(|x| x == service) {
154 return false;
155 }
156 }
157 }
158
159 if let Some(manufacturer_data) = filter.get_manufacturer_data() {
161 let advertised_manufacturer_data = match device.get_manufacturer_data().await {
162 Ok(data) => data,
163 Err(_) => return false,
164 };
165 for (id, (prefix, mask)) in manufacturer_data.iter() {
166 if let Some(advertised_data) = advertised_manufacturer_data.get(id) {
167 if !data_filter_matches(advertised_data, prefix, mask) {
168 return false;
169 }
170 } else {
171 return false;
172 }
173 }
174 }
175
176 if let Some(service_data) = filter.get_service_data() {
178 let advertised_service_data = match device.get_service_data().await {
179 Ok(data) => data,
180 Err(_) => return false,
181 };
182 for (uuid, (prefix, mask)) in service_data.iter() {
183 if let Some(advertised_data) = advertised_service_data.get(uuid.as_str()) {
184 if !data_filter_matches(advertised_data, prefix, mask) {
185 return false;
186 }
187 } else {
188 return false;
189 }
190 }
191 }
192
193 true
195}
196
197fn data_filter_matches(data: &[u8], prefix: &[u8], mask: &[u8]) -> bool {
199 if data.len() < prefix.len() {
202 return false;
203 }
204
205 for ((data, mask), prefix) in data.iter().zip(mask.iter()).zip(prefix.iter()) {
207 if data & mask != prefix & mask {
208 return false;
209 }
210 }
211
212 true
214}
215
216async fn matches_filters(device: &BluetoothDevice, filters: &BluetoothScanfilterSequence) -> bool {
217 if filters.has_empty_or_invalid_filter() {
218 return false;
219 }
220 for f in filters.iter() {
221 if matches_filter(device, f).await {
222 return true;
223 }
224 }
225 false
226}
227
228async fn async_sleep(duration: Duration) {
230 #[cfg(feature = "native-bluetooth")]
231 {
232 tokio::time::sleep(duration).await;
233 }
234 #[cfg(not(feature = "native-bluetooth"))]
235 {
236 thread::sleep(duration);
237 }
238}
239
240fn is_mock_adapter(adapter: &BluetoothAdapter) -> bool {
241 matches!(adapter, &BluetoothAdapter::Mock(_))
242}
243
244pub struct BluetoothManager {
245 adapter: Option<BluetoothAdapter>,
246 address_to_id: HashMap<String, String>,
247 service_to_device: HashMap<String, String>,
248 characteristic_to_service: HashMap<String, String>,
249 descriptor_to_characteristic: HashMap<String, String>,
250 cached_devices: HashMap<String, BluetoothDevice>,
251 cached_services: HashMap<String, BluetoothGATTService>,
252 cached_characteristics: HashMap<String, BluetoothGATTCharacteristic>,
253 cached_descriptors: HashMap<String, BluetoothGATTDescriptor>,
254 allowed_services: HashMap<String, HashSet<String>>,
255 embedder_proxy: EmbedderProxy,
256}
257
258impl BluetoothManager {
259 pub fn new(
260 adapter: Option<BluetoothAdapter>,
261 embedder_proxy: EmbedderProxy,
262 ) -> BluetoothManager {
263 BluetoothManager {
264 adapter,
265 address_to_id: HashMap::new(),
266 service_to_device: HashMap::new(),
267 characteristic_to_service: HashMap::new(),
268 descriptor_to_characteristic: HashMap::new(),
269 cached_devices: HashMap::new(),
270 cached_services: HashMap::new(),
271 cached_characteristics: HashMap::new(),
272 cached_descriptors: HashMap::new(),
273 allowed_services: HashMap::new(),
274 embedder_proxy,
275 }
276 }
277
278 #[cfg(feature = "native-bluetooth")]
281 async fn start(&mut self, mut rx: tokio::sync::mpsc::UnboundedReceiver<BluetoothRequest>) {
282 while let Some(msg) = rx.recv().await {
283 if self.handle_message(msg).await {
284 break;
285 }
286 }
287 }
288
289 #[cfg(not(feature = "native-bluetooth"))]
291 fn start_sync(&mut self, receiver: GenericReceiver<BluetoothRequest>) {
292 while let Ok(msg) = receiver.recv() {
295 let should_exit = futures::executor::block_on(self.handle_message(msg));
296 if should_exit {
297 break;
298 }
299 }
300 }
301
302 async fn handle_message(&mut self, msg: BluetoothRequest) -> bool {
304 match msg {
305 BluetoothRequest::RequestDevice(options, sender) => {
306 let _ = sender.send(self.request_device(options).await);
307 },
308 BluetoothRequest::GATTServerConnect(device_id, sender) => {
309 let _ = sender.send(self.gatt_server_connect(device_id).await);
310 },
311 BluetoothRequest::GATTServerDisconnect(device_id, sender) => {
312 let _ = sender.send(self.gatt_server_disconnect(device_id).await);
313 },
314 BluetoothRequest::GetGATTChildren(id, uuid, single, child_type, sender) => {
315 let _ = sender.send(self.get_gatt_children(id, uuid, single, child_type).await);
316 },
317 BluetoothRequest::ReadValue(id, sender) => {
318 let _ = sender.send(self.read_value(id).await);
319 },
320 BluetoothRequest::WriteValue(id, value, sender) => {
321 let _ = sender.send(self.write_value(id, value).await);
322 },
323 BluetoothRequest::EnableNotification(id, enable, sender) => {
324 let _ = sender.send(self.enable_notification(id, enable).await);
325 },
326 BluetoothRequest::WatchAdvertisements(id, sender) => {
327 let _ = sender.send(self.watch_advertisements(id));
328 },
329 BluetoothRequest::Test(data_set_name, sender) => {
330 let _ = sender.send(self.test(data_set_name).await);
331 },
332 BluetoothRequest::SetRepresentedToNull(
333 service_ids,
334 characteristic_ids,
335 descriptor_ids,
336 ) => self.remove_ids_from_caches(service_ids, characteristic_ids, descriptor_ids),
337 BluetoothRequest::IsRepresentedDeviceNull(id, sender) => {
338 let _ = sender.send(!self.device_is_cached(&id));
339 },
340 BluetoothRequest::GetAvailability(sender) => {
341 let _ = sender.send(self.get_availability().await);
342 },
343 BluetoothRequest::MatchesFilter(id, filters, sender) => {
344 let _ = sender.send(self.device_matches_filter(&id, &filters).await);
345 },
346 BluetoothRequest::Exit => return true,
347 }
348 false
349 }
350
351 async fn test(&mut self, data_set_name: String) -> BluetoothResult<()> {
354 self.address_to_id.clear();
355 self.service_to_device.clear();
356 self.characteristic_to_service.clear();
357 self.descriptor_to_characteristic.clear();
358 self.cached_devices.clear();
359 self.cached_services.clear();
360 self.cached_characteristics.clear();
361 self.cached_descriptors.clear();
362 self.allowed_services.clear();
363 self.adapter = BluetoothAdapter::new_mock().ok();
364 match test::test(self, data_set_name).await {
365 Ok(_) => Ok(()),
366 Err(error) => Err(BluetoothError::Type(error.to_string())),
367 }
368 }
369
370 fn remove_ids_from_caches(
371 &mut self,
372 service_ids: Vec<String>,
373 characteristic_ids: Vec<String>,
374 descriptor_ids: Vec<String>,
375 ) {
376 for id in service_ids {
377 self.cached_services.remove(&id);
378 self.service_to_device.remove(&id);
379 }
380
381 for id in characteristic_ids {
382 self.cached_characteristics.remove(&id);
383 self.characteristic_to_service.remove(&id);
384 }
385
386 for id in descriptor_ids {
387 self.cached_descriptors.remove(&id);
388 self.descriptor_to_characteristic.remove(&id);
389 }
390 }
391
392 pub async fn get_or_create_adapter(&mut self) -> Option<BluetoothAdapter> {
395 let adapter_valid = match self.adapter.as_ref() {
396 Some(a) => a.get_address().await.is_ok(),
397 None => false,
398 };
399 if !adapter_valid {
400 #[cfg(feature = "native-bluetooth")]
401 {
402 self.adapter = BluetoothAdapter::new().await.ok();
403 }
404 #[cfg(not(feature = "native-bluetooth"))]
405 {
406 self.adapter = BluetoothAdapter::new().ok();
407 }
408 }
409
410 let adapter = self.adapter.as_ref()?;
411
412 if is_mock_adapter(adapter) && !adapter.is_present().unwrap_or(false) {
413 return None;
414 }
415
416 self.adapter.clone()
417 }
418
419 async fn get_adapter(&mut self) -> BluetoothResult<BluetoothAdapter> {
420 match self.get_or_create_adapter().await {
421 Some(adapter) => {
422 if !adapter.is_powered().await.unwrap_or(false) {
423 return Err(BluetoothError::NotFound);
424 }
425 Ok(adapter)
426 },
427 None => Err(BluetoothError::NotFound),
428 }
429 }
430
431 async fn get_and_cache_devices(
434 &mut self,
435 adapter: &mut BluetoothAdapter,
436 ) -> Vec<BluetoothDevice> {
437 let devices = adapter.get_devices().await.unwrap_or_default();
438 for device in &devices {
439 if let Ok(address) = device.get_address() {
440 #[allow(clippy::map_entry)] if !self.address_to_id.contains_key(&address) {
442 let generated_id = self.generate_device_id();
443 self.address_to_id.insert(address, generated_id.clone());
444 self.cached_devices
445 .insert(generated_id.clone(), device.clone());
446 self.allowed_services.insert(generated_id, HashSet::new());
447 }
448 }
449 }
450 self.cached_devices.values().cloned().collect()
451 }
452
453 async fn get_device(
454 &mut self,
455 adapter: &mut BluetoothAdapter,
456 device_id: &str,
457 ) -> Option<&BluetoothDevice> {
458 if self.cached_devices.contains_key(device_id) {
459 return self.cached_devices.get(device_id);
460 }
461 self.get_and_cache_devices(adapter).await;
462 self.cached_devices.get(device_id)
463 }
464
465 async fn select_device(
466 &mut self,
467 webview_id: WebViewId,
468 devices: Vec<BluetoothDevice>,
469 adapter: &BluetoothAdapter,
470 ) -> Option<String> {
471 if is_mock_adapter(adapter) {
472 for device in &devices {
473 if let Ok(address) = device.get_address() {
474 return Some(address);
475 }
476 }
477 return None;
478 }
479
480 let mut device_descriptions = Vec::with_capacity(devices.len());
481 for device in devices {
482 let address = device.get_address().unwrap_or_default();
483 let name = device.get_name().await.unwrap_or_else(|_| {
484 let short = if address.len() > 8 {
485 &address[..8]
486 } else {
487 &address
488 };
489 format!("Unknown ({}...)", short)
490 });
491 device_descriptions.push(BluetoothDeviceDescription { address, name });
492 }
493
494 let (ipc_sender, ipc_receiver) =
495 generic_channel::channel().expect("Failed to create IPC channel!");
496 self.embedder_proxy
497 .send(EmbedderMsg::GetSelectedBluetoothDevice(
498 webview_id,
499 device_descriptions,
500 ipc_sender,
501 ));
502
503 match ipc_receiver.recv() {
504 Ok(result) => result,
505 Err(e) => {
506 warn!("Failed to receive files from embedder ({:?}).", e);
507 None
508 },
509 }
510 }
511
512 fn generate_device_id(&mut self) -> String {
513 let mut device_id;
514 let mut rng = rand::rng();
515 loop {
516 device_id = rng.random::<u32>().to_string();
517 if !self.cached_devices.contains_key(&device_id) {
518 break;
519 }
520 }
521 device_id
522 }
523
524 fn device_from_service_id(&self, service_id: &str) -> Option<BluetoothDevice> {
525 let device_id = self.service_to_device.get(service_id)?;
526 self.cached_devices.get(device_id).cloned()
527 }
528
529 fn device_is_cached(&self, device_id: &str) -> bool {
530 self.cached_devices.contains_key(device_id) &&
531 self.address_to_id.values().any(|v| v == device_id)
532 }
533
534 async fn device_matches_filter(
535 &mut self,
536 device_id: &str,
537 filters: &BluetoothScanfilterSequence,
538 ) -> BluetoothResult<bool> {
539 let mut adapter = self.get_adapter().await?;
540 match self.get_device(&mut adapter, device_id).await {
541 Some(device) => Ok(matches_filters(device, filters).await),
542 None => Ok(false),
543 }
544 }
545
546 async fn get_and_cache_gatt_services(
549 &mut self,
550 adapter: &mut BluetoothAdapter,
551 device_id: &str,
552 ) -> Vec<BluetoothGATTService> {
553 let mut services = match self.get_device(adapter, device_id).await {
554 Some(d) => d.get_gatt_services().await.unwrap_or_default(),
555 None => vec![],
556 };
557
558 services.retain(|s| {
559 !uuid_is_blocklisted(&s.get_uuid().unwrap_or_default(), Blocklist::All) &&
560 self.allowed_services
561 .get(device_id)
562 .is_some_and(|uuids| uuids.contains(&s.get_uuid().unwrap_or_default()))
563 });
564 for service in &services {
565 self.cached_services
566 .insert(service.get_id(), service.clone());
567 self.service_to_device
568 .insert(service.get_id(), device_id.to_owned());
569 }
570 services
571 }
572
573 async fn get_gatt_service(
574 &mut self,
575 adapter: &mut BluetoothAdapter,
576 service_id: &str,
577 ) -> Option<&BluetoothGATTService> {
578 if self.cached_services.contains_key(service_id) {
579 return self.cached_services.get(service_id);
580 }
581 let device_id = self.service_to_device.get(service_id)?.clone();
582 self.get_and_cache_gatt_services(adapter, &device_id).await;
583 self.cached_services.get(service_id)
584 }
585
586 fn service_is_cached(&self, service_id: &str) -> bool {
587 self.cached_services.contains_key(service_id) &&
588 self.service_to_device.contains_key(service_id)
589 }
590
591 async fn get_and_cache_gatt_characteristics(
594 &mut self,
595 adapter: &mut BluetoothAdapter,
596 service_id: &str,
597 ) -> Vec<BluetoothGATTCharacteristic> {
598 let mut characteristics = match self.get_gatt_service(adapter, service_id).await {
599 Some(s) => s.get_gatt_characteristics().unwrap_or_default(),
600 None => vec![],
601 };
602
603 characteristics
604 .retain(|c| !uuid_is_blocklisted(&c.get_uuid().unwrap_or_default(), Blocklist::All));
605 for characteristic in &characteristics {
606 self.cached_characteristics
607 .insert(characteristic.get_id(), characteristic.clone());
608 self.characteristic_to_service
609 .insert(characteristic.get_id(), service_id.to_owned());
610 }
611 characteristics
612 }
613
614 async fn get_gatt_characteristic(
615 &mut self,
616 adapter: &mut BluetoothAdapter,
617 characteristic_id: &str,
618 ) -> Option<&BluetoothGATTCharacteristic> {
619 if self.cached_characteristics.contains_key(characteristic_id) {
620 return self.cached_characteristics.get(characteristic_id);
621 }
622 let service_id = self
623 .characteristic_to_service
624 .get(characteristic_id)?
625 .clone();
626 self.get_and_cache_gatt_characteristics(adapter, &service_id)
627 .await;
628 self.cached_characteristics.get(characteristic_id)
629 }
630
631 fn get_characteristic_properties(&self, characteristic: &BluetoothGATTCharacteristic) -> Flags {
632 let mut props: Flags = Flags::empty();
633 let flags = characteristic.get_flags().unwrap_or_default();
634 for flag in flags {
635 match flag.as_ref() {
636 "broadcast" => props.insert(Flags::BROADCAST),
637 "read" => props.insert(Flags::READ),
638 "write-without-response" => props.insert(Flags::WRITE_WITHOUT_RESPONSE),
639 "write" => props.insert(Flags::WRITE),
640 "notify" => props.insert(Flags::NOTIFY),
641 "indicate" => props.insert(Flags::INDICATE),
642 "authenticated-signed-writes" => props.insert(Flags::AUTHENTICATED_SIGNED_WRITES),
643 "reliable-write" => props.insert(Flags::RELIABLE_WRITE),
644 "writable-auxiliaries" => props.insert(Flags::WRITABLE_AUXILIARIES),
645 _ => (),
646 }
647 }
648 props
649 }
650
651 fn characteristic_is_cached(&self, characteristic_id: &str) -> bool {
652 self.cached_characteristics.contains_key(characteristic_id) &&
653 self.characteristic_to_service
654 .contains_key(characteristic_id)
655 }
656
657 async fn get_and_cache_gatt_descriptors(
660 &mut self,
661 adapter: &mut BluetoothAdapter,
662 characteristic_id: &str,
663 ) -> Vec<BluetoothGATTDescriptor> {
664 let mut descriptors = match self
665 .get_gatt_characteristic(adapter, characteristic_id)
666 .await
667 {
668 Some(c) => c.get_gatt_descriptors().unwrap_or_default(),
669 None => vec![],
670 };
671
672 descriptors
673 .retain(|d| !uuid_is_blocklisted(&d.get_uuid().unwrap_or_default(), Blocklist::All));
674 for descriptor in &descriptors {
675 self.cached_descriptors
676 .insert(descriptor.get_id(), descriptor.clone());
677 self.descriptor_to_characteristic
678 .insert(descriptor.get_id(), characteristic_id.to_owned());
679 }
680 descriptors
681 }
682
683 async fn get_gatt_descriptor(
684 &mut self,
685 adapter: &mut BluetoothAdapter,
686 descriptor_id: &str,
687 ) -> Option<&BluetoothGATTDescriptor> {
688 if self.cached_descriptors.contains_key(descriptor_id) {
689 return self.cached_descriptors.get(descriptor_id);
690 }
691 let characteristic_id = self
692 .descriptor_to_characteristic
693 .get(descriptor_id)?
694 .clone();
695 self.get_and_cache_gatt_descriptors(adapter, &characteristic_id)
696 .await;
697 self.cached_descriptors.get(descriptor_id)
698 }
699
700 async fn request_device(&mut self, options: RequestDeviceoptions) -> BluetoothResponseResult {
704 let mut adapter = self.get_adapter().await?;
706
707 if let Ok(ref session) = adapter.create_discovery_session() {
710 if session.start_discovery().await.is_ok() && !is_mock_adapter(&adapter) {
711 async_sleep(Duration::from_millis(DISCOVERY_TIMEOUT_MS)).await;
712 }
713 let _ = session.stop_discovery().await;
714 }
715
716 let mut matched_devices = self.get_and_cache_devices(&mut adapter).await;
717
718 if !options.is_accepting_all_devices() {
720 let mut filtered = Vec::new();
721 for d in matched_devices {
722 if matches_filters(&d, options.get_filters()).await {
723 filtered.push(d);
724 }
725 }
726 matched_devices = filtered;
727 }
728
729 if let Some(address) = self
731 .select_device(options.webview_id(), matched_devices, &adapter)
732 .await
733 {
734 let device_id = match self.address_to_id.get(&address) {
735 Some(id) => id.clone(),
736 None => return Err(BluetoothError::NotFound),
737 };
738 let mut services = options.get_services_set();
739 if let Some(services_set) = self.allowed_services.get(&device_id) {
740 services = services_set | &services;
741 }
742 self.allowed_services.insert(device_id.clone(), services);
743 if let Some(device) = self.get_device(&mut adapter, &device_id).await {
744 let message = BluetoothDeviceMsg {
745 id: device_id,
746 name: device.get_name().await.ok(),
747 };
748 return Ok(BluetoothResponse::RequestDevice(message));
749 }
750 }
751 Err(BluetoothError::NotFound)
753 }
755
756 async fn gatt_server_connect(&mut self, device_id: String) -> BluetoothResponseResult {
758 if !self.device_is_cached(&device_id) {
760 return Err(BluetoothError::Network);
761 }
762 let mut adapter = self.get_adapter().await?;
763
764 match self.get_device(&mut adapter, &device_id).await {
766 Some(d) => {
767 if d.is_connected().await.unwrap_or(false) {
768 return Ok(BluetoothResponse::GATTServerConnect(true));
769 }
770 let _ = d.connect().await;
771 for _ in 0..MAXIMUM_TRANSACTION_TIME {
772 if d.is_connected().await.unwrap_or(false) {
773 return Ok(BluetoothResponse::GATTServerConnect(true));
774 } else {
775 if is_mock_adapter(&adapter) {
776 break;
777 }
778 async_sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS)).await;
779 }
780 }
782 Err(BluetoothError::Network)
784 },
785 None => Err(BluetoothError::NotFound),
786 }
787 }
788
789 async fn gatt_server_disconnect(&mut self, device_id: String) -> BluetoothResult<()> {
791 let mut adapter = self.get_adapter().await?;
792 match self.get_device(&mut adapter, &device_id).await {
793 Some(d) => {
794 if !d.is_connected().await.unwrap_or(true) {
796 return Ok(());
797 }
798 let _ = d.disconnect().await;
799 for _ in 0..MAXIMUM_TRANSACTION_TIME {
800 if d.is_connected().await.unwrap_or(true) {
801 async_sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS)).await;
802 } else {
803 return Ok(());
804 }
805 }
806 Err(BluetoothError::Network)
807 },
808 None => Err(BluetoothError::NotFound),
809 }
810 }
811
812 async fn get_gatt_children(
814 &mut self,
815 id: String,
816 uuid: Option<String>,
817 single: bool,
818 child_type: GATTType,
819 ) -> BluetoothResponseResult {
820 let mut adapter = self.get_adapter().await?;
821 match child_type {
822 GATTType::PrimaryService => {
823 if !self.device_is_cached(&id) {
825 return Err(BluetoothError::InvalidState);
826 }
827 if let Some(ref uuid) = uuid &&
829 !self
830 .allowed_services
831 .get(&id)
832 .is_some_and(|s| s.contains(uuid))
833 {
834 return Err(BluetoothError::Security);
835 }
836 let mut services = self.get_and_cache_gatt_services(&mut adapter, &id).await;
837 if let Some(uuid) = uuid {
838 services.retain(|e| e.get_uuid().unwrap_or_default() == uuid);
839 }
840 let mut services_vec = vec![];
841 for service in services {
842 if service.is_primary().unwrap_or(false) &&
843 let Ok(uuid) = service.get_uuid()
844 {
845 services_vec.push(BluetoothServiceMsg {
846 uuid,
847 is_primary: true,
848 instance_id: service.get_id(),
849 });
850 }
851 }
852
853 if services_vec.is_empty() {
855 return Err(BluetoothError::NotFound);
856 }
857
858 Ok(BluetoothResponse::GetPrimaryServices(services_vec, single))
859 },
860 GATTType::Characteristic => {
861 if !self.service_is_cached(&id) {
863 return Err(BluetoothError::InvalidState);
864 }
865 let mut characteristics = self
867 .get_and_cache_gatt_characteristics(&mut adapter, &id)
868 .await;
869 if let Some(uuid) = uuid {
870 characteristics.retain(|e| e.get_uuid().unwrap_or_default() == uuid);
871 }
872 let mut characteristics_vec = vec![];
873 for characteristic in characteristics {
874 if let Ok(uuid) = characteristic.get_uuid() {
875 let properties = self.get_characteristic_properties(&characteristic);
876 characteristics_vec.push(BluetoothCharacteristicMsg {
877 uuid,
878 instance_id: characteristic.get_id(),
879 broadcast: properties.contains(Flags::BROADCAST),
880 read: properties.contains(Flags::READ),
881 write_without_response: properties
882 .contains(Flags::WRITE_WITHOUT_RESPONSE),
883 write: properties.contains(Flags::WRITE),
884 notify: properties.contains(Flags::NOTIFY),
885 indicate: properties.contains(Flags::INDICATE),
886 authenticated_signed_writes: properties
887 .contains(Flags::AUTHENTICATED_SIGNED_WRITES),
888 reliable_write: properties.contains(Flags::RELIABLE_WRITE),
889 writable_auxiliaries: properties.contains(Flags::WRITABLE_AUXILIARIES),
890 });
891 }
892 }
893
894 if characteristics_vec.is_empty() {
896 return Err(BluetoothError::NotFound);
897 }
898
899 Ok(BluetoothResponse::GetCharacteristics(
900 characteristics_vec,
901 single,
902 ))
903 },
904 GATTType::IncludedService => {
905 if !self.service_is_cached(&id) {
907 return Err(BluetoothError::InvalidState);
908 }
909 let device = match self.device_from_service_id(&id) {
911 Some(device) => device,
912 None => return Err(BluetoothError::NotFound),
913 };
914 let primary_service = match self.get_gatt_service(&mut adapter, &id).await {
915 Some(s) => s,
916 None => return Err(BluetoothError::NotFound),
917 };
918 let services = primary_service.get_includes(device).unwrap_or(vec![]);
919 let mut services_vec = vec![];
920 for service in services {
921 if let Ok(service_uuid) = service.get_uuid() {
922 services_vec.push(BluetoothServiceMsg {
923 uuid: service_uuid,
924 is_primary: service.is_primary().unwrap_or(false),
925 instance_id: service.get_id(),
926 });
927 }
928 }
929 if let Some(uuid) = uuid {
930 services_vec.retain(|s| s.uuid == uuid);
931 }
932 services_vec.retain(|s| !uuid_is_blocklisted(&s.uuid, Blocklist::All));
933
934 if services_vec.is_empty() {
936 return Err(BluetoothError::NotFound);
937 }
938
939 Ok(BluetoothResponse::GetIncludedServices(services_vec, single))
940 },
941 GATTType::Descriptor => {
942 if !self.characteristic_is_cached(&id) {
944 return Err(BluetoothError::InvalidState);
945 }
946 let mut descriptors = self.get_and_cache_gatt_descriptors(&mut adapter, &id).await;
948 if let Some(uuid) = uuid {
949 descriptors.retain(|e| e.get_uuid().unwrap_or_default() == uuid);
950 }
951 let mut descriptors_vec = vec![];
952 for descriptor in descriptors {
953 if let Ok(uuid) = descriptor.get_uuid() {
954 descriptors_vec.push(BluetoothDescriptorMsg {
955 uuid,
956 instance_id: descriptor.get_id(),
957 });
958 }
959 }
960
961 if descriptors_vec.is_empty() {
963 return Err(BluetoothError::NotFound);
964 }
965 Ok(BluetoothResponse::GetDescriptors(descriptors_vec, single))
966 },
967 }
968 }
969
970 async fn read_value(&mut self, id: String) -> BluetoothResponseResult {
973 let mut adapter = self.get_adapter().await?;
976
977 let mut value = match self.get_gatt_characteristic(&mut adapter, &id).await {
979 Some(c) => Some(c.read_value().await.unwrap_or_default()),
980 None => None,
981 };
982
983 if value.is_none() {
987 value = match self.get_gatt_descriptor(&mut adapter, &id).await {
988 Some(d) => Some(d.read_value().await.unwrap_or_default()),
989 None => None,
990 };
991 }
992
993 match value {
996 Some(v) => Ok(BluetoothResponse::ReadValue(v)),
999
1000 None => Err(BluetoothError::InvalidState),
1003 }
1004 }
1005
1006 async fn write_value(&mut self, id: String, value: Vec<u8>) -> BluetoothResponseResult {
1009 let mut adapter = self.get_adapter().await?;
1012
1013 let mut result = match self.get_gatt_characteristic(&mut adapter, &id).await {
1015 Some(c) => Some(c.write_value(value.clone()).await),
1016 None => None,
1017 };
1018
1019 if result.is_none() {
1023 result = match self.get_gatt_descriptor(&mut adapter, &id).await {
1024 Some(d) => Some(d.write_value(value.clone()).await),
1025 None => None,
1026 };
1027 }
1028
1029 match result {
1032 Some(Ok(_)) => Ok(BluetoothResponse::WriteValue(value)),
1035
1036 Some(Err(_)) => Err(BluetoothError::NotSupported),
1038
1039 None => Err(BluetoothError::InvalidState),
1042 }
1043 }
1044
1045 async fn enable_notification(&mut self, id: String, enable: bool) -> BluetoothResponseResult {
1048 if !self.characteristic_is_cached(&id) {
1051 return Err(BluetoothError::InvalidState);
1052 }
1053
1054 let mut adapter = self.get_adapter().await?;
1056 match self.get_gatt_characteristic(&mut adapter, &id).await {
1057 Some(c) => {
1058 let result = if enable {
1059 c.start_notify().await
1062 } else {
1063 c.stop_notify().await
1065 };
1066 match result {
1067 Ok(_) => Ok(BluetoothResponse::EnableNotification(())),
1070
1071 Err(_) => Err(BluetoothError::NotSupported),
1073 }
1074 },
1075 None => Err(BluetoothError::InvalidState),
1077 }
1078 }
1079
1080 fn watch_advertisements(&mut self, _device_id: String) -> BluetoothResponseResult {
1082 Err(BluetoothError::NotSupported)
1085 }
1086
1087 async fn get_availability(&mut self) -> BluetoothResponseResult {
1089 Ok(BluetoothResponse::GetAvailability(
1090 self.get_adapter().await.is_ok(),
1091 ))
1092 }
1093}