1use crate::common_utils::common::macros::{fx_err_and_bail, with_line};
6use anyhow::Error;
7use fidl::endpoints::create_request_stream;
8use fidl_fuchsia_bluetooth::{ChannelMode, ChannelParameters};
9use fidl_fuchsia_bluetooth_bredr::{
10 Attribute, Channel, ConnectParameters, ConnectionReceiverRequest,
11 ConnectionReceiverRequestStream, DataElement, Information, L2capParameters,
12 ProfileAdvertiseRequest, ProfileDescriptor, ProfileMarker, ProfileProxy, ProfileSearchRequest,
13 ProtocolDescriptor, ProtocolIdentifier, SearchResultsRequest, SearchResultsRequestStream,
14 ServiceClassProfileIdentifier, ServiceDefinition,
15};
16use fuchsia_async as fasync;
17use fuchsia_bluetooth::types::{PeerId, Uuid};
18use fuchsia_component as component;
19use fuchsia_sync::RwLock;
20use futures::channel::oneshot;
21use futures::stream::StreamExt;
22use futures::{FutureExt, select};
23use log::*;
24use serde_json::value::Value;
25use std::collections::HashMap;
26
27#[derive(Debug)]
28struct ProfileServerFacadeInner {
29 profile_server_proxy: Option<ProfileProxy>,
31
32 advertisement_count: usize,
34
35 advertisement_stoppers: HashMap<usize, oneshot::Sender<()>>,
37
38 l2cap_channel_holder: Option<Channel>,
40}
41
42#[derive(Debug)]
46pub struct ProfileServerFacade {
47 inner: RwLock<ProfileServerFacadeInner>,
48}
49
50impl ProfileServerFacade {
51 pub fn new() -> ProfileServerFacade {
52 ProfileServerFacade {
53 inner: RwLock::new(ProfileServerFacadeInner {
54 profile_server_proxy: None,
55 advertisement_count: 0,
56 advertisement_stoppers: HashMap::new(),
57 l2cap_channel_holder: None,
58 }),
59 }
60 }
61
62 pub fn create_profile_server_proxy(&self) -> Result<ProfileProxy, Error> {
64 let tag = "ProfileServerFacade::create_profile_server_proxy";
65 match self.inner.read().profile_server_proxy.clone() {
66 Some(profile_server_proxy) => {
67 info!(
68 tag = &with_line!(tag);
69 "Current profile server proxy: {:?}", profile_server_proxy
70 );
71 Ok(profile_server_proxy)
72 }
73 None => {
74 info!(tag = &with_line!(tag); "Setting new profile server proxy");
75 let profile_server_proxy =
76 component::client::connect_to_protocol::<ProfileMarker>();
77 if let Err(err) = profile_server_proxy {
78 fx_err_and_bail!(
79 &with_line!(tag),
80 format_err!("Failed to create profile server proxy: {}", err)
81 );
82 }
83 profile_server_proxy
84 }
85 }
86 }
87
88 pub async fn init_profile_server_proxy(&self) -> Result<(), Error> {
90 self.inner.write().profile_server_proxy = Some(self.create_profile_server_proxy()?);
91 Ok(())
92 }
93
94 pub fn generate_service_class_uuids(&self, uuid_list: &Vec<Value>) -> Result<Vec<Uuid>, Error> {
101 let tag = "ProfileServerFacade::generate_service_class_uuids";
102 let mut service_class_uuid_list = Vec::new();
103 for raw_uuid in uuid_list {
104 let uuid = if let Some(u) = raw_uuid.as_str() {
105 u
106 } else {
107 fx_err_and_bail!(
108 &with_line!(tag),
109 format_err!("Unable to convert Value to String.")
110 )
111 };
112 let uuid: Uuid = match uuid.parse() {
113 Ok(uuid) => uuid,
114 Err(e) => {
115 fx_err_and_bail!(
116 &with_line!(tag),
117 format_err!("Unable to convert to Uuid: {:?}", e)
118 );
119 }
120 };
121 service_class_uuid_list.push(uuid);
122 }
123 Ok(service_class_uuid_list)
124 }
125
126 pub fn generate_protocol_descriptors(
156 &self,
157 protocol_descriptors: &Vec<Value>,
158 ) -> Result<Vec<ProtocolDescriptor>, Error> {
159 let tag = "ProfileServerFacade::generate_protocol_descriptors";
160 let mut protocol_descriptor_list = Vec::new();
161
162 for raw_protocol_descriptor in protocol_descriptors {
163 let protocol = match raw_protocol_descriptor["protocol"].as_u64() {
164 Some(p) => match p as u16 {
165 1 => ProtocolIdentifier::Sdp,
166 3 => ProtocolIdentifier::Rfcomm,
167 7 => ProtocolIdentifier::Att,
168 8 => ProtocolIdentifier::Obex,
169 15 => ProtocolIdentifier::Bnep,
170 17 => ProtocolIdentifier::Hidp,
171 18 => ProtocolIdentifier::HardcopyControlChannel,
172 20 => ProtocolIdentifier::HardcopyDataChannel,
173 22 => ProtocolIdentifier::HardcopyNotification,
174 23 => ProtocolIdentifier::Avctp,
175 25 => ProtocolIdentifier::Avdtp,
176 30 => ProtocolIdentifier::McapControlChannel,
177 31 => ProtocolIdentifier::McapDataChannel,
178 256 => ProtocolIdentifier::L2Cap,
179 _ => fx_err_and_bail!(
180 &with_line!(tag),
181 format!("Input protocol does not match supported protocols: {}", p)
182 ),
183 },
184 None => fx_err_and_bail!(&with_line!(tag), "Value 'protocol' not found."),
185 };
186
187 let raw_params = if let Some(p) = raw_protocol_descriptor["params"].as_array() {
188 p
189 } else {
190 fx_err_and_bail!(&with_line!(tag), "Value 'params' not found or invalid type.")
191 };
192
193 let mut params = Vec::new();
194 for param in raw_params {
195 let data = if let Some(d) = param["data"].as_u64() {
196 d as u16
197 } else {
198 fx_err_and_bail!(&with_line!(tag), "Value 'data' not found or invalid type.")
199 };
200
201 params.push(DataElement::Uint16(data as u16));
202 }
203
204 protocol_descriptor_list.push(ProtocolDescriptor {
205 protocol: Some(protocol),
206 params: Some(params),
207 ..Default::default()
208 });
209 }
210 Ok(protocol_descriptor_list)
211 }
212
213 pub fn generate_profile_descriptors(
230 &self,
231 profile_descriptors: &Vec<Value>,
232 ) -> Result<Vec<ProfileDescriptor>, Error> {
233 let tag = "ProfileServerFacade::generate_profile_descriptors";
234 let mut profile_descriptor_list = Vec::new();
235 for raw_profile_descriptor in profile_descriptors.iter() {
236 let profile_id = if let Some(r) = raw_profile_descriptor.get("profile_id") {
237 match self.get_service_class_profile_identifier_from_id(r) {
238 Ok(id) => id,
239 Err(e) => fx_err_and_bail!(&with_line!(tag), e),
240 }
241 } else {
242 let log_err = "Invalid SDP search input. Missing 'profile_id'";
243 fx_err_and_bail!(&with_line!(tag), log_err)
244 };
245
246 let minor_version = if let Some(num) = raw_profile_descriptor["minor_version"].as_u64()
247 {
248 num as u8
249 } else {
250 let log_err = "Type of 'minor_version' incorrect or incorrect type.";
251 fx_err_and_bail!(&with_line!(tag), log_err)
252 };
253
254 let major_version = if let Some(num) = raw_profile_descriptor["major_version"].as_u64()
255 {
256 num as u8
257 } else {
258 let log_err = "Type of 'major_version' incorrect or incorrect type.";
259 fx_err_and_bail!(&with_line!(tag), log_err)
260 };
261
262 profile_descriptor_list.push(ProfileDescriptor {
263 profile_id: Some(profile_id),
264 minor_version: Some(minor_version),
265 major_version: Some(major_version),
266 ..Default::default()
267 });
268 }
269 Ok(profile_descriptor_list)
270 }
271
272 pub fn generate_information(
284 &self,
285 information_list: &Vec<Value>,
286 ) -> Result<Vec<Information>, Error> {
287 let tag = "ProfileServerFacade::generate_information";
288 let mut info_list = Vec::new();
289 for raw_information in information_list {
290 let language = if let Some(v) = raw_information["language"].as_str() {
291 Some(v.to_string())
292 } else {
293 let log_err = "Type of 'language' incorrect of invalid type.";
294 fx_err_and_bail!(&with_line!(tag), log_err)
295 };
296
297 let name = if let Some(v) = raw_information["name"].as_str() {
298 Some(v.to_string())
299 } else {
300 None
301 };
302
303 let description = if let Some(v) = raw_information["description"].as_str() {
304 Some(v.to_string())
305 } else {
306 None
307 };
308
309 let provider = if let Some(v) = raw_information["provider"].as_str() {
310 Some(v.to_string())
311 } else {
312 None
313 };
314
315 info_list.push(Information {
316 language,
317 name,
318 description,
319 provider,
320 ..Default::default()
321 });
322 }
323 Ok(info_list)
324 }
325
326 pub fn generate_additional_attributes(
338 &self,
339 additional_attributes_list: &Vec<Value>,
340 ) -> Result<Vec<Attribute>, Error> {
341 let tag = "ProfileServerFacade::generate_additional_attributes";
342 let mut attribute_list = Vec::new();
343 for raw_attribute in additional_attributes_list {
344 let id = if let Some(v) = raw_attribute["id"].as_u64() {
345 v as u16
346 } else {
347 let log_err = "Type of 'id' incorrect or invalid type.";
348 fx_err_and_bail!(&with_line!(tag), log_err)
349 };
350
351 let raw_element = if let Some(e) = raw_attribute.get("element") {
352 e
353 } else {
354 let log_err = "Type of 'element' incorrect.";
355 fx_err_and_bail!(&with_line!(tag), log_err)
356 };
357
358 let data_element = if let Some(d) = raw_element["data"].as_u64() {
359 DataElement::Uint8(d as u8)
360 } else {
361 fx_err_and_bail!(&with_line!(tag), "Value 'data' not found.")
362 };
363
364 attribute_list.push(Attribute {
365 id: Some(id),
366 element: Some(data_element),
367 ..Default::default()
368 })
369 }
370 Ok(attribute_list)
371 }
372
373 pub async fn monitor_connection_receiver(
375 mut requests: ConnectionReceiverRequestStream,
376 end_signal: oneshot::Receiver<()>,
377 ) -> Result<(), Error> {
378 let tag = "ProfileServerFacade::monitor_connection_receiver";
379 let mut fused_end_signal = end_signal.fuse();
380 loop {
381 select! {
382 _ = fused_end_signal => {
383 info!("Ending advertisement on signal..");
384 return Ok(());
385 },
386 request = requests.next() => {
387 let request = match request {
388 None => {
389 let log_err = format_err!("Connection request stream ended");
390 fx_err_and_bail!(&with_line!(tag), log_err)
391 }
392 Some(Err(e)) => {
393 let log_err = format_err!("Error during connection request: {}", e);
394 fx_err_and_bail!(&with_line!(tag), log_err)
395 },
396 Some(Ok(r)) => r,
397 };
398 let ConnectionReceiverRequest::Connected { peer_id, channel, .. } = request else {
399 fx_err_and_bail!(&with_line!(tag), "unknown method")
400 };
401 let peer_id: PeerId = peer_id.into();
402 info!(
403 tag = &with_line!(tag);
404 "Connection from {}: {:?}!",
405 peer_id,
406 channel
407 );
408 }
409 }
410 }
411 }
412
413 pub async fn monitor_search_results(
415 mut requests: SearchResultsRequestStream,
416 ) -> Result<(), Error> {
417 let tag = "ProfileServerFacade::monitor_search_results";
418 while let Some(request) = requests.next().await {
419 let request = match request {
420 Err(e) => {
421 let log_err = format_err!("Error during search results request: {}", e);
422 fx_err_and_bail!(&with_line!(tag), log_err)
423 }
424 Ok(r) => r,
425 };
426 let SearchResultsRequest::ServiceFound { peer_id, protocol, attributes, responder } =
427 request
428 else {
429 fx_err_and_bail!(&with_line!(tag), "unknown method")
430 };
431 let peer_id: PeerId = peer_id.into();
432 info!(
433 tag = &with_line!(tag);
434 "Search Result: Peer {} with protocol {:?}: {:?}", peer_id, protocol, attributes
435 );
436 responder.send()?;
437 }
438 let log_err = format_err!("Search result request stream ended");
439 fx_err_and_bail!(&with_line!(tag), log_err)
440 }
441
442 pub async fn add_service(&self, args: Value) -> Result<usize, Error> {
492 let tag = "ProfileServerFacade::write_sdp_record";
493 info!(tag = &with_line!(tag); "Writing SDP record");
494
495 let record_description = if let Some(r) = args.get("record") {
496 r
497 } else {
498 let log_err = "Invalid SDP record input. Missing 'record'";
499 fx_err_and_bail!(&with_line!(tag), log_err)
500 };
501
502 let service_class_uuids = if let Some(v) = record_description.get("service_class_uuids") {
503 if let Some(r) = v.as_array() {
504 self.generate_service_class_uuids(r)?
505 } else {
506 let log_err = "Invalid type for service_class_uuids in record input.";
507 fx_err_and_bail!(&with_line!(tag), log_err)
508 }
509 } else {
510 let log_err = "Invalid SDP record input. Missing 'service_class_uuids'";
511 fx_err_and_bail!(&with_line!(tag), log_err)
512 };
513
514 let protocol_descriptors = if let Some(v) = record_description.get("protocol_descriptors") {
515 if let Some(r) = v.as_array() {
516 self.generate_protocol_descriptors(r)?
517 } else {
518 let log_err = "Invalid type for protocol_descriptors in record input.";
519 fx_err_and_bail!(&with_line!(tag), log_err)
520 }
521 } else {
522 let log_err = "Invalid SDP record input. Missing 'protocol_descriptors'";
523 fx_err_and_bail!(&with_line!(tag), log_err)
524 };
525
526 let profile_descriptors = if let Some(v) = record_description.get("profile_descriptors") {
527 if let Some(r) = v.as_array() {
528 self.generate_profile_descriptors(r)?
529 } else {
530 let log_err = "Invalid type for profile_descriptors in record input.";
531 fx_err_and_bail!(&with_line!(tag), log_err)
532 }
533 } else {
534 let log_err = "Invalid SDP record input. Missing 'profile_descriptors'";
535 fx_err_and_bail!(&with_line!(tag), log_err)
536 };
537
538 let raw_additional_protocol_descriptors = if let Some(v) =
539 record_description.get("additional_protocol_descriptors")
540 {
541 if let Some(arr) = v.as_array() {
542 Some(self.generate_protocol_descriptors(arr)?)
543 } else if v.is_null() {
544 None
545 } else {
546 let log_err =
547 "Invalid type for 'additional_protocol_descriptors'. Expected null or array.";
548 fx_err_and_bail!(&with_line!(tag), log_err)
549 }
550 } else {
551 let log_err = "Invalid SDP record input. Missing 'additional_protocol_descriptors'";
552 fx_err_and_bail!(&with_line!(tag), log_err)
553 };
554
555 let information = if let Some(v) = record_description.get("information") {
556 if let Some(r) = v.as_array() {
557 self.generate_information(r)?
558 } else {
559 let log_err = "Invalid type for information in record input.";
560 fx_err_and_bail!(&with_line!(tag), log_err)
561 }
562 } else {
563 let log_err = "Invalid SDP record input. Missing 'information'";
564 fx_err_and_bail!(&with_line!(tag), log_err)
565 };
566
567 let additional_attributes = if let Some(v) = record_description.get("additional_attributes")
568 {
569 if let Some(r) = v.as_array() {
570 Some(self.generate_additional_attributes(r)?)
571 } else {
572 None
573 }
574 } else {
575 let log_err = "Invalid SDP record input. Missing 'additional_attributes'";
576 fx_err_and_bail!(&with_line!(tag), log_err)
577 };
578
579 let service_defs = vec![ServiceDefinition {
580 service_class_uuids: Some(service_class_uuids.into_iter().map(Into::into).collect()),
581 protocol_descriptor_list: Some(protocol_descriptors),
582 profile_descriptors: Some(profile_descriptors),
583 additional_protocol_descriptor_lists: match raw_additional_protocol_descriptors {
584 Some(d) => Some(vec![d]),
585 None => None,
586 },
587 information: Some(information),
588 additional_attributes,
589 ..Default::default()
590 }];
591
592 let (connect_client, connect_requests) = create_request_stream();
593
594 match &self.inner.read().profile_server_proxy {
595 Some(server) => {
596 let _ = server.advertise(ProfileAdvertiseRequest {
597 services: Some(service_defs),
598 receiver: Some(connect_client),
599 ..Default::default()
600 });
601 }
602 None => fx_err_and_bail!(&with_line!(tag), "No Server Proxy created."),
603 };
604
605 let (end_ad_sender, end_ad_receiver) = oneshot::channel::<()>();
606 let request_handler_fut =
607 Self::monitor_connection_receiver(connect_requests, end_ad_receiver);
608 fasync::Task::spawn(async move {
609 if let Err(err) = request_handler_fut.await {
610 error!(err:?; "Connection receiver handler ended with error");
611 }
612 })
613 .detach();
614
615 let next = self.inner.write().advertisement_count + 1;
616 self.inner.write().advertisement_stoppers.insert(next, end_ad_sender);
617 self.inner.write().advertisement_count = next;
618 Ok(next)
619 }
620
621 pub async fn remove_service(&self, service_id: usize) -> Result<(), Error> {
626 let tag = "ProfileServerFacade::remove_service";
627 match self.inner.write().advertisement_stoppers.remove(&service_id) {
628 Some(_) => Ok(()),
629 None => fx_err_and_bail!(&with_line!(tag), "Service ID not found"),
630 }
631 }
632
633 pub fn get_service_class_profile_identifier_from_id(
634 &self,
635 raw_profile_id: &Value,
636 ) -> Result<ServiceClassProfileIdentifier, Error> {
637 let tag = "ProfileServerFacade::get_service_class_profile_identifier_from_id";
638 match raw_profile_id.as_u64().map(u16::try_from) {
639 Some(Ok(id)) => match ServiceClassProfileIdentifier::from_primitive(id) {
640 Some(id) => return Ok(id),
641 None => {
642 let log_err = format!("UUID {} not supported by profile server.", id);
643 fx_err_and_bail!(&with_line!(tag), log_err)
644 }
645 },
646 _ => fx_err_and_bail!(&with_line!(tag), "Type of raw_profile_id incorrect."),
647 };
648 }
649
650 pub async fn add_search(&self, args: Value) -> Result<(), Error> {
651 let tag = "ProfileServerFacade::add_search";
652 info!(tag = &with_line!(tag); "Adding Search");
653
654 let raw_attribute_list = if let Some(v) = args.get("attribute_list") {
655 if let Some(r) = v.as_array() {
656 r
657 } else {
658 let log_err = "Expected 'attribute_list' as an array.";
659 fx_err_and_bail!(&with_line!(tag), log_err)
660 }
661 } else {
662 let log_err = "Invalid SDP search input. Missing 'attribute_list'";
663 fx_err_and_bail!(&with_line!(tag), log_err)
664 };
665
666 let mut attribute_list = Vec::new();
667 for item in raw_attribute_list {
668 match item.as_u64() {
669 Some(v) => attribute_list.push(v as u16),
670 None => fx_err_and_bail!(
671 &with_line!(tag),
672 "Failed to convert value in attribute_list to u16."
673 ),
674 };
675 }
676
677 let profile_id = if let Some(r) = args.get("profile_id") {
678 self.get_service_class_profile_identifier_from_id(r)?
679 } else {
680 let log_err = "Invalid SDP search input. Missing 'profile_id'";
681 fx_err_and_bail!(&with_line!(tag), log_err)
682 };
683
684 let (search_client, result_requests) = create_request_stream();
685
686 match &self.inner.read().profile_server_proxy {
687 Some(server) => server.search(ProfileSearchRequest {
688 service_uuid: Some(profile_id),
689 attr_ids: Some(attribute_list),
690 results: Some(search_client),
691 ..Default::default()
692 })?,
693 None => fx_err_and_bail!(&with_line!(tag), "No Server Proxy created."),
694 };
695
696 let search_fut = Self::monitor_search_results(result_requests);
697 fasync::Task::spawn(async move {
698 if let Err(err) = search_fut.await {
699 error!(err:?; "Search result handler ended with error");
700 }
701 })
702 .detach();
703
704 Ok(())
705 }
706
707 pub async fn connect(&self, id: String, psm: u16, mode: &str) -> Result<(), Error> {
716 let tag = "ProfileServerFacade::connect";
717 let peer_id: PeerId = match id.parse() {
718 Ok(id) => id,
719 Err(_) => {
720 fx_err_and_bail!(
721 &with_line!(tag),
722 "Failed to convert value in attribute_list to u16."
723 );
724 }
725 };
726
727 let mode = match mode {
728 "BASIC" => ChannelMode::Basic,
729 "ERTM" => ChannelMode::EnhancedRetransmission,
730 _ => fx_err_and_bail!(&with_line!(tag), format!("Invalid mode: {:?}.", mode)),
731 };
732
733 let proxy_opt = self.inner.read().profile_server_proxy.clone();
734
735 let connection_result = match proxy_opt {
736 Some(server) => {
737 let l2cap_params = L2capParameters {
738 psm: Some(psm),
739 parameters: Some(ChannelParameters {
740 channel_mode: Some(mode),
741 ..Default::default()
742 }),
743 ..Default::default()
744 };
745 server.connect(&peer_id.into(), &ConnectParameters::L2cap(l2cap_params)).await?
746 }
747 None => fx_err_and_bail!(&with_line!(tag), "No Server Proxy created."),
748 };
749
750 match connection_result {
751 Ok(r) => self.inner.write().l2cap_channel_holder = Some(r),
752 Err(e) => {
753 fx_err_and_bail!(&with_line!(tag), format!("Failed to connect with error: {:?}", e))
754 }
755 };
756
757 Ok(())
758 }
759
760 pub async fn cleanup(&self) -> Result<(), Error> {
762 self.inner.write().advertisement_stoppers.clear();
764 self.inner.write().advertisement_count = 0;
765 self.inner.write().l2cap_channel_holder = None;
766 self.inner.write().profile_server_proxy = None;
767 Ok(())
768 }
769}