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