1use futures::SinkExt;
6use log::trace;
7
8use crate::client::SrmOperation;
9use crate::error::Error;
10use crate::header::{HeaderSet, SingleResponseMode};
11use crate::operation::{OpCode, RequestPacket, ResponseCode, ResponsePacket};
12use crate::transport::ObexTransport;
13
14#[must_use]
31#[derive(Debug)]
32pub struct GetOperation<'a> {
33 transport: ObexTransport<'a>,
35 headers: Option<HeaderSet>,
38 is_started: bool,
40 srm: SingleResponseMode,
43}
44
45impl<'a> GetOperation<'a> {
46 pub fn new(headers: HeaderSet, transport: ObexTransport<'a>) -> Self {
47 let srm = transport.srm_supported().into();
48 Self { transport, headers: Some(headers), is_started: false, srm }
49 }
50
51 fn set_started(&mut self) {
52 let _ = self.headers.take().unwrap();
53 self.is_started = true;
54 }
55
56 fn update_headers_before_start(
59 &mut self,
60 application_headers: &mut HeaderSet,
61 ) -> Result<(), Error> {
62 if self.is_started {
63 return Ok(());
64 }
65 let initial = self.headers.replace(HeaderSet::new()).unwrap();
67 application_headers.try_append(initial)?;
68 self.try_enable_srm(application_headers)?;
70 Ok(())
71 }
72
73 fn handle_get_response(response: ResponsePacket) -> Result<HeaderSet, Error> {
76 response.expect_code(OpCode::Get, ResponseCode::Continue).map(Into::into)
77 }
78
79 fn handle_get_final_response(
82 response: ResponsePacket,
83 ) -> Result<(bool, HeaderSet, Vec<u8>), Error> {
84 if *response.code() == ResponseCode::Ok {
86 let mut headers = HeaderSet::from(response);
88 return headers.remove_body(true).map(|eob| (true, headers, eob));
89 }
90
91 let mut headers =
93 response.expect_code(OpCode::GetFinal, ResponseCode::Continue).map(HeaderSet::from)?;
94 headers.remove_body(false).map(|b| (false, headers, b))
96 }
97
98 pub async fn get_information(&mut self, mut headers: HeaderSet) -> Result<HeaderSet, Error> {
104 self.update_headers_before_start(&mut headers)?;
106
107 if headers.is_empty() {
109 return Err(Error::operation(OpCode::Get, "missing headers"));
110 }
111
112 let srm_active = self.is_started && self.get_srm() == SingleResponseMode::Enable;
114
115 let request = RequestPacket::new_get(headers);
116 trace!(request:?; "Making outgoing GET request");
117 self.transport.send(request).await?;
118 trace!("Successfully made GET request");
119
120 let response_headers = if !srm_active {
122 let response = self.transport.receive_response(OpCode::Get).await?;
123 Self::handle_get_response(response)?
124 } else {
125 HeaderSet::new()
126 };
127 if !self.is_started {
128 self.check_response_for_srm(&response_headers);
129 self.set_started();
130 }
131 Ok(response_headers)
132 }
133
134 pub async fn get_data(mut self, mut headers: HeaderSet) -> Result<Vec<u8>, Error> {
139 self.update_headers_before_start(&mut headers)?;
141
142 let mut request = RequestPacket::new_get_final(headers);
143 let mut first_request = true;
144 let mut body = vec![];
145 loop {
146 if first_request || self.srm != SingleResponseMode::Enable {
149 trace!(request:?; "Making outgoing GET final request");
150 self.transport.send(request.clone()).await?;
151 trace!("Successfully made GET final request");
152 request = RequestPacket::new_get_final(HeaderSet::new());
154 first_request = false;
155 }
156 let response = self.transport.receive_response(OpCode::GetFinal).await?;
157 let (final_packet, response_headers, mut response_body) =
158 Self::handle_get_final_response(response)?;
159 body.append(&mut response_body);
160
161 if !self.is_started {
163 self.check_response_for_srm(&response_headers);
164 self.set_started();
165 }
166
167 if final_packet {
168 trace!("Found terminal GET final packet");
169 break;
170 }
171 }
172 Ok(body)
173 }
174
175 pub async fn terminate(mut self, headers: HeaderSet) -> Result<HeaderSet, Error> {
180 let opcode = OpCode::Abort;
181 if !self.is_started {
182 return Err(Error::operation(opcode, "can't abort when not started"));
183 }
184
185 let request = RequestPacket::new_abort(headers);
186 trace!(request:?; "Making outgoing {opcode:?} request");
187 self.transport.send(request).await?;
188 trace!("Successfully made {opcode:?} request");
189 let response = self.transport.receive_response(opcode).await?;
190 response.expect_code(opcode, ResponseCode::Ok).map(Into::into)
191 }
192}
193
194impl SrmOperation for GetOperation<'_> {
195 const OPERATION_TYPE: OpCode = OpCode::Get;
196
197 fn get_srm(&self) -> SingleResponseMode {
198 self.srm
199 }
200
201 fn set_srm(&mut self, mode: SingleResponseMode) {
202 self.srm = mode;
203 }
204}
205
206#[cfg(test)]
207mod tests {
208 use super::*;
209 use bt_channel_test_support::Transport;
210 use test_case::test_case;
211
212 use assert_matches::assert_matches;
213 use async_test_helpers::expect_stream_pending;
214 use async_utils::PollExt;
215 use fuchsia_async as fasync;
216 use std::pin::pin;
217
218 use crate::error::PacketError;
219 use crate::header::{Header, HeaderIdentifier};
220 use crate::transport::ObexTransportManager;
221 use crate::transport::test_utils::{
222 expect_code, expect_request, expect_request_and_reply, new_manager, reply,
223 };
224
225 fn setup_get_operation(mgr: &ObexTransportManager, initial: HeaderSet) -> GetOperation<'_> {
226 let transport = mgr.try_new_operation().expect("can start operation");
227 GetOperation::new(initial, transport)
228 }
229
230 #[test_case(Transport::Socket ; "socket")]
231 #[test_case(Transport::Fidl ; "fidl")]
232 #[fuchsia::test]
233 fn get_operation(transport: Transport) {
234 let mut exec = fasync::TestExecutor::new();
235 let (manager, mut remote) = new_manager(transport, false);
236 let mut operation = setup_get_operation(&manager, HeaderSet::new());
237 assert!(!operation.is_started);
238
239 {
242 let info_headers = HeaderSet::from_header(Header::name("text"));
243 let info_fut = operation.get_information(info_headers);
244 let mut info_fut = pin!(info_fut);
245 exec.run_until_stalled(&mut info_fut).expect_pending("waiting for peer response");
246 let response_headers = HeaderSet::from_header(Header::name("bar"));
247 let response = ResponsePacket::new_no_data(ResponseCode::Continue, response_headers);
248 let expectation = |request: RequestPacket| {
249 assert_eq!(*request.code(), OpCode::Get);
250 let headers = HeaderSet::from(request);
251 assert!(headers.contains_header(&HeaderIdentifier::Name));
252 };
253 expect_request_and_reply(&mut exec, &mut remote, expectation, response);
254 let received_headers = exec
255 .run_until_stalled(&mut info_fut)
256 .expect("response received")
257 .expect("valid response");
258 assert!(received_headers.contains_header(&HeaderIdentifier::Name));
259 }
260 assert!(operation.is_started);
261
262 {
265 let info_headers = HeaderSet::from_header(Header::Type("file".into()));
266 let info_fut = operation.get_information(info_headers);
267 let mut info_fut = pin!(info_fut);
268 exec.run_until_stalled(&mut info_fut).expect_pending("waiting for peer response");
269 let response_headers = HeaderSet::from_header(Header::Description("big file".into()));
270 let response = ResponsePacket::new_no_data(ResponseCode::Continue, response_headers);
271 expect_request_and_reply(&mut exec, &mut remote, expect_code(OpCode::Get), response);
272 let received_headers = exec
273 .run_until_stalled(&mut info_fut)
274 .expect("response received")
275 .expect("valid response");
276 assert!(received_headers.contains_header(&HeaderIdentifier::Description));
277 }
278
279 let data_fut = operation.get_data(HeaderSet::new());
283 let mut data_fut = pin!(data_fut);
284 exec.run_until_stalled(&mut data_fut).expect_pending("waiting for peer response");
285 let response_headers1 = HeaderSet::from_header(Header::Body(vec![1, 2, 3]));
286 let response1 = ResponsePacket::new_no_data(ResponseCode::Continue, response_headers1);
287 expect_request_and_reply(&mut exec, &mut remote, expect_code(OpCode::GetFinal), response1);
288 exec.run_until_stalled(&mut data_fut)
289 .expect_pending("waiting for additional peer responses");
290 let response_headers2 = HeaderSet::from_header(Header::EndOfBody(vec![4, 5, 6]));
292 let response2 = ResponsePacket::new_no_data(ResponseCode::Ok, response_headers2);
293 expect_request_and_reply(&mut exec, &mut remote, expect_code(OpCode::GetFinal), response2);
294 let user_data = exec
296 .run_until_stalled(&mut data_fut)
297 .expect("received all responses")
298 .expect("valid user data");
299 assert_eq!(user_data, vec![1, 2, 3, 4, 5, 6]);
300 }
301
302 #[fuchsia::test]
303 fn get_operation_terminate_success() {
304 let mut exec = fasync::TestExecutor::new();
305 let (manager, mut remote) = new_manager(Transport::Socket, false);
306 let initial = HeaderSet::from_header(Header::name("foo"));
307 let mut operation = setup_get_operation(&manager, initial);
308
309 operation.set_started();
311
312 let headers = HeaderSet::from_header(Header::name("terminated"));
314 let terminate_fut = operation.terminate(headers);
315 let mut terminate_fut = pin!(terminate_fut);
316 let _ =
317 exec.run_until_stalled(&mut terminate_fut).expect_pending("waiting for peer response");
318 let response = ResponsePacket::new_no_data(ResponseCode::Ok, HeaderSet::new());
319 expect_request_and_reply(&mut exec, &mut remote, expect_code(OpCode::Abort), response);
320 }
321
322 #[fuchsia::test]
323 fn get_operation_srm() {
324 let mut exec = fasync::TestExecutor::new();
325 let (manager, mut remote) = new_manager(Transport::Socket, true);
326 let mut operation = setup_get_operation(&manager, HeaderSet::new());
327
328 {
331 let info_headers = HeaderSet::from_header(Header::name("foo"));
332 let info_fut = operation.get_information(info_headers);
333 let mut info_fut = pin!(info_fut);
334 exec.run_until_stalled(&mut info_fut).expect_pending("waiting for peer response");
335 let response_headers = HeaderSet::from_headers(vec![
336 Header::name("bar"),
337 SingleResponseMode::Enable.into(),
338 ])
339 .unwrap();
340 let response = ResponsePacket::new_no_data(ResponseCode::Continue, response_headers);
341 let expectation = |request: RequestPacket| {
342 assert_eq!(*request.code(), OpCode::Get);
343 let headers = HeaderSet::from(request);
344 assert!(headers.contains_header(&HeaderIdentifier::Name));
345 assert!(headers.contains_header(&HeaderIdentifier::SingleResponseMode));
346 };
347 expect_request_and_reply(&mut exec, &mut remote, expectation, response);
348 let _received_headers = exec
349 .run_until_stalled(&mut info_fut)
350 .expect("response received")
351 .expect("valid response");
352 }
353 assert!(operation.is_started);
354 assert_eq!(operation.srm, SingleResponseMode::Enable);
355
356 {
360 let info_headers = HeaderSet::from_header(Header::Type("file".into()));
361 let info_fut = operation.get_information(info_headers);
362 let mut info_fut = pin!(info_fut);
363 let received_headers = exec
364 .run_until_stalled(&mut info_fut)
365 .expect("ready without peer response")
366 .expect("successful request");
367 assert_eq!(received_headers, HeaderSet::new());
368 let expectation = |request: RequestPacket| {
369 assert_eq!(*request.code(), OpCode::Get);
370 let headers = HeaderSet::from(request);
371 assert!(headers.contains_header(&HeaderIdentifier::Type));
372 assert!(!headers.contains_header(&HeaderIdentifier::SingleResponseMode));
373 };
374 expect_request(&mut exec, &mut remote, expectation);
375 }
376
377 let data_fut = operation.get_data(HeaderSet::new());
380 let mut data_fut = pin!(data_fut);
381 exec.run_until_stalled(&mut data_fut).expect_pending("waiting for peer response");
382 let response_headers1 = HeaderSet::from_header(Header::Body(vec![1, 2, 3]));
383 let response1 = ResponsePacket::new_no_data(ResponseCode::Continue, response_headers1);
384 expect_request_and_reply(&mut exec, &mut remote, expect_code(OpCode::GetFinal), response1);
385 exec.run_until_stalled(&mut data_fut)
386 .expect_pending("waiting for additional peer responses");
387 let response_headers2 = HeaderSet::from_header(Header::Body(vec![4, 5, 6]));
389 let response2 = ResponsePacket::new_no_data(ResponseCode::Continue, response_headers2);
390 expect_stream_pending(&mut exec, &mut remote);
391 reply(&mut exec, &mut remote, response2);
392 let response_headers3 = HeaderSet::from_header(Header::EndOfBody(vec![7, 8, 9]));
394 let response3 = ResponsePacket::new_no_data(ResponseCode::Ok, response_headers3);
395 expect_stream_pending(&mut exec, &mut remote);
396 reply(&mut exec, &mut remote, response3);
397 let user_data = exec
399 .run_until_stalled(&mut data_fut)
400 .expect("received all responses")
401 .expect("valid user data");
402 assert_eq!(user_data, vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
403 }
404
405 #[fuchsia::test]
406 fn client_disable_srm_mid_get_is_ignored() {
407 let mut exec = fasync::TestExecutor::new();
408 let (manager, mut remote) = new_manager(Transport::Socket, true);
409 let transport = manager.try_new_operation().expect("can start operation");
410 let mut operation = GetOperation::new(HeaderSet::new(), transport);
411 operation.set_started();
413 assert_eq!(operation.srm, SingleResponseMode::Enable);
414
415 {
418 let info_headers = HeaderSet::from_header(SingleResponseMode::Disable.into());
419 let info_fut = operation.get_information(info_headers);
420 let mut info_fut = pin!(info_fut);
421 let received_headers = exec
422 .run_until_stalled(&mut info_fut)
423 .expect("ready without peer response")
424 .expect("successful request");
425 assert_eq!(received_headers, HeaderSet::new());
426 expect_request(&mut exec, &mut remote, expect_code(OpCode::Get));
427 }
428 assert_eq!(operation.srm, SingleResponseMode::Enable);
429 }
430
431 #[fuchsia::test]
432 fn get_operation_information_error() {
433 let mut exec = fasync::TestExecutor::new();
434 let (manager, _remote) = new_manager(Transport::Socket, false);
435 let initial = HeaderSet::from_header(Header::name("foo"));
436 let mut operation = setup_get_operation(&manager, initial);
437
438 operation.set_started();
440
441 let get_info_fut = operation.get_information(HeaderSet::new());
443 let mut get_info_fut = pin!(get_info_fut);
444 let get_info_result =
445 exec.run_until_stalled(&mut get_info_fut).expect("resolves with error");
446 assert_matches!(get_info_result, Err(Error::OperationError { .. }));
447 }
448
449 #[fuchsia::test]
450 fn get_operation_data_before_start_is_ok() {
451 let mut exec = fasync::TestExecutor::new();
452 let (manager, mut remote) = new_manager(Transport::Socket, false);
453 let initial = HeaderSet::from_header(Header::name("foo"));
454 let operation = setup_get_operation(&manager, initial);
455
456 let get_data_fut = operation.get_data(HeaderSet::new());
458 let mut get_data_fut = pin!(get_data_fut);
459 exec.run_until_stalled(&mut get_data_fut).expect_pending("waiting for peer response");
460 let response_headers = HeaderSet::from_header(Header::EndOfBody(vec![1, 2, 3]));
461 let response = ResponsePacket::new_no_data(ResponseCode::Ok, response_headers);
462 let expectation = |request: RequestPacket| {
463 assert_eq!(*request.code(), OpCode::GetFinal);
464 let headers = HeaderSet::from(request);
465 assert!(headers.contains_header(&HeaderIdentifier::Name));
466 };
467 expect_request_and_reply(&mut exec, &mut remote, expectation, response);
468 let user_data = exec
469 .run_until_stalled(&mut get_data_fut)
470 .expect("received all responses")
471 .expect("valid user data");
472 assert_eq!(user_data, vec![1, 2, 3]);
473 }
474
475 #[fuchsia::test]
476 fn get_operation_data_before_start_with_srm_is_ok() {
477 let mut exec = fasync::TestExecutor::new();
478 let (manager, mut remote) = new_manager(Transport::Socket, true);
479 let operation = setup_get_operation(&manager, HeaderSet::new());
480
481 let get_data_fut = operation.get_data(HeaderSet::new());
483 let mut get_data_fut = pin!(get_data_fut);
484 exec.run_until_stalled(&mut get_data_fut).expect_pending("waiting for peer response");
485 let response_headers1 = HeaderSet::from_headers(vec![
486 Header::Body(vec![1, 1]),
487 Header::SingleResponseMode(SingleResponseMode::Enable.into()),
488 ])
489 .unwrap();
490 let response1 = ResponsePacket::new_no_data(ResponseCode::Continue, response_headers1);
491 let expectation = |request: RequestPacket| {
492 assert_eq!(*request.code(), OpCode::GetFinal);
493 let headers = HeaderSet::from(request);
494 assert!(headers.contains_header(&HeaderIdentifier::SingleResponseMode));
495 };
496 expect_request_and_reply(&mut exec, &mut remote, expectation, response1);
497 exec.run_until_stalled(&mut get_data_fut)
498 .expect_pending("waiting for additional peer responses");
499
500 let response_headers2 = HeaderSet::from_header(Header::Body(vec![2, 2]));
502 let response2 = ResponsePacket::new_no_data(ResponseCode::Continue, response_headers2);
503 expect_stream_pending(&mut exec, &mut remote);
504 reply(&mut exec, &mut remote, response2);
505
506 let response_headers3 = HeaderSet::from_header(Header::EndOfBody(vec![3, 3]));
508 let response3 = ResponsePacket::new_no_data(ResponseCode::Ok, response_headers3);
509 expect_stream_pending(&mut exec, &mut remote);
510 reply(&mut exec, &mut remote, response3);
511 let user_data = exec
513 .run_until_stalled(&mut get_data_fut)
514 .expect("received all responses")
515 .expect("valid user data");
516 assert_eq!(user_data, vec![1, 1, 2, 2, 3, 3]);
517 }
518
519 #[fuchsia::test]
520 fn get_operation_data_peer_disconnect_is_error() {
521 let mut exec = fasync::TestExecutor::new();
522 let (manager, remote) = new_manager(Transport::Socket, false);
523 let initial = HeaderSet::from_header(Header::name("foo"));
524 let mut operation = setup_get_operation(&manager, initial);
525 operation.set_started();
527
528 drop(remote);
530 let get_data_fut = operation.get_data(HeaderSet::new());
531 let mut get_data_fut = pin!(get_data_fut);
532 let get_data_result =
533 exec.run_until_stalled(&mut get_data_fut).expect("resolves with error");
534 assert_matches!(get_data_result, Err(Error::IOError(_)));
535 }
536
537 #[fuchsia::test]
538 async fn get_operation_terminate_before_start_error() {
539 let (manager, _remote) = new_manager(Transport::Socket, false);
540 let initial = HeaderSet::from_header(Header::name("bar"));
541 let operation = setup_get_operation(&manager, initial);
542
543 let terminate_result = operation.terminate(HeaderSet::new()).await;
545 assert_matches!(terminate_result, Err(Error::OperationError { .. }));
546 }
547
548 #[fuchsia::test]
549 fn handle_get_response_success() {
550 let headers = HeaderSet::from_header(Header::name("foo"));
551 let response = ResponsePacket::new_no_data(ResponseCode::Continue, headers.clone());
552 let result = GetOperation::handle_get_response(response).expect("valid response");
553 assert_eq!(result, headers);
554 }
555
556 #[fuchsia::test]
557 fn handle_get_response_error() {
558 let headers = HeaderSet::from_header(Header::name("foo"));
559 let response1 = ResponsePacket::new_no_data(ResponseCode::Ok, headers.clone());
561 assert_matches!(
562 GetOperation::handle_get_response(response1),
563 Err(Error::PeerRejected { .. })
564 );
565
566 let response1 = ResponsePacket::new_no_data(ResponseCode::NotFound, headers);
568 assert_matches!(
569 GetOperation::handle_get_response(response1),
570 Err(Error::PeerRejected { .. })
571 );
572 }
573
574 #[fuchsia::test]
575 fn handle_get_final_response_success() {
576 let headers = HeaderSet::from_header(Header::EndOfBody(vec![1, 2]));
577 let response1 = ResponsePacket::new_no_data(ResponseCode::Ok, headers);
578 let result1 = GetOperation::handle_get_final_response(response1).expect("valid response");
579 assert_eq!(result1, (true, HeaderSet::new(), vec![1, 2]));
580
581 let headers = HeaderSet::from_header(Header::Body(vec![1, 3, 5]));
582 let response2 = ResponsePacket::new_no_data(ResponseCode::Continue, headers);
583 let result2 = GetOperation::handle_get_final_response(response2).expect("valid response");
584 assert_eq!(result2, (false, HeaderSet::new(), vec![1, 3, 5]));
585 }
586
587 #[fuchsia::test]
588 fn get_final_response_error() {
589 let headers = HeaderSet::from_header(Header::EndOfBody(vec![1, 2]));
591 let response1 = ResponsePacket::new_no_data(ResponseCode::Forbidden, headers);
592 assert_matches!(
593 GetOperation::handle_get_final_response(response1),
594 Err(Error::PeerRejected { .. })
595 );
596
597 let response2 = ResponsePacket::new_no_data(ResponseCode::Ok, HeaderSet::new());
599 assert_matches!(
600 GetOperation::handle_get_final_response(response2),
601 Err(Error::Packet(PacketError::Data(_)))
602 );
603
604 let response3 = ResponsePacket::new_no_data(ResponseCode::Continue, HeaderSet::new());
606 assert_matches!(
607 GetOperation::handle_get_final_response(response3),
608 Err(Error::Packet(PacketError::Data(_)))
609 );
610 }
611}