1use anyhow::{Error, format_err};
6use fidl::prelude::*;
7use fidl_fuchsia_bluetooth_gatt2::{
8 self as gatt, AttributePermissions, Characteristic, CharacteristicPropertyBits, Descriptor,
9 Handle, LocalServiceControlHandle, LocalServiceMarker, LocalServiceReadValueResponder,
10 LocalServiceRequest, LocalServiceRequestStream, LocalServiceWriteValueResponder,
11 SecurityRequirements, Server_Marker, Server_Proxy, ServiceHandle, ServiceInfo, ServiceKind,
12 ValueChangedParameters,
13};
14use fuchsia_async as fasync;
15use fuchsia_bluetooth::types::{PeerId, Uuid};
16use fuchsia_component as app;
17use fuchsia_sync::RwLock;
18use futures::stream::TryStreamExt;
19use log::{error, info, warn};
20use serde_json::value::Value;
21use std::collections::HashMap;
22use std::str::FromStr;
23
24use crate::bluetooth::constants::{
25 CHARACTERISTIC_EXTENDED_PROPERTIES_UUID, GATT_MAX_ATTRIBUTE_VALUE_LENGTH,
26 PERMISSION_READ_ENCRYPTED, PERMISSION_READ_ENCRYPTED_MITM, PERMISSION_WRITE_ENCRYPTED,
27 PERMISSION_WRITE_ENCRYPTED_MITM, PERMISSION_WRITE_SIGNED, PERMISSION_WRITE_SIGNED_MITM,
28 PROPERTY_INDICATE, PROPERTY_NOTIFY, PROPERTY_READ, PROPERTY_WRITE,
29};
30
31#[derive(Debug)]
32struct Counter {
33 count: u64,
34}
35
36impl Counter {
37 pub fn new() -> Counter {
38 Counter { count: 0 }
39 }
40
41 fn next(&mut self) -> u64 {
42 let id: u64 = self.count;
43 self.count += 1;
44 id
45 }
46}
47
48#[derive(Debug)]
49struct InnerGattServerFacade {
50 attribute_value_mapping: HashMap<u64, (Vec<u8>, bool)>,
56
57 generic_id_counter: Counter,
59
60 server_proxy: Option<Server_Proxy>,
62
63 service_tasks: Vec<fasync::Task<()>>,
65}
66
67#[derive(Debug)]
72pub struct GattServerFacade {
73 inner: RwLock<InnerGattServerFacade>,
74}
75
76impl GattServerFacade {
77 pub fn new() -> GattServerFacade {
78 GattServerFacade {
79 inner: RwLock::new(InnerGattServerFacade {
80 attribute_value_mapping: HashMap::new(),
81 generic_id_counter: Counter::new(),
82 server_proxy: None,
83 service_tasks: vec![],
84 }),
85 }
86 }
87
88 fn create_server_proxy(&self) -> Result<Server_Proxy, Error> {
89 let tag = "GattServerFacade::create_server_proxy:";
90 match self.inner.read().server_proxy.clone() {
91 Some(service) => {
92 info!(
93 tag = &[tag, &line!().to_string()].join("").as_str();
94 "Current service proxy: {:?}", service
95 );
96 Ok(service)
97 }
98 None => {
99 info!(
100 tag = &[tag, &line!().to_string()].join("").as_str();
101 "Setting new server proxy"
102 );
103 let service = app::client::connect_to_protocol::<Server_Marker>();
104 if let Err(err) = service {
105 error!(
106 tag = &[tag, &line!().to_string()].join("").as_str(),
107 err:?;
108 "Failed to create server proxy"
109 );
110 return Err(format_err!("Failed to create server proxy: {:?}", err));
111 }
112 service
113 }
114 }
115 }
116
117 fn parse_attribute_value_to_byte_array(&self, value_to_parse: &Value) -> Vec<u8> {
120 match value_to_parse {
121 Value::String(obj) => String::from(obj.as_str()).into_bytes(),
122 Value::Number(obj) => match obj.as_u64() {
123 Some(num) => vec![num as u8],
124 None => vec![],
125 },
126 Value::Array(obj) => obj.iter().filter_map(|v| v.as_u64()).map(|v| v as u8).collect(),
127 _ => vec![],
128 }
129 }
130
131 fn on_characteristic_configuration(
132 peer_id: PeerId,
133 handle: Handle,
134 notify: bool,
135 indicate: bool,
136 control_handle: &LocalServiceControlHandle,
137 ) {
138 let tag = "GattServerFacade::on_characteristic_configuration:";
139 info!(
140 tag = &[tag, &line!().to_string()].join("").as_str(),
141 notify:%,
142 indicate:%,
143 id:% = peer_id;
144 "OnCharacteristicConfiguration"
145 );
146
147 if indicate {
148 let value = ValueChangedParameters {
149 handle: Some(handle),
150 value: Some(vec![0x02, 0x00]),
151 peer_ids: Some(vec![peer_id.into()]),
152 ..Default::default()
153 };
154 let (confirmation, _) = fidl::EventPair::create();
156 let _ = control_handle.send_on_indicate_value(&value, confirmation);
157 } else if notify {
158 let value = ValueChangedParameters {
159 handle: Some(handle),
160 value: Some(vec![0x01, 0x00]),
161 peer_ids: Some(vec![peer_id.into()]),
162 ..Default::default()
163 };
164 let _ = control_handle.send_on_notify_value(&value);
165 }
166 }
167
168 fn on_read_value(
169 peer_id: PeerId,
170 handle: Handle,
171 offset: i32,
172 responder: LocalServiceReadValueResponder,
173 value_in_mapping: Option<&(Vec<u8>, bool)>,
174 ) {
175 let tag = "GattServerFacade::on_read_value:";
176 info!(
177 tag = &[tag, &line!().to_string()].join("").as_str(),
178 at_id:? = handle.value,
179 offset:? = offset,
180 id:% = peer_id;
181 "OnReadValue request",
182 );
183 match value_in_mapping {
184 Some(v) => {
185 let (value, _enforce_initial_attribute_length) = v;
186 if value.len() < offset as usize {
187 let _result = responder.send(Err(gatt::Error::InvalidOffset));
188 } else {
189 let _result = responder.send(Ok(&value[offset as usize..]));
190 }
191 }
192 None => {
193 let _result = responder.send(Err(gatt::Error::ReadNotPermitted));
195 }
196 };
197 }
198
199 fn write_and_extend(value: &mut Vec<u8>, value_to_write: Vec<u8>, offset: usize) {
200 let split_idx = (value.len() - offset).min(value_to_write.len());
201 let (overlapping, extending) = value_to_write.split_at(split_idx);
202 let end_of_overlap = offset + overlapping.len();
203 value.splice(offset..end_of_overlap, overlapping.iter().cloned());
204 value.extend_from_slice(extending);
205 }
206
207 fn on_write_value(
208 peer_id: PeerId,
209 handle: Handle,
210 offset: u32,
211 value_to_write: Vec<u8>,
212 responder: LocalServiceWriteValueResponder,
213 value_in_mapping: Option<&mut (Vec<u8>, bool)>,
214 ) {
215 let tag = "GattServerFacade::on_write_value:";
216 info!(
217 tag = &[tag, &line!().to_string()].join("").as_str(),
218 at_id = handle.value,
219 offset = offset,
220 value:? = value_to_write,
221 id:% = peer_id;
222 "OnWriteValue request",
223 );
224
225 match value_in_mapping {
226 Some(v) => {
227 let (value, enforce_initial_attribute_length) = v;
228 let max_attribute_size: usize = match enforce_initial_attribute_length {
229 true => value.len(),
230 false => GATT_MAX_ATTRIBUTE_VALUE_LENGTH,
231 };
232 if max_attribute_size < (value_to_write.len() + offset as usize) {
233 let _result = responder.send(Err(gatt::Error::InvalidAttributeValueLength));
234 } else if value.len() < offset as usize {
235 let _result = responder.send(Err(gatt::Error::InvalidOffset));
236 } else {
237 GattServerFacade::write_and_extend(value, value_to_write, offset as usize);
238 let _result = responder.send(Ok(()));
239 }
240 }
241 None => {
242 let _result = responder.send(Err(gatt::Error::WriteNotPermitted));
244 }
245 }
246 }
247
248 async fn monitor_service_request_stream(
249 stream: LocalServiceRequestStream,
250 control_handle: LocalServiceControlHandle,
251 mut attribute_value_mapping: HashMap<u64, (Vec<u8>, bool)>,
252 ) -> Result<(), Error> {
253 stream
254 .map_ok(move |request| match request {
255 LocalServiceRequest::CharacteristicConfiguration {
256 peer_id,
257 handle,
258 notify,
259 indicate,
260 responder,
261 } => {
262 GattServerFacade::on_characteristic_configuration(
263 peer_id.into(),
264 handle,
265 notify,
266 indicate,
267 &control_handle,
268 );
269 let _ = responder.send();
270 }
271 LocalServiceRequest::ReadValue { peer_id, handle, offset, responder } => {
272 GattServerFacade::on_read_value(
273 peer_id.into(),
274 handle,
275 offset,
276 responder,
277 attribute_value_mapping.get(&handle.value),
278 );
279 }
280 LocalServiceRequest::WriteValue { payload, responder } => {
281 GattServerFacade::on_write_value(
282 payload.peer_id.unwrap().into(),
283 payload.handle.unwrap(),
284 payload.offset.unwrap(),
285 payload.value.unwrap(),
286 responder,
287 attribute_value_mapping.get_mut(&payload.handle.unwrap().value),
288 );
289 }
290 LocalServiceRequest::PeerUpdate { payload: _, responder } => {
291 responder.drop_without_shutdown();
292 }
293 LocalServiceRequest::ValueChangedCredit { .. } => {}
294 })
295 .try_collect::<()>()
296 .await
297 .map_err(|e| e.into())
298 }
299
300 fn permissions_and_properties_from_raw_num(
322 &self,
323 permissions: u32,
324 properties: u32,
325 ) -> AttributePermissions {
326 let mut read_encryption_required = false;
327 let mut read_authentication_required = false;
328 let mut read_authorization_required = false;
329
330 let mut write_encryption_required = false;
331 let mut write_authentication_required = false;
332 let mut write_authorization_required = false;
333
334 let mut update_encryption_required = false;
335 let mut update_authentication_required = false;
336 let mut update_authorization_required = false;
337
338 if permissions & PERMISSION_READ_ENCRYPTED != 0 {
339 read_encryption_required = true;
340 read_authentication_required = true;
341 read_authorization_required = true;
342 }
343
344 if permissions & PERMISSION_READ_ENCRYPTED_MITM != 0 {
345 read_encryption_required = true;
346 update_encryption_required = true;
347 }
348
349 if permissions & PERMISSION_WRITE_ENCRYPTED != 0 {
350 write_encryption_required = true;
351 update_encryption_required = true;
352 }
353
354 if permissions & PERMISSION_WRITE_ENCRYPTED_MITM != 0 {
355 write_encryption_required = true;
356 update_encryption_required = true;
357 update_authentication_required = true;
358 update_authorization_required = true;
359 }
360
361 if permissions & PERMISSION_WRITE_SIGNED != 0 {
362 write_authorization_required = true;
363 }
364
365 if permissions & PERMISSION_WRITE_SIGNED_MITM != 0 {
366 write_encryption_required = true;
367 write_authentication_required = true;
368 write_authorization_required = true;
369 update_encryption_required = true;
370 update_authentication_required = true;
371 update_authorization_required = true;
372 }
373
374 let update_sec_requirement = if properties & (PROPERTY_NOTIFY | PROPERTY_INDICATE) != 0 {
377 Some(SecurityRequirements {
378 encryption_required: Some(update_encryption_required),
379 authentication_required: Some(update_authentication_required),
380 authorization_required: Some(update_authorization_required),
381 ..Default::default()
382 })
383 } else {
384 None
385 };
386
387 let read_sec_requirement = if properties & PROPERTY_READ != 0 {
388 Some(SecurityRequirements {
389 encryption_required: Some(read_encryption_required),
390 authentication_required: Some(read_authentication_required),
391 authorization_required: Some(read_authorization_required),
392 ..Default::default()
393 })
394 } else {
395 None
396 };
397
398 let write_sec_requirement = if properties & PROPERTY_WRITE != 0 {
399 Some(SecurityRequirements {
400 encryption_required: Some(write_encryption_required),
401 authentication_required: Some(write_authentication_required),
402 authorization_required: Some(write_authorization_required),
403 ..Default::default()
404 })
405 } else {
406 None
407 };
408
409 AttributePermissions {
410 read: read_sec_requirement,
411 write: write_sec_requirement,
412 update: update_sec_requirement,
413 ..Default::default()
414 }
415 }
416
417 fn process_descriptors(
423 &self,
424 descriptor_list_json: &Value,
425 ) -> Result<(Vec<Descriptor>, CharacteristicPropertyBits), Error> {
426 let mut descriptors: Vec<Descriptor> = Vec::new();
427 let banned_descriptor_uuids = [
430 Uuid::from_str("00002900-0000-1000-8000-00805f9b34fb").unwrap(), Uuid::from_str("00002902-0000-1000-8000-00805f9b34fb").unwrap(), Uuid::from_str("00002903-0000-1000-8000-00805f9b34fb").unwrap(), ];
434
435 if descriptor_list_json.is_null() {
436 return Ok((descriptors, CharacteristicPropertyBits::empty()));
437 }
438
439 let descriptor_list = descriptor_list_json
440 .as_array()
441 .ok_or_else(|| format_err!("Attribute 'descriptors' is not a parseable list."))?;
442
443 let mut ext_property_bits = CharacteristicPropertyBits::empty();
444
445 for descriptor in descriptor_list.iter() {
446 let descriptor_uuid: Uuid = match descriptor["uuid"].as_str() {
447 Some(uuid_str) => Uuid::from_str(uuid_str)
448 .map_err(|_| format_err!("Descriptor uuid is invalid"))?,
449 None => return Err(format_err!("Descriptor uuid was unable to cast to str.")),
450 };
451 let descriptor_value = self.parse_attribute_value_to_byte_array(&descriptor["value"]);
452
453 if descriptor_uuid == Uuid::new16(CHARACTERISTIC_EXTENDED_PROPERTIES_UUID) {
455 if descriptor_value.is_empty() {
456 warn!("Extended properties descriptor has empty value. Ignoring.");
457 continue;
458 }
459 let ext_bits_raw: u16 = (descriptor_value[0] as u16) << u8::BITS;
461 ext_property_bits = CharacteristicPropertyBits::from_bits_truncate(ext_bits_raw);
462 continue;
463 }
464
465 let raw_enforce_enforce_initial_attribute_length =
466 descriptor["enforce_initial_attribute_length"].as_bool().unwrap_or(false);
467
468 let properties = 0u32;
470
471 if banned_descriptor_uuids.contains(&descriptor_uuid) {
472 continue;
473 }
474
475 let raw_descriptor_permissions = match descriptor["permissions"].as_u64() {
476 Some(permissions) => permissions as u32,
477 None => {
478 return Err(format_err!("Descriptor permissions was unable to cast to u64."));
479 }
480 };
481
482 let desc_permission_attributes = self
483 .permissions_and_properties_from_raw_num(raw_descriptor_permissions, properties);
484
485 let descriptor_id = self.inner.write().generic_id_counter.next();
486 self.inner.write().attribute_value_mapping.insert(
487 descriptor_id,
488 (descriptor_value, raw_enforce_enforce_initial_attribute_length),
489 );
490 let fidl_descriptor = Descriptor {
491 handle: Some(Handle { value: descriptor_id }),
492 type_: Some(descriptor_uuid.into()),
493 permissions: Some(desc_permission_attributes),
494 ..Default::default()
495 };
496
497 descriptors.push(fidl_descriptor);
498 }
499 Ok((descriptors, ext_property_bits))
500 }
501
502 fn generate_characteristics(
503 &self,
504 characteristic_list_json: &Value,
505 ) -> Result<Vec<Characteristic>, Error> {
506 let mut characteristics: Vec<Characteristic> = Vec::new();
507 if characteristic_list_json.is_null() {
508 return Ok(characteristics);
509 }
510
511 let characteristic_list = match characteristic_list_json.as_array() {
512 Some(c) => c,
513 None => {
514 return Err(format_err!("Attribute 'characteristics' is not a parseable list."));
515 }
516 };
517
518 for characteristic in characteristic_list.iter() {
519 let characteristic_uuid = match characteristic["uuid"].as_str() {
520 Some(uuid_str) => Uuid::from_str(uuid_str)
521 .map_err(|_| format_err!("Invalid characteristic uuid: {}", uuid_str))?,
522 None => return Err(format_err!("Characteristic uuid was unable to cast to str.")),
523 };
524
525 let characteristic_properties = match characteristic["properties"].as_u64() {
526 Some(properties) => properties as u32,
527 None => {
528 return Err(format_err!(
529 "Characteristic properties was unable to cast to u64."
530 ));
531 }
532 };
533
534 let raw_characteristic_permissions = match characteristic["permissions"].as_u64() {
535 Some(permissions) => permissions as u32,
536 None => {
537 return Err(format_err!(
538 "Characteristic permissions was unable to cast to u64."
539 ));
540 }
541 };
542
543 let characteristic_value =
544 self.parse_attribute_value_to_byte_array(&characteristic["value"]);
545
546 let raw_enforce_enforce_initial_attribute_length =
547 characteristic["enforce_initial_attribute_length"].as_bool().unwrap_or(false);
548
549 let descriptor_list = &characteristic["descriptors"];
550 let (fidl_descriptors, ext_properties_bits) =
551 self.process_descriptors(descriptor_list)?;
552
553 let characteristic_permissions = self.permissions_and_properties_from_raw_num(
554 raw_characteristic_permissions,
555 characteristic_properties,
556 );
557
558 let characteristic_properties =
563 CharacteristicPropertyBits::from_bits_truncate(characteristic_properties as u16)
564 | ext_properties_bits;
565
566 let characteristic_id = self.inner.write().generic_id_counter.next();
567 self.inner.write().attribute_value_mapping.insert(
568 characteristic_id,
569 (characteristic_value, raw_enforce_enforce_initial_attribute_length),
570 );
571 let fidl_characteristic = Characteristic {
572 handle: Some(Handle { value: characteristic_id }),
573 type_: Some(characteristic_uuid.into()),
574 properties: Some(characteristic_properties),
575 permissions: Some(characteristic_permissions),
576 descriptors: Some(fidl_descriptors),
577 ..Default::default()
578 };
579
580 characteristics.push(fidl_characteristic);
581 }
582 Ok(characteristics)
583 }
584
585 fn generate_service(&self, service_json: &Value) -> Result<ServiceInfo, Error> {
586 let service_id = self.inner.write().generic_id_counter.next();
588 let service_kind = match service_json["type"]
589 .as_i64()
590 .ok_or_else(|| format_err!("Invalid service type"))?
591 {
592 0 => ServiceKind::Primary,
593 1 => ServiceKind::Secondary,
594 _ => return Err(format_err!("Invalid Service type")),
595 };
596
597 let service_uuid_str = service_json["uuid"]
599 .as_str()
600 .ok_or_else(|| format_err!("Service uuid was unable to cast to str"))?;
601 let service_uuid =
602 Uuid::from_str(service_uuid_str).map_err(|_| format_err!("Invalid service uuid"))?;
603
604 let characteristics = self.generate_characteristics(&service_json["characteristics"])?;
606
607 Ok(ServiceInfo {
608 handle: Some(ServiceHandle { value: service_id }),
609 kind: Some(service_kind),
610 type_: Some(service_uuid.into()),
611 characteristics: Some(characteristics),
612 ..Default::default()
613 })
614 }
615
616 async fn publish_service(
617 &self,
618 service_info: ServiceInfo,
619 service_uuid: String,
620 ) -> Result<(), Error> {
621 let tag = "GattServerFacade::publish_service:";
622 let (service_client, service_server) =
623 fidl::endpoints::create_endpoints::<LocalServiceMarker>();
624 let (service_request_stream, service_control_handle) =
625 service_server.into_stream_and_control_handle();
626
627 let server_proxy = self
628 .inner
629 .read()
630 .server_proxy
631 .as_ref()
632 .ok_or_else(|| format_err!("No Server Proxy created."))?
633 .clone();
634 match server_proxy.publish_service(&service_info, service_client).await? {
635 Ok(()) => info!(
636 tag = &[tag, &line!().to_string()].join("").as_str(),
637 uuid:? = service_uuid;
638 "Successfully published GATT service",
639 ),
640 Err(e) => return Err(format_err!("PublishService error: {:?}", e)),
641 }
642
643 let monitor_delegate_fut = GattServerFacade::monitor_service_request_stream(
644 service_request_stream,
645 service_control_handle,
646 self.inner.read().attribute_value_mapping.clone(),
647 );
648 let fut = async {
649 let result = monitor_delegate_fut.await;
650 if let Err(err) = result {
651 error!(
652 tag = "publish_service",
653 err:?;
654 "Failed to create or monitor the gatt service delegate"
655 );
656 }
657 };
658 self.inner.write().service_tasks.push(fasync::Task::spawn(fut));
659 Ok(())
660 }
661
662 pub async fn publish_server(&self, args: Value) -> Result<(), Error> {
731 let tag = "GattServerFacade::publish_server:";
732 info!(tag = &[tag, &line!().to_string()].join("").as_str(); "Publishing service");
733 let server_proxy = self.create_server_proxy()?;
734 self.inner.write().server_proxy = Some(server_proxy);
735 let services = args
736 .get("database")
737 .ok_or_else(|| format_err!("Could not find the 'database' key in the json database."))?
738 .get("services")
739 .ok_or_else(|| {
740 format_err!("Could not find the 'services' key in the json database.")
741 })?;
742
743 let service_list = match services.as_array() {
744 Some(s) => s,
745 None => return Err(format_err!("Attribute 'service' is not a parseable list.")),
746 };
747
748 for service in service_list.iter() {
749 self.inner.write().attribute_value_mapping.clear();
750 let service_info = self.generate_service(service)?;
751 let service_uuid = &service["uuid"];
752 self.publish_service(service_info, service_uuid.to_string()).await?;
753 }
754 Ok(())
755 }
756
757 pub async fn close_server(&self) {
758 self.inner.write().server_proxy = None;
759 let _ = std::mem::take(&mut self.inner.write().service_tasks);
760 }
761
762 pub fn cleanup(&self) {
764 let tag = "GattServerFacade::cleanup:";
765 info!(tag = &[tag, &line!().to_string()].join("").as_str(); "Cleanup GATT server objects");
766 self.inner.write().server_proxy = None;
767 let _ = std::mem::take(&mut self.inner.write().service_tasks);
768 }
769
770 pub fn print(&self) {
773 let tag = "GattServerFacade::print:";
774 info!(tag = &[tag, &line!().to_string()].join("").as_str(); "Unimplemented print function");
775 }
776}