1use fuchsia_bluetooth::types::Channel;
6use futures::future::Future;
7use futures::stream::StreamExt;
8use log::{info, trace, warn};
9use packet_encoding::{Decodable, Encodable};
10
11use crate::error::{Error, PacketError};
12use crate::header::{
13 ConnectionIdentifier, Header, HeaderIdentifier, HeaderSet, SingleResponseMode,
14};
15use crate::operation::{OpCode, RequestPacket, ResponseCode, ResponsePacket, SetPathFlags};
16pub use crate::transport::TransportType;
17use crate::transport::max_packet_size_from_transport;
18use futures::SinkExt;
19
20mod handler;
23pub use handler::{ObexOperationError, ObexServerHandler, new_operation_error};
24
25mod get;
27use get::GetOperation;
28
29mod put;
31use put::PutOperation;
32
33#[derive(Debug)]
35pub enum OperationRequest {
36 SendPackets(Vec<ResponsePacket>),
38 GetApplicationInfo(HeaderSet),
41 GetApplicationData(HeaderSet),
43 PutApplicationData(Vec<u8>, HeaderSet),
45 DeleteApplicationData(HeaderSet),
47 None,
49}
50
51#[derive(Debug)]
53pub enum ApplicationResponse {
54 GetInfo(HeaderSet),
57 GetData((Vec<u8>, HeaderSet)),
60 Put,
62}
63
64impl ApplicationResponse {
65 #[cfg(test)]
66 fn accept_get(data: Vec<u8>, headers: HeaderSet) -> Result<Self, ObexOperationError> {
67 Ok(ApplicationResponse::GetData((data, headers)))
68 }
69
70 #[cfg(test)]
71 fn accept_get_info(headers: HeaderSet) -> Result<Self, ObexOperationError> {
72 Ok(ApplicationResponse::GetInfo(headers))
73 }
74
75 #[cfg(test)]
76 fn accept_put() -> Result<Self, ObexOperationError> {
77 Ok(ApplicationResponse::Put)
78 }
79}
80
81pub trait ServerOperation {
85 fn srm_status(&self) -> SingleResponseMode;
87
88 fn check_headers_for_srm(
91 srm_supported_locally: bool,
92 headers: &HeaderSet,
93 ) -> Option<SingleResponseMode>
94 where
95 Self: Sized,
96 {
97 let Some(Header::SingleResponseMode(srm)) =
98 headers.get(&HeaderIdentifier::SingleResponseMode)
99 else {
100 trace!("No SRM header in request");
101 return None;
102 };
103
104 if srm_supported_locally && *srm == SingleResponseMode::Enable {
106 Some(SingleResponseMode::Enable)
107 } else {
108 Some(SingleResponseMode::Disable)
110 }
111 }
112
113 fn is_complete(&self) -> bool;
115
116 fn handle_peer_request(&mut self, request: RequestPacket) -> Result<OperationRequest, Error>;
120
121 fn handle_application_response(
128 &mut self,
129 response: Result<ApplicationResponse, ObexOperationError>,
130 ) -> Result<Vec<ResponsePacket>, Error>;
131}
132
133#[derive(Clone, Copy, Debug, Default, PartialEq)]
134enum ConnectionStatus {
135 #[default]
137 Initialized,
138 Connected { id: Option<ConnectionIdentifier> },
143 DisconnectReceived,
146}
147
148impl ConnectionStatus {
149 #[cfg(test)]
150 fn connected_no_id() -> Self {
151 Self::Connected { id: None }
152 }
153}
154
155pub struct ObexServer {
159 connected: ConnectionStatus,
161 max_packet_size: u16,
163 active_operation: Option<Box<dyn ServerOperation>>,
170 channel: Channel,
172 type_: TransportType,
174 handler: Box<dyn ObexServerHandler>,
178}
179
180impl ObexServer {
181 const DIRECTED_CONNECTION_ID: ConnectionIdentifier = ConnectionIdentifier(1);
187
188 pub fn new(
189 channel: Channel,
190 type_: TransportType,
191 handler: Box<dyn ObexServerHandler>,
192 ) -> Self {
193 let max_packet_size = max_packet_size_from_transport(channel.max_tx_size());
194 Self {
195 connected: ConnectionStatus::default(),
196 max_packet_size,
197 active_operation: None,
198 channel,
199 type_,
200 handler,
201 }
202 }
203
204 fn is_connected(&self) -> bool {
206 matches!(self.connected, ConnectionStatus::Connected { .. })
207 }
208
209 fn set_connection_status(&mut self, status: ConnectionStatus) {
210 self.connected = status;
211 }
212
213 fn set_max_packet_size(&mut self, peer_max_packet_size: u16) {
214 let min_ = std::cmp::min(peer_max_packet_size, self.max_packet_size);
216 self.max_packet_size = min_;
217 trace!("Max packet size set to {}", self.max_packet_size);
218 }
219
220 async fn send(&mut self, data: impl Encodable<Error = PacketError>) -> Result<(), Error> {
223 let mut buf = vec![0; data.encoded_len()];
224 data.encode(&mut buf[..])?;
225 self.channel.send(buf).await?;
226 Ok(())
227 }
228
229 async fn connect_request(&mut self, request: RequestPacket) -> Result<ResponsePacket, Error> {
230 let data = request.data();
232 let version = data[0];
233 let flags = data[1];
234 let peer_max_packet_size = u16::from_be_bytes(data[2..4].try_into().unwrap());
235 trace!(version, flags, peer_max_packet_size; "Additional data in CONNECT request");
236 self.set_max_packet_size(peer_max_packet_size);
237
238 let headers = HeaderSet::from(request);
239
240 let id = if headers.contains_header(&HeaderIdentifier::Target) {
243 Some(Self::DIRECTED_CONNECTION_ID)
244 } else {
245 None
246 };
247 let (code, response_headers) = match self.handler.connect(headers).await {
248 Ok(mut headers) => {
249 trace!("Application accepted CONNECT request");
250 let _ = headers.try_add_connection_id(&id);
251 self.set_connection_status(ConnectionStatus::Connected { id });
252 (ResponseCode::Ok, headers)
253 }
254 Err(reject_parameters) => {
255 trace!("Application rejected CONNECT request");
256 reject_parameters
257 }
258 };
259 let response_packet =
260 ResponsePacket::new_connect(code, self.max_packet_size, response_headers);
261 Ok(response_packet)
262 }
263
264 async fn disconnect_request(
267 &mut self,
268 request: RequestPacket,
269 ) -> Result<ResponsePacket, Error> {
270 let headers = HeaderSet::from(request);
271 let response_headers = self.handler.disconnect(headers).await;
272 let response_packet = ResponsePacket::new_disconnect(response_headers);
273 self.set_connection_status(ConnectionStatus::DisconnectReceived);
274 Ok(response_packet)
275 }
276
277 async fn setpath_request(&mut self, request: RequestPacket) -> Result<ResponsePacket, Error> {
280 if !self.is_connected() {
281 return Err(Error::operation(OpCode::SetPath, "CONNECT not completed"));
282 }
283 let data = request.data();
286 let flags = SetPathFlags::from_bits_truncate(data[0]);
287 let backup = flags.contains(SetPathFlags::BACKUP);
288 let create = !flags.contains(SetPathFlags::DONT_CREATE);
289
290 let headers = HeaderSet::from(request);
291 let (code, response_headers) = match self.handler.set_path(headers, backup, create).await {
292 Ok(headers) => {
293 trace!("Application accepted SETPATH request");
294 (ResponseCode::Ok, headers)
295 }
296 Err(reject_parameters) => {
297 trace!("Application rejected SETPATH request");
298 reject_parameters
299 }
300 };
301 let response_packet = ResponsePacket::new_setpath(code, response_headers);
302 Ok(response_packet)
303 }
304
305 fn maybe_start_new_operation(&mut self, code: &OpCode) -> bool {
308 if self.active_operation.as_ref().is_some_and(|o| !o.is_complete()) {
309 return false;
310 }
311
312 let op: Box<dyn ServerOperation> = match code {
313 OpCode::Get | OpCode::GetFinal => {
314 Box::new(GetOperation::new(self.max_packet_size, self.type_.srm_supported()))
315 }
316 OpCode::Put | OpCode::PutFinal => {
317 Box::new(PutOperation::new(self.type_.srm_supported()))
318 }
319 _ => unreachable!("only called from `Self::multistep_request`"),
320 };
321 trace!("Started new operation ({code:?})");
322 self.active_operation = Some(op);
323 return true;
324 }
325
326 async fn multistep_request(
331 &mut self,
332 request: RequestPacket,
333 ) -> Result<Vec<ResponsePacket>, Error> {
334 let _ = self.maybe_start_new_operation(request.code());
335 let operation = self.active_operation.as_mut().expect("just initialized");
336
337 let application_response = match operation.handle_peer_request(request) {
338 Ok(OperationRequest::SendPackets(responses)) => return Ok(responses),
339 Ok(OperationRequest::GetApplicationInfo(info_headers)) => {
340 self.handler.get_info(info_headers).await.map(|x| ApplicationResponse::GetInfo(x))
341 }
342 Ok(OperationRequest::GetApplicationData(request_headers)) => self
343 .handler
344 .get_data(request_headers)
345 .await
346 .map(|x| ApplicationResponse::GetData(x)),
347 Ok(OperationRequest::PutApplicationData(data, request_headers)) => {
348 self.handler.put(data, request_headers).await.map(|_| ApplicationResponse::Put)
349 }
350 Ok(OperationRequest::DeleteApplicationData(request_headers)) => {
351 self.handler.delete(request_headers).await.map(|_| ApplicationResponse::Put)
352 }
353 Ok(OperationRequest::None) => return Ok(vec![]),
354 Err(e) => {
355 warn!("Internal error in operation: {e:?}");
356 return Ok(vec![ResponsePacket::new_no_data(
357 ResponseCode::InternalServerError,
358 HeaderSet::new(),
359 )]);
360 }
361 };
362
363 operation.handle_application_response(application_response)
364 }
365
366 async fn receive_packet(&mut self, packet: Vec<u8>) -> Result<Vec<ResponsePacket>, Error> {
370 let decoded = RequestPacket::decode(&packet[..])?;
371 trace!(packet:? = decoded; "Received request from OBEX client");
372 let response = match decoded.code() {
373 OpCode::Connect => self.connect_request(decoded).await?,
374 OpCode::Disconnect => self.disconnect_request(decoded).await?,
375 OpCode::SetPath => self.setpath_request(decoded).await?,
376 OpCode::Put | OpCode::PutFinal | OpCode::Get | OpCode::GetFinal => {
377 return self.multistep_request(decoded).await;
378 }
379 _code => todo!("Support other OBEX requests"),
380 };
381 Ok(vec![response])
382 }
383
384 pub fn run(mut self) -> impl Future<Output = Result<(), Error>> {
385 async move {
386 while let Some(packet) = self.channel.next().await {
387 match packet {
388 Ok(bytes) => {
389 let responses = self.receive_packet(bytes).await?;
390 for response in responses {
391 self.send(response).await?;
392 }
393
394 if self.connected == ConnectionStatus::DisconnectReceived {
396 trace!("Disconnect request - closing transport");
397 return Ok(());
398 }
399 }
400 Err(e) => warn!("Error reading data from transport: {e:?}"),
401 }
402 }
403 info!("Peer disconnected transport");
404 Ok(())
405 }
406 }
407}
408
409#[cfg(test)]
410pub(crate) mod test_utils {
411 use super::*;
412
413 #[track_caller]
414 pub fn expect_single_packet(request: OperationRequest) -> ResponsePacket {
415 let OperationRequest::SendPackets(mut packets) = request else {
416 panic!("Expected outgoing packet request, got: {request:?}");
417 };
418 assert_eq!(packets.len(), 1);
419 packets.pop().unwrap()
420 }
421}
422
423#[cfg(test)]
424mod tests {
425 use super::*;
426
427 use assert_matches::assert_matches;
428 use async_test_helpers::expect_stream_pending;
429 use async_utils::PollExt;
430 use fuchsia_async as fasync;
431 use std::pin::pin;
432
433 use crate::header::header_set::{expect_body, expect_end_of_body};
434 use crate::server::handler::test_utils::TestApplicationProfile;
435 use crate::transport::test_utils::{expect_response, send_packet};
436
437 fn new_obex_server(srm: bool) -> (ObexServer, TestApplicationProfile, Channel) {
440 let (local, remote) = Channel::create();
441 let app = TestApplicationProfile::new();
442 let type_ = if srm { TransportType::L2cap } else { TransportType::Rfcomm };
443 let obex_server = ObexServer::new(local, type_, Box::new(app.clone()));
444 (obex_server, app, remote)
445 }
446
447 #[fuchsia::test]
448 fn obex_server_terminates_when_channel_closes() {
449 let mut exec = fasync::TestExecutor::new();
450 let (obex_server, _test_app, remote) = new_obex_server(false);
451
452 let server_fut = obex_server.run();
453 let mut server_fut = pin!(server_fut);
454 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server still active");
455
456 drop(remote);
457 let result = exec.run_until_stalled(&mut server_fut).expect("server finished");
458 assert_matches!(result, Ok(_));
459 }
460
461 #[fuchsia::test]
462 fn connect_accepted_by_app_success() {
463 let mut exec = fasync::TestExecutor::new();
464 let (obex_server, test_app, mut remote) = new_obex_server(false);
465 let server_fut = obex_server.run();
466 let mut server_fut = pin!(server_fut);
467 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
468
469 let connect_request = RequestPacket::new_connect(500, HeaderSet::new());
470 send_packet(&mut exec, &mut remote, connect_request);
471
472 let headers = HeaderSet::from_header(Header::Description("foo".into()));
475 test_app.set_response(Ok(headers));
476 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
477
478 let expectation = |response: ResponsePacket| {
481 assert_eq!(*response.code(), ResponseCode::Ok);
482 assert_eq!(response.data(), &[0x10, 0, 0x01, 0xf4]);
483 assert!(response.headers().contains_header(&HeaderIdentifier::Description));
484 assert!(!response.headers().contains_header(&HeaderIdentifier::ConnectionId));
485 };
486 expect_response(&mut exec, &mut remote, expectation, OpCode::Connect);
487 }
488
489 #[fuchsia::test]
490 fn directed_connect_accepted_by_app_success() {
491 let mut exec = fasync::TestExecutor::new();
492 let (obex_server, test_app, mut remote) = new_obex_server(false);
493 let server_fut = obex_server.run();
494 let mut server_fut = pin!(server_fut);
495 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
496
497 let request_headers = HeaderSet::from_header(Header::Target(vec![5, 6]));
498 let connect_request = RequestPacket::new_connect(500, request_headers);
499 send_packet(&mut exec, &mut remote, connect_request);
500
501 let headers = HeaderSet::from_header(Header::name("foo"));
504 test_app.set_response(Ok(headers));
505 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
506
507 let expectation = |response: ResponsePacket| {
510 assert_eq!(*response.code(), ResponseCode::Ok);
511 assert_eq!(response.data(), &[0x10, 0, 0x01, 0xf4]);
512 assert!(response.headers().contains_header(&HeaderIdentifier::Name));
513 assert!(response.headers().contains_header(&HeaderIdentifier::ConnectionId));
514 };
515 expect_response(&mut exec, &mut remote, expectation, OpCode::Connect);
516 }
517
518 #[fuchsia::test]
519 fn connect_rejected_by_app_is_ok() {
520 let mut exec = fasync::TestExecutor::new();
521 let (obex_server, test_app, mut remote) = new_obex_server(false);
522 let server_fut = obex_server.run();
523 let mut server_fut = pin!(server_fut);
524 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
525
526 let connect_request = RequestPacket::new_connect(255, HeaderSet::new());
527 send_packet(&mut exec, &mut remote, connect_request);
528
529 test_app.set_response(Err((ResponseCode::Forbidden, HeaderSet::new())));
531 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
532
533 let expectation = |response: ResponsePacket| {
535 assert_eq!(*response.code(), ResponseCode::Forbidden);
536 assert_eq!(response.data(), &[0x10, 0, 0x00, 0xff]);
537 let headers = HeaderSet::from(response);
538 assert!(headers.is_empty());
539 };
540 expect_response(&mut exec, &mut remote, expectation, OpCode::Connect);
541 }
542
543 #[fuchsia::test]
544 fn invalid_connect_request_is_error() {
545 let mut exec = fasync::TestExecutor::new();
546 let (obex_server, _test_app, mut remote) = new_obex_server(false);
547
548 let server_fut = obex_server.run();
549 let mut server_fut = pin!(server_fut);
550 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server still active");
551
552 let bytes = [0x80, 0x00, 0x05, 0x00, 0x00];
554 let mut fut = remote.send(bytes.to_vec());
555 exec.run_until_stalled(&mut fut).expect("can send data").expect("write success");
556
557 let result = exec.run_until_stalled(&mut server_fut).expect("terminate due to error");
558 assert_matches!(result, Err(Error::Packet(_)));
559 }
560
561 #[fuchsia::test]
562 fn peer_disconnect_request_terminates_server() {
563 let mut exec = fasync::TestExecutor::new();
564 let (obex_server, test_app, mut remote) = new_obex_server(false);
565 let server_fut = obex_server.run();
566 let mut server_fut = pin!(server_fut);
567 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
568
569 let headers = HeaderSet::from_header(Header::Description("done".into()));
570 let disconnect_request = RequestPacket::new_disconnect(headers);
571 send_packet(&mut exec, &mut remote, disconnect_request);
572
573 let headers = HeaderSet::from_header(Header::Description("disconnecting".into()));
577 test_app.set_response(Ok(headers));
578 let result =
579 exec.run_until_stalled(&mut server_fut).expect("server terminated from disconnect");
580 assert_matches!(result, Ok(_));
581
582 let expectation = |response: ResponsePacket| {
584 assert_eq!(*response.code(), ResponseCode::Ok);
585 let headers = HeaderSet::from(response);
586 assert!(headers.contains_header(&HeaderIdentifier::Description));
587 };
588 expect_response(&mut exec, &mut remote, expectation, OpCode::Disconnect);
589 }
590
591 #[fuchsia::test]
592 fn setpath_request_accepted_by_app_success() {
593 let mut exec = fasync::TestExecutor::new();
594 let (mut obex_server, test_app, mut remote) = new_obex_server(false);
595 obex_server.set_connection_status(ConnectionStatus::connected_no_id());
597 let server_fut = obex_server.run();
598 let mut server_fut = pin!(server_fut);
599 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
600
601 let headers = HeaderSet::from_header(Header::name("folder1"));
602 let setpath_request =
603 RequestPacket::new_set_path(SetPathFlags::all(), headers).expect("valid request");
604 send_packet(&mut exec, &mut remote, setpath_request);
605
606 test_app.set_response(Ok(HeaderSet::new()));
608 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
609
610 let expectation = |response: ResponsePacket| {
612 assert_eq!(*response.code(), ResponseCode::Ok);
613 let headers = HeaderSet::from(response);
614 assert!(headers.is_empty());
615 };
616 expect_response(&mut exec, &mut remote, expectation, OpCode::SetPath);
617 }
618
619 #[fuchsia::test]
620 fn setpath_request_rejected_by_app_success() {
621 let mut exec = fasync::TestExecutor::new();
622 let (mut obex_server, test_app, mut remote) = new_obex_server(false);
623 obex_server.set_connection_status(ConnectionStatus::connected_no_id());
625 let server_fut = obex_server.run();
626 let mut server_fut = pin!(server_fut);
627 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
628
629 let setpath_request = RequestPacket::new_set_path(SetPathFlags::BACKUP, HeaderSet::new())
630 .expect("valid request");
631 send_packet(&mut exec, &mut remote, setpath_request);
632
633 test_app.set_response(Err((ResponseCode::Forbidden, HeaderSet::new())));
635 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
636
637 let expectation = |response: ResponsePacket| {
639 assert_eq!(*response.code(), ResponseCode::Forbidden);
640 let headers = HeaderSet::from(response);
641 assert!(headers.is_empty());
642 };
643 expect_response(&mut exec, &mut remote, expectation, OpCode::SetPath);
644 }
645
646 #[fuchsia::test]
647 fn setpath_request_before_connect_is_error() {
648 let mut exec = fasync::TestExecutor::new();
649 let (obex_server, _test_app, mut remote) = new_obex_server(false);
650 let server_fut = obex_server.run();
651 let mut server_fut = pin!(server_fut);
652 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
653
654 let setpath_request = RequestPacket::new_set_path(SetPathFlags::BACKUP, HeaderSet::new())
655 .expect("valid request");
656 send_packet(&mut exec, &mut remote, setpath_request);
657 let result = exec
658 .run_until_stalled(&mut server_fut)
659 .expect("server terminated from invalid setpath");
660 assert_matches!(result, Err(Error::OperationError { operation: OpCode::SetPath, .. }));
661 }
662
663 #[fuchsia::test]
664 fn get_request_accepted_by_app_success() {
665 let mut exec = fasync::TestExecutor::new();
666 let (mut obex_server, test_app, mut remote) = new_obex_server(false);
667 obex_server.set_connection_status(ConnectionStatus::connected_no_id());
669 let server_fut = obex_server.run();
670 let mut server_fut = pin!(server_fut);
671 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
672
673 let get_request1 =
676 RequestPacket::new_get(HeaderSet::from_header(Header::name("random object")));
677 send_packet(&mut exec, &mut remote, get_request1);
678 test_app.set_response(Ok(HeaderSet::from_header(Header::Length(0x10))));
680 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
681
682 let expectation = |response: ResponsePacket| {
684 assert_eq!(*response.code(), ResponseCode::Continue);
685 assert!(response.headers().contains_header(&HeaderIdentifier::Length));
686 };
687 expect_response(&mut exec, &mut remote, expectation, OpCode::Get);
688
689 let get_request2 = RequestPacket::new_get_final(HeaderSet::new());
691 send_packet(&mut exec, &mut remote, get_request2);
692
693 let application_response_buf = vec![1, 2, 3, 4, 5, 6];
696 let response_headers = HeaderSet::from_header(Header::Description("foo".into()));
697 test_app.set_get_response((application_response_buf.clone(), response_headers));
698 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
699
700 let expectation = |response: ResponsePacket| {
701 assert_eq!(*response.code(), ResponseCode::Ok);
702 let mut headers = HeaderSet::from(response);
703 assert!(headers.contains_header(&HeaderIdentifier::Description));
704 let received_body = headers.remove_body(true).expect("contains body");
705 assert_eq!(received_body, application_response_buf);
706 };
707 expect_response(&mut exec, &mut remote, expectation, OpCode::GetFinal);
708 }
709
710 #[fuchsia::test]
711 fn get_request_rejected_by_app_success() {
712 let mut exec = fasync::TestExecutor::new();
713 let (mut obex_server, _test_app, mut remote) = new_obex_server(false);
714 obex_server.set_connection_status(ConnectionStatus::connected_no_id());
715 let server_fut = obex_server.run();
716 let mut server_fut = pin!(server_fut);
717 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
718
719 let headers = HeaderSet::from_header(Header::name("random object123"));
721 let get_request = RequestPacket::new_get_final(headers);
722 send_packet(&mut exec, &mut remote, get_request);
723
724 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
727 let expectation = |response: ResponsePacket| {
729 assert_eq!(*response.code(), ResponseCode::NotImplemented);
730 assert!(response.headers().is_empty());
731 };
732 expect_response(&mut exec, &mut remote, expectation, OpCode::GetFinal);
733 }
734
735 #[fuchsia::test]
736 fn get_request_with_srm_enabled_success() {
737 let mut exec = fasync::TestExecutor::new();
738 let (mut obex_server, test_app, mut remote) = new_obex_server(true);
739 obex_server.set_connection_status(ConnectionStatus::connected_no_id());
740 obex_server.set_max_packet_size(20); let server_fut = obex_server.run();
742 let mut server_fut = pin!(server_fut);
743 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
744
745 let headers1 = HeaderSet::from_headers(vec![
748 Header::name("random object"),
749 SingleResponseMode::Enable.into(),
750 ])
751 .unwrap();
752 let get_request1 = RequestPacket::new_get(headers1);
753 send_packet(&mut exec, &mut remote, get_request1);
754 test_app.set_response(Ok(HeaderSet::from_header(Header::Length(0x20))));
755 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
756 let expectation1 = |response: ResponsePacket| {
759 assert_eq!(*response.code(), ResponseCode::Continue);
760 let Header::SingleResponseMode(SingleResponseMode::Enable) =
761 response.headers().get(&HeaderIdentifier::SingleResponseMode).unwrap()
762 else {
763 panic!("Expected SRM enable in response");
764 };
765 assert!(response.headers().contains_header(&HeaderIdentifier::Length));
766 };
767 expect_response(&mut exec, &mut remote, expectation1, OpCode::Get);
768 let get_request2 = RequestPacket::new_get_final(HeaderSet::new());
772 send_packet(&mut exec, &mut remote, get_request2);
773 let application_response_buf = (0..50).collect::<Vec<u8>>();
776 test_app.set_get_response((application_response_buf, HeaderSet::new()));
777 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
778
779 let expected_bufs = vec![
782 (0..14).collect::<Vec<u8>>(),
783 (14..28).collect::<Vec<u8>>(),
784 (28..42).collect::<Vec<u8>>(),
785 ];
786 for expected_buf in expected_bufs {
787 let expectation = |response: ResponsePacket| {
788 assert_eq!(*response.code(), ResponseCode::Continue);
789 expect_body(response.headers(), expected_buf);
790 };
791 expect_response(&mut exec, &mut remote, expectation, OpCode::Get);
792 }
793
794 let final_expectation = |response: ResponsePacket| {
796 assert_eq!(*response.code(), ResponseCode::Ok);
797 expect_end_of_body(response.headers(), (42..50).collect::<Vec<u8>>());
798 };
799 expect_response(&mut exec, &mut remote, final_expectation, OpCode::GetFinal);
800 }
801
802 #[fuchsia::test]
803 fn put_request_accepted_by_app_success() {
804 let mut exec = fasync::TestExecutor::new();
805 let (mut obex_server, test_app, mut remote) = new_obex_server(false);
806 obex_server.set_connection_status(ConnectionStatus::connected_no_id());
808 let server_fut = obex_server.run();
809 let mut server_fut = pin!(server_fut);
810 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
811
812 let headers = HeaderSet::from_headers(vec![
813 Header::name("random object"),
814 Header::EndOfBody(vec![1, 2, 3, 4, 5]),
815 ])
816 .unwrap();
817 let put_request = RequestPacket::new_put_final(headers);
818 send_packet(&mut exec, &mut remote, put_request);
819
820 test_app.set_put_response(Ok(()));
822 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
823 let (rec_data, rec_headers) = test_app.put_data();
825 assert_eq!(rec_data, vec![1, 2, 3, 4, 5]);
826 assert!(rec_headers.contains_header(&HeaderIdentifier::Name));
827
828 let expectation = |response: ResponsePacket| {
829 assert_eq!(*response.code(), ResponseCode::Ok);
830 assert!(response.headers().is_empty());
831 };
832 expect_response(&mut exec, &mut remote, expectation, OpCode::PutFinal);
833 }
834
835 #[fuchsia::test]
836 fn put_request_with_srm_enabled_success() {
837 let mut exec = fasync::TestExecutor::new();
838 let (mut obex_server, test_app, mut remote) = new_obex_server(true);
839 obex_server.set_connection_status(ConnectionStatus::connected_no_id());
840 let server_fut = obex_server.run();
841 let mut server_fut = pin!(server_fut);
842 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
843
844 let headers1 = HeaderSet::from_headers(vec![
846 Header::name("my file"),
847 SingleResponseMode::Enable.into(),
848 ])
849 .unwrap();
850 let put_request1 = RequestPacket::new_put(headers1);
851 send_packet(&mut exec, &mut remote, put_request1);
852 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
853 let expectation1 = |response: ResponsePacket| {
856 assert_eq!(*response.code(), ResponseCode::Continue);
857 let Header::SingleResponseMode(SingleResponseMode::Enable) =
858 response.headers().get(&HeaderIdentifier::SingleResponseMode).unwrap()
859 else {
860 panic!("Expected SRM enable in response");
861 };
862 };
863 expect_response(&mut exec, &mut remote, expectation1, OpCode::Put);
864
865 let headers2 = HeaderSet::from_header(Header::Body(vec![1, 2, 3, 4, 5]));
867 let put_request2 = RequestPacket::new_put(headers2);
868 send_packet(&mut exec, &mut remote, put_request2);
869 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
870 expect_stream_pending(&mut exec, &mut remote);
871
872 let headers3 = HeaderSet::from_header(Header::EndOfBody(vec![6, 7, 8, 9, 10]));
875 let put_request3 = RequestPacket::new_put_final(headers3);
876 send_packet(&mut exec, &mut remote, put_request3);
877
878 test_app.set_put_response(Ok(()));
881 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
882 let (rec_data, rec_headers) = test_app.put_data();
883 assert_eq!(rec_data, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
884 assert!(rec_headers.contains_header(&HeaderIdentifier::Name));
885
886 let expectation = |response: ResponsePacket| {
887 assert_eq!(*response.code(), ResponseCode::Ok);
888 assert!(response.headers().is_empty());
889 };
890 expect_response(&mut exec, &mut remote, expectation, OpCode::PutFinal);
891 }
892
893 #[fuchsia::test]
894 fn delete_request_accepted_by_app_success() {
895 let mut exec = fasync::TestExecutor::new();
896 let (mut obex_server, test_app, mut remote) = new_obex_server(false);
897 obex_server.set_connection_status(ConnectionStatus::connected_no_id());
898 let server_fut = obex_server.run();
899 let mut server_fut = pin!(server_fut);
900 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
901
902 let headers = HeaderSet::from_header(Header::name("foo.txt"));
903 let put_request = RequestPacket::new_put_final(headers);
904 send_packet(&mut exec, &mut remote, put_request);
905
906 test_app.set_put_response(Ok(()));
908 let _ = exec.run_until_stalled(&mut server_fut).expect_pending("server active");
909
910 let expectation = |response: ResponsePacket| {
911 assert_eq!(*response.code(), ResponseCode::Ok);
912 assert!(response.headers().is_empty());
913 };
914 expect_response(&mut exec, &mut remote, expectation, OpCode::PutFinal);
915 }
916}