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