1use super::common::wire_header_1_0::WireHeader as Raw;
7use super::response::ResponseHeader;
8use crate::requests::{ResponseStatus, Result};
9use crate::secrecy::ExposeSecret;
10use derivative::Derivative;
11use log::error;
12use std::convert::{TryFrom, TryInto};
13use std::io::{Read, Write};
14
15mod request_auth;
16mod request_body;
17mod request_header;
18
19pub use request_auth::RequestAuth;
20pub use request_body::RequestBody;
21pub use request_header::RequestHeader;
22
23#[cfg(feature = "testing")]
24pub use super::common::wire_header_1_0::WireHeader as RawHeader;
25
26#[derive(Derivative)]
28#[derivative(Debug)]
29pub struct Request {
30 pub header: RequestHeader,
32 pub body: RequestBody,
36 #[derivative(Debug = "ignore")]
39 pub auth: RequestAuth,
40}
41
42impl Request {
43 #[cfg(feature = "testing")]
46 pub fn new() -> Request {
47 Request {
48 header: RequestHeader::new(),
49 body: RequestBody::new(),
50 auth: RequestAuth::new(Vec::new()),
51 }
52 }
53
54 pub fn write_to_stream(self, stream: &mut impl Write) -> Result<()> {
64 let mut raw_header: Raw = self.header.into();
65 raw_header.body_len = u32::try_from(self.body.len())?;
66 raw_header.auth_len = u16::try_from(self.auth.buffer.expose_secret().len())?;
67 raw_header.write_to_stream(stream)?;
68
69 self.body.write_to_stream(stream)?;
70 self.auth.write_to_stream(stream)?;
71
72 Ok(())
73 }
74
75 pub fn read_from_stream(stream: &mut impl Read, body_len_limit: usize) -> Result<Request> {
87 let raw_header = Raw::read_from_stream(stream)?;
88 let body_len = usize::try_from(raw_header.body_len)?;
89 if body_len > body_len_limit {
90 error!(
91 "Request body length ({}) bigger than the limit given ({}).",
92 body_len, body_len_limit
93 );
94 return Err(ResponseStatus::BodySizeExceedsLimit);
95 }
96 let body = RequestBody::read_from_stream(stream, body_len)?;
97 let auth = RequestAuth::read_from_stream(stream, usize::try_from(raw_header.auth_len)?)?;
98
99 Ok(Request {
100 header: raw_header.try_into()?,
101 body,
102 auth,
103 })
104 }
105}
106
107#[cfg(feature = "testing")]
108impl Default for Request {
109 fn default() -> Request {
110 Request::new()
111 }
112}
113
114impl From<RequestHeader> for ResponseHeader {
117 fn from(req_hdr: RequestHeader) -> ResponseHeader {
118 ResponseHeader {
119 provider: req_hdr.provider,
120 session: req_hdr.session,
121 content_type: req_hdr.accept_type,
122 opcode: req_hdr.opcode,
123 status: ResponseStatus::Success,
124 }
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::super::utils::tests as test_utils;
131 use super::super::{AuthType, BodyType, Opcode, ProviderId, ResponseStatus};
132 use super::*;
133
134 #[test]
135 fn request_1_to_stream() {
136 let mut mock = test_utils::MockReadWrite { buffer: Vec::new() };
137 let request = get_request_1();
138
139 request
140 .write_to_stream(&mut mock)
141 .expect("Failed to write request");
142
143 assert_eq!(mock.buffer, get_request_1_bytes());
144 }
145
146 #[test]
147 fn request_2_to_stream() {
148 let mut mock = test_utils::MockReadWrite { buffer: Vec::new() };
149 let request = get_request_2();
150
151 request
152 .write_to_stream(&mut mock)
153 .expect("Failed to write request");
154
155 assert_eq!(mock.buffer, get_request_2_bytes());
156 }
157
158 #[test]
159 fn stream_to_request_1() {
160 let mut mock = test_utils::MockReadWrite {
161 buffer: get_request_1_bytes(),
162 };
163
164 let request = Request::read_from_stream(&mut mock, 1000).expect("Failed to read request");
165 let exp_req = get_request_1();
166
167 assert_eq!(request.header, exp_req.header);
168 assert_eq!(request.body, exp_req.body);
169 assert_eq!(
170 request.auth.buffer.expose_secret(),
171 exp_req.auth.buffer.expose_secret()
172 );
173 }
174
175 #[test]
176 fn stream_to_request_2() {
177 let mut mock = test_utils::MockReadWrite {
178 buffer: get_request_2_bytes(),
179 };
180
181 let request = Request::read_from_stream(&mut mock, 1000).expect("Failed to read request");
182 let exp_req = get_request_2();
183
184 assert_eq!(request.header, exp_req.header);
185 assert_eq!(request.body, exp_req.body);
186 assert_eq!(
187 request.auth.buffer.expose_secret(),
188 exp_req.auth.buffer.expose_secret()
189 );
190 }
191
192 #[test]
193 fn stream_to_fail_request_1() {
194 let mut mock = test_utils::MockReadWrite {
195 buffer: get_request_bytes_reserved_fields_both_not_zero(),
196 };
197
198 assert_eq!(
199 Request::read_from_stream(&mut mock, 1000).unwrap_err(),
200 ResponseStatus::InvalidHeader
201 );
202 }
203
204 #[test]
205 fn stream_to_fail_request_2() {
206 let mut mock = test_utils::MockReadWrite {
207 buffer: get_request_bytes_reserved_fields_first_not_zero(),
208 };
209
210 assert_eq!(
211 Request::read_from_stream(&mut mock, 1000).unwrap_err(),
212 ResponseStatus::InvalidHeader
213 );
214 }
215
216 #[test]
217 fn stream_to_fail_request_3() {
218 let mut mock = test_utils::MockReadWrite {
219 buffer: get_request_bytes_reserved_fields_second_not_zero(),
220 };
221
222 assert_eq!(
223 Request::read_from_stream(&mut mock, 1000).unwrap_err(),
224 ResponseStatus::InvalidHeader
225 );
226 }
227
228 #[test]
229 fn stream_to_fail_request_wrong_endians() {
230 let mut mock = test_utils::MockReadWrite {
231 buffer: get_request_bytes_big_endian_fixint_encoding(),
232 };
233 let response_status =
234 Request::read_from_stream(&mut mock, 1000).expect_err("Should have failed.");
235 assert_eq!(response_status, ResponseStatus::InvalidHeader);
236
237 let mut mock = test_utils::MockReadWrite {
238 buffer: get_request_bytes_big_endian_varint_encoding(),
239 };
240 let response_status =
241 Request::read_from_stream(&mut mock, 1000).expect_err("Should have failed.");
242 assert_eq!(response_status, ResponseStatus::InvalidHeader);
243 }
244 #[test]
245 fn stream_to_fail_request_wrong_int_encoding() {
246 let mut mock = test_utils::MockReadWrite {
247 buffer: get_request_bytes_little_endian_varint_encoding(),
248 };
249 let response_status =
250 Request::read_from_stream(&mut mock, 1000).expect_err("Should have failed.");
251 assert_eq!(response_status, ResponseStatus::InvalidHeader);
252 }
253
254 #[test]
255 #[should_panic(expected = "Failed to read request")]
256 fn failed_read() {
257 let mut fail_mock = test_utils::MockFailReadWrite;
258
259 let _ = Request::read_from_stream(&mut fail_mock, 1000).expect("Failed to read request");
260 }
261
262 #[test]
263 #[should_panic(expected = "Request body too large")]
264 fn body_too_large() {
265 let mut mock = test_utils::MockReadWrite {
266 buffer: get_request_1_bytes(),
267 };
268
269 let _ = Request::read_from_stream(&mut mock, 0).expect("Request body too large");
270 }
271
272 #[test]
273 #[should_panic(expected = "Failed to write request")]
274 fn failed_write() {
275 let request: Request = get_request_1();
276 let mut fail_mock = test_utils::MockFailReadWrite;
277
278 request
279 .write_to_stream(&mut fail_mock)
280 .expect("Failed to write request");
281 }
282
283 #[test]
284 fn req_hdr_to_resp_hdr() {
285 let req_hdr = get_request_1().header;
286 let resp_hdr: ResponseHeader = req_hdr.into();
287
288 let mut resp_hdr_exp = ResponseHeader::new();
289 resp_hdr_exp.provider = ProviderId::Core;
290 resp_hdr_exp.session = 0x11_22_33_44_55_66_77_88;
291 resp_hdr_exp.content_type = BodyType::Protobuf;
292 resp_hdr_exp.opcode = Opcode::Ping;
293 resp_hdr_exp.status = ResponseStatus::Success;
294
295 assert_eq!(resp_hdr, resp_hdr_exp);
296 }
297
298 #[test]
299 fn wrong_version() {
300 let mut mock = test_utils::MockReadWrite {
301 buffer: get_request_1_bytes(),
302 };
303 mock.buffer[6] = 0xFF;
305 mock.buffer[7] = 0xFF;
307
308 let response_status =
309 Request::read_from_stream(&mut mock, 1000).expect_err("Should have failed.");
310
311 assert_eq!(
312 response_status,
313 ResponseStatus::WireProtocolVersionNotSupported
314 );
315 }
316
317 fn get_request_1() -> Request {
318 let body = RequestBody::from_bytes(vec![0x70, 0x80, 0x90]);
319 let auth = RequestAuth::new(vec![0xa0, 0xb0, 0xc0]);
320 let header = RequestHeader {
321 provider: ProviderId::Core,
322 session: 0x11_22_33_44_55_66_77_88,
323 content_type: BodyType::Protobuf,
324 accept_type: BodyType::Protobuf,
325 auth_type: AuthType::Direct,
326 opcode: Opcode::Ping,
327 };
328 Request { header, body, auth }
329 }
330
331 fn get_request_2() -> Request {
332 let body = RequestBody::from_bytes(vec![0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5]);
333 let auth = RequestAuth::new(vec![0xA0, 0xA1, 0xA2, 0xA3, 0xA4]);
334 let header = RequestHeader {
335 provider: ProviderId::Core,
336 session: 0x88_99_AA_BB_CC_DD_EE_FF,
337 content_type: BodyType::Protobuf,
338 accept_type: BodyType::Protobuf,
339 auth_type: AuthType::Direct,
340 opcode: Opcode::Ping,
341 };
342 Request { header, body, auth }
343 }
344
345 fn get_request_1_bytes() -> Vec<u8> {
346 vec![
347 0x10, 0xA7, 0xC0, 0x5E, 0x1E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, ]
366 }
367
368 fn get_request_2_bytes() -> Vec<u8> {
369 vec![
370 0x10, 0xA7, 0xC0, 0x5E, 0x1E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, ]
389 }
390
391 fn get_request_bytes_reserved_fields_both_not_zero() -> Vec<u8> {
392 vec![
394 0x10, 0xA7, 0xC0, 0x5E, 0x1E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, ]
413 }
414
415 fn get_request_bytes_reserved_fields_first_not_zero() -> Vec<u8> {
416 vec![
417 0x10, 0xA7, 0xC0, 0x5E, 0x1E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0x00, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, ]
436 }
437 fn get_request_bytes_reserved_fields_second_not_zero() -> Vec<u8> {
438 vec![
439 0x10, 0xA7, 0xC0, 0x5E, 0x1E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAD, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, ]
458 }
459 fn get_request_bytes_big_endian_fixint_encoding() -> Vec<u8> {
460 vec![
461 0x5E, 0xC0, 0xA7, 0x10, 0x00, 0x1E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, ]
480 }
481 fn get_request_bytes_little_endian_varint_encoding() -> Vec<u8> {
482 vec![
483 0xFC, 0x5E, 0xC0, 0xA7, 0x10, 0x1E, 0x01, 0x00, 0x00, 0x00, 0xFD, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x00, 0x00, 0x01, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, ]
506 }
507 fn get_request_bytes_big_endian_varint_encoding() -> Vec<u8> {
508 vec![
509 0xFC, 0x10, 0xA7, 0xC0, 0x5E, 0x1E, 0x01, 0x00, 0x00, 0x00, 0xFD, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x00, 0x00, 0x01, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, ]
532 }
533}