1use super::common::wire_header_1_0::WireHeader as Raw;
6use super::request::RequestHeader;
7use super::ResponseStatus;
8use super::Result;
9use log::error;
10use std::convert::{TryFrom, TryInto};
11use std::io::{Read, Write};
12
13mod response_body;
14mod response_header;
15
16pub use response_body::ResponseBody;
17pub use response_header::ResponseHeader;
18
19#[cfg(feature = "testing")]
20pub use super::common::wire_header_1_0::WireHeader as RawHeader;
21
22#[derive(PartialEq, Eq, Debug)]
24pub struct Response {
25 pub header: ResponseHeader,
27 pub body: ResponseBody,
31}
32
33impl Response {
34 fn new() -> Response {
36 Response {
37 header: ResponseHeader::new(),
38 body: ResponseBody::new(),
39 }
40 }
41
42 pub fn from_request_header(header: RequestHeader, status: ResponseStatus) -> Response {
47 let mut response = Response::new();
48 response.header = header.into();
49 response.header.status = status;
50
51 response
52 }
53
54 pub fn from_status(status: ResponseStatus) -> Response {
56 let mut response = Response::new();
57 response.header.status = status;
58
59 response
60 }
61
62 pub fn write_to_stream(self, stream: &mut impl Write) -> Result<()> {
72 let mut raw_header: Raw = self.header.into();
73 raw_header.body_len = u32::try_from(self.body.len())?;
74
75 raw_header.write_to_stream(stream)?;
76 self.body.write_to_stream(stream)?;
77
78 Ok(())
79 }
80
81 pub fn read_from_stream(stream: &mut impl Read, body_len_limit: usize) -> Result<Response> {
92 let raw_header = Raw::read_from_stream(stream)?;
93 let body_len = usize::try_from(raw_header.body_len)?;
94 if body_len > body_len_limit {
95 error!(
96 "Request body length ({}) bigger than the limit given ({}).",
97 body_len, body_len_limit
98 );
99 return Err(ResponseStatus::BodySizeExceedsLimit);
100 }
101 let body = ResponseBody::read_from_stream(stream, body_len)?;
102
103 Ok(Response {
104 header: raw_header.try_into()?,
105 body,
106 })
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::super::utils::tests as test_utils;
113 use super::super::{BodyType, Opcode, ProviderId, ResponseStatus};
114 use super::*;
115
116 #[test]
117 fn response_1_to_stream() {
118 let mut mock = test_utils::MockReadWrite { buffer: Vec::new() };
119 let response = get_response_1();
120
121 response
122 .write_to_stream(&mut mock)
123 .expect("Failed to write response");
124
125 assert_eq!(mock.buffer, get_response_1_bytes());
126 }
127
128 #[test]
129 fn response_2_to_stream() {
130 let mut mock = test_utils::MockReadWrite { buffer: Vec::new() };
131 let response = get_response_2();
132
133 response
134 .write_to_stream(&mut mock)
135 .expect("Failed to write response");
136
137 assert_eq!(mock.buffer, get_response_2_bytes());
138 }
139
140 #[test]
141 fn stream_to_response_1() {
142 let mut mock = test_utils::MockReadWrite {
143 buffer: get_response_1_bytes(),
144 };
145
146 let response =
147 Response::read_from_stream(&mut mock, 1000).expect("Failed to read response");
148
149 assert_eq!(response, get_response_1());
150 }
151
152 #[test]
153 fn stream_to_response_2() {
154 let mut mock = test_utils::MockReadWrite {
155 buffer: get_response_2_bytes(),
156 };
157
158 let response =
159 Response::read_from_stream(&mut mock, 1000).expect("Failed to read response");
160
161 assert_eq!(response, get_response_2());
162 }
163
164 #[test]
165 fn stream_to_fail_response_wrong_endians() {
166 let mut mock = test_utils::MockReadWrite {
167 buffer: get_response_bytes_big_endian_fixint_encoding(),
168 };
169 let response_status =
170 Response::read_from_stream(&mut mock, 1000).expect_err("Should have failed.");
171 assert_eq!(response_status, ResponseStatus::InvalidHeader);
172
173 let mut mock = test_utils::MockReadWrite {
174 buffer: get_response_bytes_big_endian_varint_encoding(),
175 };
176 let response_status =
177 Response::read_from_stream(&mut mock, 1000).expect_err("Should have failed.");
178 assert_eq!(response_status, ResponseStatus::InvalidHeader);
179 }
180 #[test]
181 fn stream_to_fail_response_wrong_int_encoding() {
182 let mut mock = test_utils::MockReadWrite {
183 buffer: get_response_bytes_little_endian_varint_encoding(),
184 };
185 let response_status =
186 Response::read_from_stream(&mut mock, 1000).expect_err("Should have failed.");
187 assert_eq!(response_status, ResponseStatus::InvalidHeader);
188 }
189
190 #[test]
191 #[should_panic(expected = "Failed to read response")]
192 fn failed_read() {
193 let mut fail_mock = test_utils::MockFailReadWrite;
194
195 let _ = Response::read_from_stream(&mut fail_mock, 1000).expect("Failed to read response");
196 }
197
198 #[test]
199 #[should_panic(expected = "Response body too large")]
200 fn body_too_large() {
201 let mut mock = test_utils::MockReadWrite {
202 buffer: get_response_1_bytes(),
203 };
204
205 let _ = Response::read_from_stream(&mut mock, 0).expect("Response body too large");
206 }
207
208 #[test]
209 #[should_panic(expected = "Failed to write response")]
210 fn failed_write() {
211 let response: Response = get_response_1();
212 let mut fail_mock = test_utils::MockFailReadWrite;
213
214 response
215 .write_to_stream(&mut fail_mock)
216 .expect("Failed to write response");
217 }
218
219 #[test]
220 fn wrong_version() {
221 let mut mock = test_utils::MockReadWrite {
222 buffer: get_response_1_bytes(),
223 };
224 mock.buffer[6] = 0xFF;
226 mock.buffer[7] = 0xFF;
228
229 let response_status =
230 Response::read_from_stream(&mut mock, 1000).expect_err("Should have failed.");
231
232 assert_eq!(
233 response_status,
234 ResponseStatus::WireProtocolVersionNotSupported
235 );
236 }
237
238 fn get_response_1() -> Response {
239 let body = ResponseBody::from_bytes(vec![0x70, 0x80, 0x90]);
240 let header = ResponseHeader {
241 provider: ProviderId::Core,
242 session: 0x11_22_33_44_55_66_77_88,
243 content_type: BodyType::Protobuf,
244 opcode: Opcode::Ping,
245 status: ResponseStatus::Success,
246 };
247 Response { header, body }
248 }
249
250 fn get_response_2() -> Response {
251 let body = ResponseBody::from_bytes(vec![0xB0, 0xB1, 0xB2, 0xB3]);
252 let header = ResponseHeader {
253 provider: ProviderId::Core,
254 session: 0x88_99_AA_BB_CC_DD_EE_FF,
255 content_type: BodyType::Protobuf,
256 opcode: Opcode::Ping,
257 status: ResponseStatus::Success,
258 };
259 Response { header, body }
260 }
261
262 fn get_response_1_bytes() -> Vec<u8> {
263 vec![
264 0x10, 0xA7, 0xC0, 0x5E, 0x1E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x90, ]
282 }
283
284 fn get_response_2_bytes() -> Vec<u8> {
285 vec![
286 0x10, 0xA7, 0xC0, 0x5E, 0x1E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xB1, 0xB2, 0xB3, ]
304 }
305 fn get_response_bytes_big_endian_fixint_encoding() -> Vec<u8> {
306 vec![
307 0x5E, 0xC0, 0xA7, 0x10, 0x00, 0x1E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x90, ]
325 }
326 fn get_response_bytes_little_endian_varint_encoding() -> Vec<u8> {
327 vec![
328 0xFC, 0x5E, 0xC0, 0xA7, 0x10, 0x1E, 0x01, 0x00, 0x00, 0x00, 0xFD, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x80, 0x90, ]
350 }
351 fn get_response_bytes_big_endian_varint_encoding() -> Vec<u8> {
352 vec![
353 0xFC, 0x10, 0xA7, 0xC0, 0x5E, 0x1E, 0x01, 0x00, 0x00, 0x00, 0xFD, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x80, 0x90, ]
375 }
376}