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::{select, FutureExt};
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.into_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 =
538 if let Some(v) = record_description.get("additional_protocol_descriptors") {
539 if let Some(arr) = v.as_array() {
540 Some(self.generate_protocol_descriptors(arr)?)
541 } else if v.is_null() {
542 None
543 } else {
544 let log_err =
545 "Invalid type for 'additional_protocol_descriptors'. Expected null or array.";
546 fx_err_and_bail!(&with_line!(tag), log_err)
547 }
548 } else {
549 let log_err = "Invalid SDP record input. Missing 'additional_protocol_descriptors'";
550 fx_err_and_bail!(&with_line!(tag), log_err)
551 };
552
553 let information = if let Some(v) = record_description.get("information") {
554 if let Some(r) = v.as_array() {
555 self.generate_information(r)?
556 } else {
557 let log_err = "Invalid type for information in record input.";
558 fx_err_and_bail!(&with_line!(tag), log_err)
559 }
560 } else {
561 let log_err = "Invalid SDP record input. Missing 'information'";
562 fx_err_and_bail!(&with_line!(tag), log_err)
563 };
564
565 let additional_attributes = if let Some(v) = record_description.get("additional_attributes")
566 {
567 if let Some(r) = v.as_array() {
568 Some(self.generate_additional_attributes(r)?)
569 } else {
570 None
571 }
572 } else {
573 let log_err = "Invalid SDP record input. Missing 'additional_attributes'";
574 fx_err_and_bail!(&with_line!(tag), log_err)
575 };
576
577 let service_defs = vec![ServiceDefinition {
578 service_class_uuids: Some(service_class_uuids.into_iter().map(Into::into).collect()),
579 protocol_descriptor_list: Some(protocol_descriptors),
580 profile_descriptors: Some(profile_descriptors),
581 additional_protocol_descriptor_lists: match raw_additional_protocol_descriptors {
582 Some(d) => Some(vec![d]),
583 None => None,
584 },
585 information: Some(information),
586 additional_attributes,
587 ..Default::default()
588 }];
589
590 let (connect_client, connect_requests) = create_request_stream();
591
592 match &self.inner.read().profile_server_proxy {
593 Some(server) => {
594 let _ = server.advertise(ProfileAdvertiseRequest {
595 services: Some(service_defs),
596 receiver: Some(connect_client),
597 ..Default::default()
598 });
599 }
600 None => fx_err_and_bail!(&with_line!(tag), "No Server Proxy created."),
601 };
602
603 let (end_ad_sender, end_ad_receiver) = oneshot::channel::<()>();
604 let request_handler_fut =
605 Self::monitor_connection_receiver(connect_requests, end_ad_receiver);
606 fasync::Task::spawn(async move {
607 if let Err(err) = request_handler_fut.await {
608 error!(err:?; "Connection receiver handler ended with error");
609 }
610 })
611 .detach();
612
613 let next = self.inner.write().advertisement_count + 1;
614 self.inner.write().advertisement_stoppers.insert(next, end_ad_sender);
615 self.inner.write().advertisement_count = next;
616 Ok(next)
617 }
618
619 pub async fn remove_service(&self, service_id: usize) -> Result<(), Error> {
624 let tag = "ProfileServerFacade::remove_service";
625 match self.inner.write().advertisement_stoppers.remove(&service_id) {
626 Some(_) => Ok(()),
627 None => fx_err_and_bail!(&with_line!(tag), "Service ID not found"),
628 }
629 }
630
631 pub fn get_service_class_profile_identifier_from_id(
632 &self,
633 raw_profile_id: &Value,
634 ) -> Result<ServiceClassProfileIdentifier, Error> {
635 let tag = "ProfileServerFacade::get_service_class_profile_identifier_from_id";
636 match raw_profile_id.as_u64().map(u16::try_from) {
637 Some(Ok(id)) => match ServiceClassProfileIdentifier::from_primitive(id) {
638 Some(id) => return Ok(id),
639 None => {
640 let log_err = format!("UUID {} not supported by profile server.", id);
641 fx_err_and_bail!(&with_line!(tag), log_err)
642 }
643 },
644 _ => fx_err_and_bail!(&with_line!(tag), "Type of raw_profile_id incorrect."),
645 };
646 }
647
648 pub async fn add_search(&self, args: Value) -> Result<(), Error> {
649 let tag = "ProfileServerFacade::add_search";
650 info!(tag = &with_line!(tag); "Adding Search");
651
652 let raw_attribute_list = if let Some(v) = args.get("attribute_list") {
653 if let Some(r) = v.as_array() {
654 r
655 } else {
656 let log_err = "Expected 'attribute_list' as an array.";
657 fx_err_and_bail!(&with_line!(tag), log_err)
658 }
659 } else {
660 let log_err = "Invalid SDP search input. Missing 'attribute_list'";
661 fx_err_and_bail!(&with_line!(tag), log_err)
662 };
663
664 let mut attribute_list = Vec::new();
665 for item in raw_attribute_list {
666 match item.as_u64() {
667 Some(v) => attribute_list.push(v as u16),
668 None => fx_err_and_bail!(
669 &with_line!(tag),
670 "Failed to convert value in attribute_list to u16."
671 ),
672 };
673 }
674
675 let profile_id = if let Some(r) = args.get("profile_id") {
676 self.get_service_class_profile_identifier_from_id(r)?
677 } else {
678 let log_err = "Invalid SDP search input. Missing 'profile_id'";
679 fx_err_and_bail!(&with_line!(tag), log_err)
680 };
681
682 let (search_client, result_requests) = create_request_stream();
683
684 match &self.inner.read().profile_server_proxy {
685 Some(server) => server.search(ProfileSearchRequest {
686 service_uuid: Some(profile_id),
687 attr_ids: Some(attribute_list),
688 results: Some(search_client),
689 ..Default::default()
690 })?,
691 None => fx_err_and_bail!(&with_line!(tag), "No Server Proxy created."),
692 };
693
694 let search_fut = Self::monitor_search_results(result_requests);
695 fasync::Task::spawn(async move {
696 if let Err(err) = search_fut.await {
697 error!(err:?; "Search result handler ended with error");
698 }
699 })
700 .detach();
701
702 Ok(())
703 }
704
705 pub async fn connect(&self, id: String, psm: u16, mode: &str) -> Result<(), Error> {
714 let tag = "ProfileServerFacade::connect";
715 let peer_id: PeerId = match id.parse() {
716 Ok(id) => id,
717 Err(_) => {
718 fx_err_and_bail!(
719 &with_line!(tag),
720 "Failed to convert value in attribute_list to u16."
721 );
722 }
723 };
724
725 let mode = match mode {
726 "BASIC" => ChannelMode::Basic,
727 "ERTM" => ChannelMode::EnhancedRetransmission,
728 _ => fx_err_and_bail!(&with_line!(tag), format!("Invalid mode: {:?}.", mode)),
729 };
730
731 let connection_result = match &self.inner.read().profile_server_proxy {
732 Some(server) => {
733 let l2cap_params = L2capParameters {
734 psm: Some(psm),
735 parameters: Some(ChannelParameters {
736 channel_mode: Some(mode),
737 ..Default::default()
738 }),
739 ..Default::default()
740 };
741 server.connect(&peer_id.into(), &ConnectParameters::L2cap(l2cap_params)).await?
742 }
743 None => fx_err_and_bail!(&with_line!(tag), "No Server Proxy created."),
744 };
745
746 match connection_result {
747 Ok(r) => self.inner.write().l2cap_channel_holder = Some(r),
748 Err(e) => {
749 fx_err_and_bail!(&with_line!(tag), format!("Failed to connect with error: {:?}", e))
750 }
751 };
752
753 Ok(())
754 }
755
756 pub async fn cleanup(&self) -> Result<(), Error> {
758 self.inner.write().advertisement_stoppers.clear();
760 self.inner.write().advertisement_count = 0;
761 self.inner.write().l2cap_channel_holder = None;
762 self.inner.write().profile_server_proxy = None;
763 Ok(())
764 }
765}