1use log::{trace, warn};
6use packet_encoding::Encodable;
7use std::collections::VecDeque;
8
9use crate::error::Error;
10use crate::header::{Header, HeaderSet, SingleResponseMode};
11use crate::operation::{OpCode, RequestPacket, ResponseCode, ResponsePacket};
12use crate::server::handler::ObexOperationError;
13use crate::server::{ApplicationResponse, OperationRequest, ServerOperation};
14
15const BODY_HEADER_PREFIX_LENGTH_BYTES: usize = 3;
17
18#[derive(Debug, PartialEq)]
20struct StagedData {
21 first: Option<Option<Vec<u8>>>,
26 rest: VecDeque<Vec<u8>>,
30}
31
32impl StagedData {
33 fn new(first: Option<Vec<u8>>, rest: VecDeque<Vec<u8>>) -> Self {
34 Self { first: Some(first), rest }
35 }
36
37 fn empty() -> Self {
38 Self { first: None, rest: VecDeque::new() }
39 }
40
41 fn from_data(
47 mut data: Vec<u8>,
48 max_headers_size: u16,
49 headers_size: usize,
50 ) -> Result<Self, Error> {
51 let max_headers_size = max_headers_size as usize;
52 if headers_size > max_headers_size {
54 warn!("Too many headers in GET");
55 return Err(Error::operation(OpCode::Get, "too many headers"));
58 }
59
60 if max_headers_size <= BODY_HEADER_PREFIX_LENGTH_BYTES {
64 return Err(Error::operation(OpCode::Get, "max_headers_size too small"));
65 }
66
67 let max_first_data_packet_size = max_headers_size - headers_size;
70
71 let data_encoded_len = data.len() + BODY_HEADER_PREFIX_LENGTH_BYTES;
73 if data_encoded_len <= max_first_data_packet_size {
74 return Ok(Self::new(Some(data), VecDeque::new()));
75 }
76
77 let first_chunk_size =
79 max_first_data_packet_size.checked_sub(BODY_HEADER_PREFIX_LENGTH_BYTES);
80 let (first, remaining) = if let Some(max) = first_chunk_size {
81 let remaining = data.split_off(max);
82 (Some(data), remaining)
83 } else {
84 (None, data)
86 };
87
88 let max_data_packet_size = max_headers_size - BODY_HEADER_PREFIX_LENGTH_BYTES;
90 let mut chunks = VecDeque::new();
92 for chunk in remaining.chunks(max_data_packet_size as usize) {
93 chunks.push_back(chunk.to_vec());
94 }
95 Ok(Self::new(first, chunks))
96 }
97
98 #[cfg(test)]
100 fn is_first_response(&self) -> bool {
101 self.first.is_some()
102 }
103
104 fn is_complete(&self) -> bool {
106 self.first.is_none() && self.rest.is_empty()
107 }
108
109 fn next_response(&mut self, mut headers: HeaderSet) -> Result<ResponsePacket, Error> {
113 if self.is_complete() {
114 return Err(Error::operation(OpCode::Get, "staged data is already complete"));
115 }
116
117 let chunk = if let Some(first_packet) = self.first.take() {
118 first_packet
120 } else {
121 Some(self.rest.pop_front().unwrap_or(vec![]))
123 };
124
125 let (code, h) = if self.rest.is_empty() {
128 (ResponseCode::Ok, chunk.map(|p| Header::EndOfBody(p)))
129 } else {
130 (ResponseCode::Continue, chunk.map(|p| Header::Body(p)))
131 };
132
133 if let Some(header) = h {
134 headers.add(header)?;
135 }
136 Ok(ResponsePacket::new_get(code, headers))
137 }
138
139 fn all_responses(
142 &mut self,
143 mut initial_headers: HeaderSet,
144 ) -> Result<Vec<ResponsePacket>, Error> {
145 let mut responses = Vec::new();
146 while !self.is_complete() {
147 let headers = std::mem::replace(&mut initial_headers, HeaderSet::new());
150 let response = self.next_response(headers)?;
151 responses.push(response);
152 }
153 Ok(responses)
154 }
155}
156
157#[derive(Debug)]
159enum State {
160 Request { headers: HeaderSet },
165 RequestPhaseComplete,
170 Response { staged_data: StagedData },
174 Complete,
177}
178
179enum SrmState {
181 NotNegotiated { srm_supported: bool },
184 Negotiating { negotiated_srm: SingleResponseMode },
187 Negotiated { srm: SingleResponseMode },
190}
191
192pub struct GetOperation {
194 max_headers_size: u16,
197 srm_state: SrmState,
201 state: State,
203}
204
205impl GetOperation {
206 pub fn new(max_packet_size: u16, srm_supported: bool) -> Self {
208 let max_headers_size = max_packet_size - ResponsePacket::MIN_PACKET_SIZE as u16;
209 Self {
210 max_headers_size,
211 srm_state: SrmState::NotNegotiated { srm_supported },
212 state: State::Request { headers: HeaderSet::new() },
213 }
214 }
215
216 #[cfg(test)]
217 fn new_at_state(max_packet_size: u16, state: State) -> Self {
218 let max_headers_size = max_packet_size - ResponsePacket::MIN_PACKET_SIZE as u16;
219 Self {
220 max_headers_size,
221 srm_state: SrmState::NotNegotiated { srm_supported: false },
222 state,
223 }
224 }
225
226 fn check_complete_and_update_state(&mut self) {
228 let State::Response { ref staged_data } = &self.state else { return };
229
230 if staged_data.is_complete() {
231 self.state = State::Complete;
232 }
233 }
234
235 fn maybe_add_srm_header(&mut self, headers: &mut HeaderSet) -> Result<bool, Error> {
240 if let SrmState::Negotiating { negotiated_srm } = self.srm_state {
241 headers.add(negotiated_srm.into())?;
242 self.srm_state = SrmState::Negotiated { srm: negotiated_srm };
243 return Ok(true);
244 }
245 Ok(false)
246 }
247}
248
249impl ServerOperation for GetOperation {
250 fn srm_status(&self) -> SingleResponseMode {
251 match self.srm_state {
253 SrmState::NotNegotiated { .. } | SrmState::Negotiating { .. } => {
254 SingleResponseMode::Disable
255 }
256 SrmState::Negotiated { srm } => srm,
257 }
258 }
259
260 fn is_complete(&self) -> bool {
261 matches!(self.state, State::Complete)
262 }
263
264 fn handle_peer_request(&mut self, request: RequestPacket) -> Result<OperationRequest, Error> {
265 let code = *request.code();
266 let current_srm_mode = self.srm_status();
270 match &mut self.state {
271 State::Request { ref mut headers } if code == OpCode::Get => {
272 let request_headers = HeaderSet::from(request);
273 match self.srm_state {
280 SrmState::Negotiated { srm: SingleResponseMode::Enable } => {
281 headers.try_append(request_headers)?;
283 return Ok(OperationRequest::None);
284 }
285 SrmState::Negotiated { srm: SingleResponseMode::Disable }
286 | SrmState::Negotiating { .. } => {}
287 SrmState::NotNegotiated { srm_supported } => {
288 if let Some(negotiated_srm) =
290 Self::check_headers_for_srm(srm_supported, &request_headers)
291 {
292 self.srm_state = SrmState::Negotiating { negotiated_srm };
295 }
296 }
297 };
298 Ok(OperationRequest::GetApplicationInfo(request_headers))
299 }
300 State::Request { ref mut headers } if code == OpCode::GetFinal => {
301 headers.try_append(HeaderSet::from(request))?;
302 if let SrmState::NotNegotiated { srm_supported } = self.srm_state {
304 if let Some(negotiated_srm) =
305 Self::check_headers_for_srm(srm_supported, &headers)
306 {
307 self.srm_state = SrmState::Negotiating { negotiated_srm };
310 }
311 }
312
313 let request_headers = std::mem::replace(headers, HeaderSet::new());
314 self.state = State::RequestPhaseComplete;
317 Ok(OperationRequest::GetApplicationData(request_headers))
318 }
319 State::Response { ref mut staged_data } if code == OpCode::GetFinal => {
320 let responses = if current_srm_mode == SingleResponseMode::Enable {
321 staged_data.all_responses(HeaderSet::new())?
322 } else {
323 vec![staged_data.next_response(HeaderSet::new())?]
324 };
325 self.check_complete_and_update_state();
326 Ok(OperationRequest::SendPackets(responses))
327 }
328 _ => Err(Error::operation(OpCode::Get, "received invalid request")),
329 }
330 }
331
332 fn handle_application_response(
333 &mut self,
334 response: Result<ApplicationResponse, ObexOperationError>,
335 ) -> Result<Vec<ResponsePacket>, Error> {
336 let response = match response {
337 Ok(response) => response,
338 Err((code, response_headers)) => {
339 trace!("Application rejected GET request: {code:?}");
340 self.state = State::Response { staged_data: StagedData::empty() };
341 self.check_complete_and_update_state();
342 return Ok(vec![ResponsePacket::new_get(code, response_headers)]);
343 }
344 };
345
346 match response {
347 ApplicationResponse::GetInfo(mut response_headers) => {
348 if !matches!(self.state, State::Request { .. }) {
349 return Err(Error::operation(OpCode::Get, "GetInfo response in invalid state"));
350 }
351 let _ = self.maybe_add_srm_header(&mut response_headers)?;
352 Ok(vec![ResponsePacket::new_get(ResponseCode::Continue, response_headers)])
353 }
354 ApplicationResponse::GetData((data, response_headers)) => {
355 if !matches!(self.state, State::RequestPhaseComplete) {
356 return Err(Error::operation(
357 OpCode::Get,
358 "Get response before request phase complete",
359 ));
360 }
361
362 let mut srm_headers = HeaderSet::new();
363 let srm_packet = if self.maybe_add_srm_header(&mut srm_headers)? {
364 Some(ResponsePacket::new_get(ResponseCode::Continue, srm_headers))
365 } else {
366 None
367 };
368
369 let mut staged_data = StagedData::from_data(
372 data,
373 self.max_headers_size,
374 response_headers.encoded_len(),
375 )?;
376
377 let responses = match (self.srm_status(), srm_packet) {
378 (SingleResponseMode::Enable, Some(packet)) => {
379 let mut packets = vec![packet];
383 packets.append(&mut staged_data.all_responses(response_headers)?);
384 packets
385 }
386 (SingleResponseMode::Disable, Some(packet)) => {
387 vec![packet]
390 }
391 (SingleResponseMode::Enable, None) => {
392 staged_data.all_responses(response_headers)?
394 }
395 (SingleResponseMode::Disable, None) => {
396 vec![staged_data.next_response(response_headers)?]
398 }
399 };
400 self.state = State::Response { staged_data };
401 self.check_complete_and_update_state();
402 Ok(responses)
403 }
404 ApplicationResponse::Put => {
405 Err(Error::operation(OpCode::Get, "invalid application response to GET request"))
406 }
407 }
408 }
409}
410
411#[cfg(test)]
412mod tests {
413 use super::*;
414
415 use assert_matches::assert_matches;
416
417 use crate::header::header_set::{expect_body, expect_end_of_body};
418 use crate::header::HeaderIdentifier;
419 use crate::server::test_utils::expect_single_packet;
420
421 fn bytes(start_idx: usize, end_idx: usize) -> Vec<u8> {
422 let s = start_idx as u8;
425 let e = end_idx as u8;
426 (s..e).collect::<Vec<u8>>()
427 }
428
429 #[track_caller]
431 fn expect_packet_with_body(
432 operation_request: OperationRequest,
433 expected_code: ResponseCode,
434 expected_body: Vec<u8>,
435 ) {
436 let packet = expect_single_packet(operation_request);
437 assert_eq!(*packet.code(), expected_code);
438 if expected_code == ResponseCode::Ok {
439 expect_end_of_body(packet.headers(), expected_body);
440 } else {
441 expect_body(packet.headers(), expected_body);
442 }
443 }
444
445 #[fuchsia::test]
446 fn single_packet_get_operation() {
447 let max_packet_size = 50;
448 let mut operation = GetOperation::new(max_packet_size, false);
449 assert!(!operation.is_complete());
450
451 let headers = HeaderSet::from_header(Header::name("default"));
453 let request = RequestPacket::new_get_final(headers);
454 let response1 = operation.handle_peer_request(request).expect("valid request");
455 assert_matches!(response1,
456 OperationRequest::GetApplicationData(headers)
457 if headers.contains_header(&HeaderIdentifier::Name)
458 );
459
460 let payload = bytes(0, 25);
463 let mut responses2 = operation
464 .handle_application_response(ApplicationResponse::accept_get(payload, HeaderSet::new()))
465 .expect("valid response");
466 let response2 = responses2.pop().expect("one response");
467 assert_eq!(*response2.code(), ResponseCode::Ok);
468 expect_end_of_body(response2.headers(), bytes(0, 25));
469 assert!(operation.is_complete());
470 }
471
472 #[fuchsia::test]
473 fn multi_packet_get_operation() {
474 let max_packet_size = 50;
475 let mut operation = GetOperation::new(max_packet_size, false);
476 assert!(!operation.is_complete());
477
478 let headers1 = HeaderSet::from_header(Header::name("foo".into()));
481 let request1 = RequestPacket::new_get(headers1);
482 let response1 = operation.handle_peer_request(request1).expect("valid request");
483 assert_matches!(response1, OperationRequest::GetApplicationInfo(headers) if headers.contains_header(&HeaderIdentifier::Name));
484
485 let info_headers = HeaderSet::from_header(Header::Description("ok".into()));
488 let response2 = operation
489 .handle_application_response(ApplicationResponse::accept_get_info(info_headers))
490 .expect("valid request");
491 assert_eq!(response2.len(), 1);
492 assert_eq!(*response2[0].code(), ResponseCode::Continue);
493 assert!(response2[0].headers().contains_header(&HeaderIdentifier::Description));
494
495 let headers3 = HeaderSet::from_header(Header::Type("text/x-vCard".into()));
499 let request3 = RequestPacket::new_get_final(headers3);
500 let response3 = operation.handle_peer_request(request3).expect("valid request");
501 assert_matches!(response3,
502 OperationRequest::GetApplicationData(headers)
503 if headers.contains_header(&HeaderIdentifier::Type)
504 );
505
506 let payload = bytes(0, 200);
512 let response_headers = HeaderSet::from_header(Header::Description("random payload".into()));
513 let response_packets4 = operation
514 .handle_application_response(ApplicationResponse::accept_get(payload, response_headers))
515 .expect("valid response");
516 assert_eq!(response_packets4.len(), 1);
517 assert_eq!(*response_packets4[0].code(), ResponseCode::Continue);
518 expect_body(response_packets4[0].headers(), bytes(0, 11));
519
520 let expected_bytes =
523 vec![bytes(11, 55), bytes(55, 99), bytes(99, 143), bytes(143, 187), bytes(187, 200)];
524 for (i, expected) in expected_bytes.into_iter().enumerate() {
525 let expected_code = if i == 4 { ResponseCode::Ok } else { ResponseCode::Continue };
526 let request = RequestPacket::new_get_final(HeaderSet::new());
527 let response = operation.handle_peer_request(request).expect("valid request");
528 expect_packet_with_body(response, expected_code, expected);
529 }
530 assert!(operation.is_complete());
531 }
532
533 #[fuchsia::test]
534 fn multi_packet_get_operation_srm_enabled() {
535 let max_packet_size = 50;
536 let mut operation = GetOperation::new(max_packet_size, true);
537 assert!(!operation.is_complete());
538 assert_eq!(operation.srm_status(), SingleResponseMode::Disable);
539
540 let headers1 = HeaderSet::from_headers(vec![
543 Header::name("foo".into()),
544 SingleResponseMode::Enable.into(),
545 ])
546 .unwrap();
547 let request1 = RequestPacket::new_get(headers1);
548 let response1 = operation.handle_peer_request(request1).expect("valid request");
549 assert_matches!(response1, OperationRequest::GetApplicationInfo(headers) if headers.contains_header(&HeaderIdentifier::Name));
550
551 let info_headers = HeaderSet::from_header(Header::Description("ok".into()));
554 let response2 = operation
555 .handle_application_response(ApplicationResponse::accept_get_info(info_headers))
556 .expect("valid request");
557 assert_eq!(response2.len(), 1);
558 assert_eq!(*response2[0].code(), ResponseCode::Continue);
559 assert!(response2[0].headers().contains_header(&HeaderIdentifier::Description));
560 assert!(response2[0].headers().contains_header(&HeaderIdentifier::SingleResponseMode));
561 assert_eq!(operation.srm_status(), SingleResponseMode::Enable);
563
564 let headers3 = HeaderSet::from_header(Header::Description("random payload".into()));
567 let request3 = RequestPacket::new_get(headers3);
568 let response3 = operation.handle_peer_request(request3).expect("valid request");
569 assert_matches!(response3, OperationRequest::None);
570
571 let headers4 = HeaderSet::from_header(Header::Type("text/x-vCard".into()));
575 let request4 = RequestPacket::new_get_final(headers4);
576 let response4 = operation.handle_peer_request(request4).expect("valid request");
577 assert_matches!(response4,
578 OperationRequest::GetApplicationData(headers)
579 if
580 headers.contains_header(&HeaderIdentifier::Type)
581 && headers.contains_header(&HeaderIdentifier::Description)
582 );
583
584 let payload = bytes(0, 100);
588 let response_headers = HeaderSet::from_header(Header::Description("random payload".into()));
589 let response_packets = operation
590 .handle_application_response(ApplicationResponse::accept_get(payload, response_headers))
591 .expect("valid response");
592 assert_eq!(response_packets.len(), 4);
593 assert_eq!(*response_packets[0].code(), ResponseCode::Continue);
596 expect_body(response_packets[0].headers(), bytes(0, 11));
597
598 let expected_bytes = [bytes(11, 55), bytes(55, 99), bytes(99, 100)];
601 for (i, expected) in expected_bytes.into_iter().enumerate() {
602 let idx = i + 1;
604 let expected_code = if idx == 3 { ResponseCode::Ok } else { ResponseCode::Continue };
606 assert_eq!(*response_packets[idx].code(), expected_code);
607 if expected_code == ResponseCode::Ok {
608 expect_end_of_body(response_packets[idx].headers(), expected);
609 } else {
610 expect_body(response_packets[idx].headers(), expected);
611 }
612 }
613
614 assert!(operation.is_complete());
616 }
617
618 #[fuchsia::test]
621 fn srm_enable_request_during_get_final_success() {
622 let max_packet_size = 50;
623 let mut operation = GetOperation::new(max_packet_size, true);
624
625 let headers1 = HeaderSet::from_header(SingleResponseMode::Enable.into());
628 let request1 = RequestPacket::new_get_final(headers1);
629 let response1 = operation.handle_peer_request(request1).expect("valid request");
630 assert_matches!(response1, OperationRequest::GetApplicationData(_));
631 assert!(!operation.is_complete());
632
633 let payload = bytes(0, 90);
636 let response_headers = HeaderSet::from_header(Header::Description("random payload".into()));
637 let response_packets = operation
638 .handle_application_response(ApplicationResponse::accept_get(payload, response_headers))
639 .expect("valid response");
640 assert_eq!(response_packets.len(), 4);
641 assert_eq!(*response_packets[0].code(), ResponseCode::Continue);
642 assert!(response_packets[0]
643 .headers()
644 .contains_header(&HeaderIdentifier::SingleResponseMode));
645 assert!(!response_packets[0].headers().contains_header(&HeaderIdentifier::Description));
647 assert!(!response_packets[0].headers().contains_header(&HeaderIdentifier::Body));
648 assert_eq!(operation.srm_status(), SingleResponseMode::Enable);
649
650 assert!(response_packets[1].headers().contains_header(&HeaderIdentifier::Description));
654 expect_body(response_packets[1].headers(), bytes(0, 11));
655 expect_body(response_packets[2].headers(), bytes(11, 55));
656 expect_end_of_body(response_packets[3].headers(), bytes(55, 90));
657 assert!(operation.is_complete());
658 }
659
660 #[fuchsia::test]
661 fn srm_disable_request_during_get_final_success() {
662 let max_packet_size = 50;
663 let mut operation = GetOperation::new(max_packet_size, false);
664
665 let headers1 = HeaderSet::from_header(SingleResponseMode::Enable.into());
668 let request1 = RequestPacket::new_get_final(headers1);
669 let response1 = operation.handle_peer_request(request1).expect("valid request");
670 assert_matches!(response1, OperationRequest::GetApplicationData(_));
671 assert!(!operation.is_complete());
672
673 let payload = bytes(0, 90);
676 let response_packets = operation
677 .handle_application_response(ApplicationResponse::accept_get(payload, HeaderSet::new()))
678 .expect("valid response");
679 assert_eq!(response_packets.len(), 1);
680 assert_eq!(*response_packets[0].code(), ResponseCode::Continue);
681 let received_srm = response_packets[0]
682 .headers()
683 .get(&HeaderIdentifier::SingleResponseMode)
684 .expect("contains SRM");
685 assert_eq!(*received_srm, Header::SingleResponseMode(SingleResponseMode::Disable));
686 assert!(!response_packets[0].headers().contains_header(&HeaderIdentifier::Body));
688 assert_eq!(operation.srm_status(), SingleResponseMode::Disable);
689
690 let expected_bytes = vec![bytes(0, 44), bytes(44, 88), bytes(88, 90)];
692 for (i, expected) in expected_bytes.into_iter().enumerate() {
693 let expected_code = if i == 2 { ResponseCode::Ok } else { ResponseCode::Continue };
694 let request2 = RequestPacket::new_get_final(HeaderSet::new());
695 let response2 = operation.handle_peer_request(request2).expect("valid request");
696 expect_packet_with_body(response2, expected_code, expected);
697 }
698 assert!(operation.is_complete());
699 }
700
701 #[fuchsia::test]
702 fn application_rejects_request_success() {
703 let mut operation = GetOperation::new_at_state(10, State::RequestPhaseComplete);
704 let headers = HeaderSet::from_header(Header::Description("not allowed today".into()));
705 let response_packets = operation
706 .handle_application_response(Err((ResponseCode::Forbidden, headers)))
707 .expect("rejection is ok");
708 assert_eq!(*response_packets[0].code(), ResponseCode::Forbidden);
709 assert!(response_packets[0].headers().contains_header(&HeaderIdentifier::Description));
710 assert!(operation.is_complete());
711 }
712
713 #[fuchsia::test]
714 fn handle_application_response_error() {
715 let max_packet_size = 15;
716 let mut operation = GetOperation::new(max_packet_size, false);
718 let data = vec![1, 2, 3];
719 assert_matches!(
720 operation.handle_application_response(ApplicationResponse::accept_get(
721 data,
722 HeaderSet::new()
723 )),
724 Err(Error::OperationError { .. })
725 );
726
727 let mut operation = GetOperation::new_at_state(10, State::RequestPhaseComplete);
729 assert_matches!(
730 operation.handle_application_response(ApplicationResponse::accept_get_info(
731 HeaderSet::new()
732 )),
733 Err(Error::OperationError { .. })
734 );
735 }
736
737 #[fuchsia::test]
738 fn non_get_request_is_error() {
739 let mut operation = GetOperation::new(50, false);
740 let random_request1 = RequestPacket::new_put(HeaderSet::new());
741 assert_matches!(
742 operation.handle_peer_request(random_request1),
743 Err(Error::OperationError { .. })
744 );
745
746 let random_request2 = RequestPacket::new_disconnect(HeaderSet::new());
747 assert_matches!(
748 operation.handle_peer_request(random_request2),
749 Err(Error::OperationError { .. })
750 );
751 }
752
753 #[fuchsia::test]
754 fn get_request_invalid_state_is_error() {
755 let random_headers = HeaderSet::from_header(Header::name("foo".into()));
756
757 let mut operation1 = GetOperation::new_at_state(10, State::RequestPhaseComplete);
760 let request1 = RequestPacket::new_get(random_headers.clone());
761 let response1 = operation1.handle_peer_request(request1);
762 assert_matches!(response1, Err(Error::OperationError { .. }));
763
764 let mut operation2 = GetOperation::new_at_state(10, State::Complete);
766 let request2 = RequestPacket::new_get(random_headers.clone());
767 let response2 = operation2.handle_peer_request(request2);
768 assert_matches!(response2, Err(Error::OperationError { .. }));
769
770 let staged_data = StagedData { first: None, rest: VecDeque::from(vec![vec![1, 2, 3]]) };
772 let mut operation3 = GetOperation::new_at_state(10, State::Response { staged_data });
773 let request3 = RequestPacket::new_get(random_headers);
774 let response3 = operation3.handle_peer_request(request3);
775 assert_matches!(response3, Err(Error::OperationError { .. }));
776 }
777
778 #[fuchsia::test]
779 fn build_staged_data_success() {
780 let empty_data = Vec::new();
782 let empty_headers = HeaderSet::new();
783 let result = StagedData::from_data(empty_data, 50, empty_headers.encoded_len())
784 .expect("can divide data");
785 let expected = StagedData { first: Some(Some(vec![])), rest: VecDeque::new() };
786 assert_eq!(result, expected);
787
788 let headers = HeaderSet::from_header(Header::name("foo".into()));
790 let data = vec![1, 2, 3];
791 let result =
792 StagedData::from_data(data, 50, headers.encoded_len()).expect("can divide data");
793 let expected = StagedData { first: Some(Some(vec![1, 2, 3])), rest: VecDeque::new() };
794 assert_eq!(result, expected);
795
796 let headers = HeaderSet::from_header(Header::Http(vec![5, 5, 5]));
799 let max = 10;
800 let large_data = (0..50).collect::<Vec<u8>>();
801 let result =
802 StagedData::from_data(large_data, max, headers.encoded_len()).expect("can divide data");
803 let first = Some(vec![0]);
804 let rest = VecDeque::from(vec![
805 bytes(1, 8),
806 bytes(8, 15),
807 bytes(15, 22),
808 bytes(22, 29),
809 bytes(29, 36),
810 bytes(36, 43),
811 bytes(43, 50),
812 ]);
813 let expected = StagedData { first: Some(first), rest };
814 assert_eq!(result, expected);
815 }
816
817 #[fuchsia::test]
818 fn build_staged_data_error() {
819 let random_data = bytes(0, 50);
820
821 let too_small_max = 2;
823 assert_matches!(
824 StagedData::from_data(random_data.clone(), too_small_max, 0),
825 Err(Error::OperationError { .. })
826 );
827 assert_matches!(
828 StagedData::from_data(random_data.clone(), 0, 0),
829 Err(Error::OperationError { .. })
830 );
831
832 let small_max = 10;
835 let large_header_size = 20;
836 assert_matches!(
837 StagedData::from_data(random_data, small_max, large_header_size),
838 Err(Error::OperationError { .. })
839 );
840 }
841
842 #[fuchsia::test]
843 fn empty_staged_data_success() {
844 let empty = Vec::new();
845 let empty_headers = HeaderSet::new();
846 let mut staged = StagedData::from_data(empty.clone(), 50, empty_headers.encoded_len())
847 .expect("can construct");
848 assert!(staged.is_first_response());
849 assert!(!staged.is_complete());
850 let response = staged.next_response(empty_headers).expect("has first response");
851 assert_eq!(*response.code(), ResponseCode::Ok);
852 expect_end_of_body(response.headers(), vec![]);
853 assert!(!staged.is_first_response());
854 assert!(staged.is_complete());
855 }
856
857 #[fuchsia::test]
858 fn single_packet_staged_data_success() {
859 let single = vec![1, 2, 3];
860 let empty_headers = HeaderSet::new();
861 let mut staged = StagedData::from_data(single.clone(), 50, empty_headers.encoded_len())
862 .expect("can construct");
863 let response = staged.next_response(empty_headers).expect("has first response");
864 assert_eq!(*response.code(), ResponseCode::Ok);
865 expect_end_of_body(response.headers(), single);
866 assert!(staged.is_complete());
867 }
868
869 #[fuchsia::test]
870 fn multi_packet_staged_data_success() {
871 let max_packet_size = 10;
872 let large_data = (0..30).collect::<Vec<u8>>();
873 let headers = HeaderSet::from_header(Header::Who(vec![1, 2, 3, 4, 5]));
874 let mut staged = StagedData::from_data(large_data, max_packet_size, headers.encoded_len())
875 .expect("can construct");
876 let response1 = staged.next_response(headers).expect("has first response");
877 assert_eq!(*response1.code(), ResponseCode::Continue);
878 assert!(response1.headers().contains_header(&HeaderIdentifier::Who));
880 assert!(!response1.headers().contains_header(&HeaderIdentifier::Body));
881 assert!(!staged.is_complete());
882
883 let expected_bytes = vec![bytes(0, 7), bytes(7, 14), bytes(14, 21), bytes(21, 28)];
886 for expected in expected_bytes {
887 let r = staged.next_response(HeaderSet::new()).expect("has next response");
888 assert_eq!(*r.code(), ResponseCode::Continue);
889 expect_body(r.headers(), expected);
890 }
891
892 let final_response = staged.next_response(HeaderSet::new()).expect("has next response");
894 assert_eq!(*final_response.code(), ResponseCode::Ok);
895 let expected = bytes(28, 30);
896 expect_end_of_body(final_response.headers(), expected);
897 assert!(staged.is_complete());
898 }
899
900 #[fuchsia::test]
901 fn staged_data_response_error() {
902 let mut staged = StagedData::new(None, VecDeque::new());
904 let _ = staged.next_response(HeaderSet::new()).expect("has first response");
905 assert!(staged.is_complete());
906 assert_matches!(staged.next_response(HeaderSet::new()), Err(Error::OperationError { .. }));
907 }
908}