Skip to content
File

Blob: firmware/vendor/sctp-proto/src/chunk/chunk_test.rs

rust772 lines
1use alloc::string::ToString;
2use alloc::vec;
3use alloc::vec::Vec;
4 
5use super::*;
6 
7///////////////////////////////////////////////////////////////////
8//chunk_type_test
9///////////////////////////////////////////////////////////////////
10use super::chunk_type::*;
11 
12#[test]
13fn test_chunk_type_string() -> Result<()> {
14 let tests = vec![
15 (CT_PAYLOAD_DATA, "DATA"),
16 (CT_INIT, "INIT"),
17 (CT_INIT_ACK, "INIT-ACK"),
18 (CT_SACK, "SACK"),
19 (CT_HEARTBEAT, "HEARTBEAT"),
20 (CT_HEARTBEAT_ACK, "HEARTBEAT-ACK"),
21 (CT_ABORT, "ABORT"),
22 (CT_SHUTDOWN, "SHUTDOWN"),
23 (CT_SHUTDOWN_ACK, "SHUTDOWN-ACK"),
24 (CT_ERROR, "ERROR"),
25 (CT_COOKIE_ECHO, "COOKIE-ECHO"),
26 (CT_COOKIE_ACK, "COOKIE-ACK"),
27 (CT_CWR, "ECNE"),
28 (CT_SHUTDOWN_COMPLETE, "SHUTDOWN-COMPLETE"),
29 (CT_RECONFIG, "RECONFIG"),
30 (CT_FORWARD_TSN, "FORWARD-TSN"),
31 (ChunkType(255), "Unknown ChunkType: 255"),
32 ];
33 
34 for (ct, expected) in tests {
35 assert_eq!(
36 ct.to_string(),
37 expected,
38 "failed to stringify chunkType {}, expected {}",
39 ct,
40 expected
41 );
42 }
43 
44 Ok(())
45}
46 
47///////////////////////////////////////////////////////////////////
48//chunk_abort_test
49///////////////////////////////////////////////////////////////////
50use super::chunk_abort::*;
51 
52#[test]
53fn test_abort_chunk_one_error_cause() -> Result<()> {
54 let abort1 = ChunkAbort {
55 error_causes: vec![ErrorCause {
56 code: PROTOCOL_VIOLATION,
57 ..Default::default()
58 }],
59 };
60 
61 let b = abort1.marshal()?;
62 let abort2 = ChunkAbort::unmarshal(&b)?;
63 
64 assert_eq!(1, abort2.error_causes.len(), "should have only one cause");
65 assert_eq!(
66 abort1.error_causes[0].error_cause_code(),
67 abort2.error_causes[0].error_cause_code(),
68 "errorCause code should match"
69 );
70 
71 Ok(())
72}
73 
74#[test]
75fn test_abort_chunk_many_error_causes() -> Result<()> {
76 let abort1 = ChunkAbort {
77 error_causes: vec![
78 ErrorCause {
79 code: INVALID_MANDATORY_PARAMETER,
80 ..Default::default()
81 },
82 ErrorCause {
83 code: UNRECOGNIZED_CHUNK_TYPE,
84 ..Default::default()
85 },
86 ErrorCause {
87 code: PROTOCOL_VIOLATION,
88 ..Default::default()
89 },
90 ],
91 };
92 
93 let b = abort1.marshal()?;
94 let abort2 = ChunkAbort::unmarshal(&b)?;
95 assert_eq!(3, abort2.error_causes.len(), "should have only one cause");
96 for (i, error_cause) in abort1.error_causes.iter().enumerate() {
97 assert_eq!(
98 error_cause.error_cause_code(),
99 abort2.error_causes[i].error_cause_code(),
100 "errorCause code should match"
101 );
102 }
103 
104 Ok(())
105}
106 
107///////////////////////////////////////////////////////////////////
108//chunk_error_test
109///////////////////////////////////////////////////////////////////
110use super::chunk_error::*;
111use std::sync::LazyLock;
112 
113const CHUNK_FLAGS: u8 = 0x00;
114static ORG_UNRECOGNIZED_CHUNK: Bytes =
115 Bytes::from_static(&[0xc0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x3]);
116 
117static RAW_IN: LazyLock<Bytes> = LazyLock::new(|| {
118 let mut raw = BytesMut::new();
119 raw.put_u8(CT_ERROR.0);
120 raw.put_u8(CHUNK_FLAGS);
121 raw.extend(vec![0x00, 0x10, 0x00, 0x06, 0x00, 0x0c]);
122 raw.extend(ORG_UNRECOGNIZED_CHUNK.clone());
123 raw.freeze()
124});
125 
126#[test]
127fn test_chunk_error_unrecognized_chunk_type_unmarshal() -> Result<()> {
128 let c = ChunkError::unmarshal(&RAW_IN)?;
129 assert_eq!(CT_ERROR, c.header().typ, "chunk type should be ERROR");
130 assert_eq!(1, c.error_causes.len(), "there should be on errorCause");
131 
132 let ec = &c.error_causes[0];
133 assert_eq!(
134 UNRECOGNIZED_CHUNK_TYPE,
135 ec.error_cause_code(),
136 "cause code should be unrecognizedChunkType"
137 );
138 assert_eq!(
139 ec.raw, ORG_UNRECOGNIZED_CHUNK,
140 "should have valid unrecognizedChunk"
141 );
142 
143 Ok(())
144}
145 
146#[test]
147fn test_chunk_error_unrecognized_chunk_type_marshal() -> Result<()> {
148 let ec_unrecognized_chunk_type = ErrorCause {
149 code: UNRECOGNIZED_CHUNK_TYPE,
150 raw: ORG_UNRECOGNIZED_CHUNK.clone(),
151 };
152 
153 let ec = ChunkError {
154 error_causes: vec![ec_unrecognized_chunk_type],
155 };
156 
157 let raw = ec.marshal()?;
158 assert_eq!(raw, *RAW_IN, "unexpected serialization result");
159 
160 Ok(())
161}
162 
163#[test]
164fn test_chunk_error_unrecognized_chunk_type_marshal_with_cause_value_being_nil() -> Result<()> {
165 let expected =
166 Bytes::from_static(&[CT_ERROR.0, CHUNK_FLAGS, 0x00, 0x08, 0x00, 0x06, 0x00, 0x04]);
167 let ec_unrecognized_chunk_type = ErrorCause {
168 code: UNRECOGNIZED_CHUNK_TYPE,
169 ..Default::default()
170 };
171 
172 let ec = ChunkError {
173 error_causes: vec![ec_unrecognized_chunk_type],
174 };
175 
176 let raw = ec.marshal()?;
177 assert_eq!(raw, expected, "unexpected serialization result");
178 
179 Ok(())
180}
181 
182///////////////////////////////////////////////////////////////////
183//chunk_forward_tsn_test
184///////////////////////////////////////////////////////////////////
185use super::chunk_forward_tsn::*;
186 
187static CHUNK_FORWARD_TSN_BYTES: Bytes =
188 Bytes::from_static(&[0xc0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x3]);
189 
190#[test]
191fn test_chunk_forward_tsn_success() -> Result<()> {
192 let tests = vec![
193 CHUNK_FORWARD_TSN_BYTES.clone(),
194 Bytes::from_static(&[0xc0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x3, 0x0, 0x4, 0x0, 0x5]),
195 Bytes::from_static(&[
196 0xc0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x3, 0x0, 0x4, 0x0, 0x5, 0x0, 0x6, 0x0, 0x7,
197 ]),
198 ];
199 
200 for binary in tests {
201 let actual = ChunkForwardTsn::unmarshal(&binary)?;
202 let b = actual.marshal()?;
203 assert_eq!(binary, b, "test not equal");
204 }
205 
206 Ok(())
207}
208 
209#[test]
210fn test_chunk_forward_tsn_unmarshal_failure() -> Result<()> {
211 let tests = vec![
212 ("chunk header to short", Bytes::from_static(&[0xc0])),
213 (
214 "missing New Cumulative TSN",
215 Bytes::from_static(&[0xc0, 0x0, 0x0, 0x4]),
216 ),
217 (
218 "missing stream sequence",
219 Bytes::from_static(&[
220 0xc0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x3, 0x0, 0x4, 0x0, 0x5, 0x0, 0x6,
221 ]),
222 ),
223 ];
224 
225 for (name, binary) in tests {
226 let result = ChunkForwardTsn::unmarshal(&binary);
227 assert!(result.is_err(), "expected unmarshal: {} to fail.", name);
228 }
229 
230 Ok(())
231}
232 
233///////////////////////////////////////////////////////////////////
234//chunk_reconfig_test
235///////////////////////////////////////////////////////////////////
236use super::chunk_reconfig::*;
237 
238static TEST_CHUNK_RECONFIG_PARAM_A: Bytes = Bytes::from_static(&[
239 0x0, 0xd, 0x0, 0x16, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x3, 0x0, 0x4, 0x0,
240 0x5, 0x0, 0x6,
241]);
242 
243static TEST_CHUNK_RECONFIG_PARAM_B: Bytes = Bytes::from_static(&[
244 0x0, 0xd, 0x0, 0x10, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x3,
245]);
246 
247static TEST_CHUNK_RECONFIG_RESPONCE: Bytes =
248 Bytes::from_static(&[0x0, 0x10, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1]);
249 
250static TEST_CHUNK_RECONFIG_BYTES: LazyLock<Vec<Bytes>> = LazyLock::new(|| {
251 let mut tests = vec![];
252 {
253 let mut test = BytesMut::new();
254 test.extend(vec![0x82, 0x0, 0x0, 0x1a]);
255 test.extend(TEST_CHUNK_RECONFIG_PARAM_A.clone());
256 tests.push(test.freeze());
257 }
258 {
259 let mut test = BytesMut::new();
260 test.extend(vec![0x82, 0x0, 0x0, 0x14]);
261 test.extend(TEST_CHUNK_RECONFIG_PARAM_B.clone());
262 tests.push(test.freeze());
263 }
264 {
265 let mut test = BytesMut::new();
266 test.extend(vec![0x82, 0x0, 0x0, 0x10]);
267 test.extend(TEST_CHUNK_RECONFIG_RESPONCE.clone());
268 tests.push(test.freeze());
269 }
270 {
271 let mut test = BytesMut::new();
272 test.extend(vec![0x82, 0x0, 0x0, 0x2c]);
273 test.extend(TEST_CHUNK_RECONFIG_PARAM_A.clone());
274 test.extend(vec![0u8; 2]);
275 test.extend(TEST_CHUNK_RECONFIG_PARAM_B.clone());
276 tests.push(test.freeze());
277 }
278 {
279 let mut test = BytesMut::new();
280 test.extend(vec![0x82, 0x0, 0x0, 0x2a]);
281 test.extend(TEST_CHUNK_RECONFIG_PARAM_B.clone());
282 test.extend(TEST_CHUNK_RECONFIG_PARAM_A.clone());
283 tests.push(test.freeze());
284 }
285 
286 tests
287});
288 
289#[test]
290fn test_chunk_reconfig_success() -> Result<()> {
291 for (i, binary) in TEST_CHUNK_RECONFIG_BYTES.iter().enumerate() {
292 let actual = ChunkReconfig::unmarshal(binary)?;
293 let b = actual.marshal()?;
294 assert_eq!(*binary, b, "test {} not equal: {:?} vs {:?}", i, *binary, b);
295 }
296 
297 Ok(())
298}
299 
300#[test]
301fn test_chunk_reconfig_unmarshal_failure() -> Result<()> {
302 let mut test = BytesMut::new();
303 test.extend(vec![0x82, 0x0, 0x0, 0x18]);
304 test.extend(TEST_CHUNK_RECONFIG_PARAM_B.clone());
305 test.extend(vec![0x0, 0xd, 0x0, 0x0]);
306 let tests = vec![
307 ("chunk header to short", Bytes::from_static(&[0x82])),
308 (
309 "missing parse param type (A)",
310 Bytes::from_static(&[0x82, 0x0, 0x0, 0x4]),
311 ),
312 (
313 "wrong param (A)",
314 Bytes::from_static(&[0x82, 0x0, 0x0, 0x8, 0x0, 0xd, 0x0, 0x0]),
315 ),
316 ("wrong param (B)", test.freeze()),
317 ];
318 
319 for (name, binary) in tests {
320 let result = ChunkReconfig::unmarshal(&binary);
321 assert!(result.is_err(), "expected unmarshal: {} to fail.", name);
322 }
323 
324 Ok(())
325}
326 
327///////////////////////////////////////////////////////////////////
328//chunk_shutdown_test
329///////////////////////////////////////////////////////////////////
330use super::chunk_shutdown::*;
331 
332#[test]
333fn test_chunk_shutdown_success() -> Result<()> {
334 let tests = vec![Bytes::from_static(&[
335 0x07, 0x00, 0x00, 0x08, 0x12, 0x34, 0x56, 0x78,
336 ])];
337 
338 for binary in tests {
339 let actual = ChunkShutdown::unmarshal(&binary)?;
340 let b = actual.marshal()?;
341 assert_eq!(binary, b, "test not equal");
342 }
343 
344 Ok(())
345}
346 
347#[test]
348fn test_chunk_shutdown_failure() -> Result<()> {
349 let tests = vec![
350 (
351 "length too short",
352 Bytes::from_static(&[0x07, 0x00, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78]),
353 ),
354 (
355 "length too long",
356 Bytes::from_static(&[0x07, 0x00, 0x00, 0x09, 0x12, 0x34, 0x56, 0x78]),
357 ),
358 (
359 "payload too short",
360 Bytes::from_static(&[0x07, 0x00, 0x00, 0x08, 0x12, 0x34, 0x56]),
361 ),
362 (
363 "payload too long",
364 Bytes::from_static(&[0x07, 0x00, 0x00, 0x08, 0x12, 0x34, 0x56, 0x78, 0x9f]),
365 ),
366 (
367 "invalid type",
368 Bytes::from_static(&[0x08, 0x00, 0x00, 0x08, 0x12, 0x34, 0x56, 0x78]),
369 ),
370 ];
371 
372 for (name, binary) in tests {
373 let result = ChunkShutdown::unmarshal(&binary);
374 assert!(result.is_err(), "expected unmarshal: {} to fail.", name);
375 }
376 
377 Ok(())
378}
379 
380///////////////////////////////////////////////////////////////////
381//chunk_shutdown_ack_test
382///////////////////////////////////////////////////////////////////
383use super::chunk_shutdown_ack::*;
384 
385#[test]
386fn test_chunk_shutdown_ack_success() -> Result<()> {
387 let tests = vec![Bytes::from_static(&[0x08, 0x00, 0x00, 0x04])];
388 
389 for binary in tests {
390 let actual = ChunkShutdownAck::unmarshal(&binary)?;
391 let b = actual.marshal()?;
392 assert_eq!(binary, b, "test not equal");
393 }
394 
395 Ok(())
396}
397 
398#[test]
399fn test_chunk_shutdown_ack_failure() -> Result<()> {
400 let tests = vec![
401 ("length too short", Bytes::from_static(&[0x08, 0x00, 0x00])),
402 (
403 "length too long",
404 Bytes::from_static(&[0x08, 0x00, 0x00, 0x04, 0x12]),
405 ),
406 (
407 "invalid type",
408 Bytes::from_static(&[0x0f, 0x00, 0x00, 0x04]),
409 ),
410 ];
411 
412 for (name, binary) in tests {
413 let result = ChunkShutdownAck::unmarshal(&binary);
414 assert!(result.is_err(), "expected unmarshal: {} to fail.", name);
415 }
416 
417 Ok(())
418}
419 
420///////////////////////////////////////////////////////////////////
421//chunk_shutdown_complete_test
422///////////////////////////////////////////////////////////////////
423use super::chunk_shutdown_complete::*;
424 
425#[test]
426fn test_chunk_shutdown_complete_success() -> Result<()> {
427 let tests = vec![Bytes::from_static(&[0x0e, 0x00, 0x00, 0x04])];
428 
429 for binary in tests {
430 let actual = ChunkShutdownComplete::unmarshal(&binary)?;
431 let b = actual.marshal()?;
432 assert_eq!(binary, b, "test not equal");
433 }
434 
435 Ok(())
436}
437 
438#[test]
439fn test_chunk_shutdown_complete_failure() -> Result<()> {
440 let tests = vec![
441 ("length too short", Bytes::from_static(&[0x0e, 0x00, 0x00])),
442 (
443 "length too long",
444 Bytes::from_static(&[0x0e, 0x00, 0x00, 0x04, 0x12]),
445 ),
446 (
447 "invalid type",
448 Bytes::from_static(&[0x0f, 0x00, 0x00, 0x04]),
449 ),
450 ];
451 
452 for (name, binary) in tests {
453 let result = ChunkShutdownComplete::unmarshal(&binary);
454 assert!(result.is_err(), "expected unmarshal: {} to fail.", name);
455 }
456 
457 Ok(())
458}
459 
460///////////////////////////////////////////////////////////////////
461//chunk_test
462///////////////////////////////////////////////////////////////////
463use crate::chunk::chunk_init::*;
464use crate::chunk::chunk_payload_data::*;
465use crate::chunk::chunk_selective_ack::ChunkSelectiveAck;
466use crate::packet::*;
467use crate::param::param_outgoing_reset_request::ParamOutgoingResetRequest;
468use crate::param::param_state_cookie::*;
469 
470#[test]
471fn test_init_chunk() -> Result<()> {
472 let raw_pkt = Bytes::from_static(&[
473 0x13, 0x88, 0x13, 0x88, 0x00, 0x00, 0x00, 0x00, 0x81, 0x46, 0x9d, 0xfc, 0x01, 0x00, 0x00,
474 0x56, 0x55, 0xb9, 0x64, 0xa5, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0xe8, 0x6d,
475 0x10, 0x30, 0xc0, 0x00, 0x00, 0x04, 0x80, 0x08, 0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80, 0x82,
476 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x24, 0x9f, 0xeb, 0xbb, 0x5c, 0x50, 0xc9, 0xbf, 0x75,
477 0x9c, 0xb1, 0x2c, 0x57, 0x4f, 0xa4, 0x5a, 0x51, 0xba, 0x60, 0x17, 0x78, 0x27, 0x94, 0x5c,
478 0x31, 0xe6, 0x5d, 0x5b, 0x09, 0x47, 0xe2, 0x22, 0x06, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01,
479 0x00, 0x00, 0x80, 0x03, 0x00, 0x06, 0x80, 0xc1, 0x00, 0x00,
480 ]);
481 let pkt = Packet::unmarshal(&raw_pkt)?;
482 
483 if let Some(c) = pkt.chunks[0].as_any().downcast_ref::<ChunkInit>() {
484 assert_eq!(
485 c.initiate_tag, 1438213285,
486 "Unmarshal passed for SCTP packet, but got incorrect initiate tag exp: {} act: {}",
487 1438213285, c.initiate_tag
488 );
489 assert_eq!(
490 c.advertised_receiver_window_credit, 131072,
491 "Unmarshal passed for SCTP packet, but got incorrect \
492 advertisedReceiverWindowCredit exp: {} act: {}",
493 131072, c.advertised_receiver_window_credit
494 );
495 assert_eq!(
496 c.num_outbound_streams, 1024,
497 "Unmarshal passed for SCTP packet, but got incorrect numOutboundStreams tag exp:{} act: {}",
498 1024, c.num_outbound_streams
499 );
500 assert_eq!(
501 c.num_inbound_streams, 2048,
502 "Unmarshal passed for SCTP packet, but got incorrect numInboundStreams exp: {} act: {}",
503 2048, c.num_inbound_streams
504 );
505 assert_eq!(
506 c.initial_tsn, 3899461680u32,
507 "Unmarshal passed for SCTP packet, but got incorrect initialTSN exp: {} act: {}",
508 3899461680u32, c.initial_tsn
509 );
510 } else {
511 panic!("Failed to cast Chunk -> Init");
512 }
513 
514 Ok(())
515}
516 
517#[test]
518fn test_init_ack() -> Result<()> {
519 let raw_pkt = Bytes::from_static(&[
520 0x13, 0x88, 0x13, 0x88, 0xce, 0x15, 0x79, 0xa2, 0x96, 0x19, 0xe8, 0xb2, 0x02, 0x00, 0x00,
521 0x1c, 0xeb, 0x81, 0x4e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x50, 0xdf,
522 0x90, 0xd9, 0x00, 0x07, 0x00, 0x08, 0x94, 0x06, 0x2f, 0x93,
523 ]);
524 let pkt = Packet::unmarshal(&raw_pkt)?;
525 assert!(
526 pkt.chunks[0].as_any().downcast_ref::<ChunkInit>().is_some(),
527 "Failed to cast Chunk -> Init"
528 );
529 
530 Ok(())
531}
532 
533#[test]
534fn test_chrome_chunk1_init() -> Result<()> {
535 let raw_pkt = Bytes::from_static(&[
536 0x13, 0x88, 0x13, 0x88, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xb3, 0x45, 0xa2, 0x01, 0x00, 0x00,
537 0x56, 0xce, 0x15, 0x79, 0xa2, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x94, 0x57,
538 0x95, 0xc0, 0xc0, 0x00, 0x00, 0x04, 0x80, 0x08, 0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80, 0x82,
539 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x24, 0xff, 0x5c, 0x49, 0x19, 0x4a, 0x94, 0xe8, 0x2a,
540 0xec, 0x58, 0x55, 0x62, 0x29, 0x1f, 0x8e, 0x23, 0xcd, 0x7c, 0xe8, 0x46, 0xba, 0x58, 0x1b,
541 0x3d, 0xab, 0xd7, 0x7e, 0x50, 0xf2, 0x41, 0xb1, 0x2e, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01,
542 0x00, 0x00, 0x80, 0x03, 0x00, 0x06, 0x80, 0xc1, 0x00, 0x00,
543 ]);
544 let pkt = Packet::unmarshal(&raw_pkt)?;
545 let raw_pkt2 = pkt.marshal()?;
546 assert_eq!(raw_pkt, raw_pkt2);
547 
548 Ok(())
549}
550 
551#[test]
552fn test_chrome_chunk2_init_ack() -> Result<()> {
553 let raw_pkt = Bytes::from_static(&[
554 0x13, 0x88, 0x13, 0x88, 0xce, 0x15, 0x79, 0xa2, 0xb5, 0xdb, 0x2d, 0x93, 0x02, 0x00, 0x01,
555 0x90, 0x9b, 0xd5, 0xb3, 0x6f, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0xef, 0xb4,
556 0x72, 0x87, 0xc0, 0x00, 0x00, 0x04, 0x80, 0x08, 0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80, 0x82,
557 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x24, 0x2e, 0xf9, 0x9c, 0x10, 0x63, 0x72, 0xed, 0x0d,
558 0x33, 0xc2, 0xdc, 0x7f, 0x9f, 0xd7, 0xef, 0x1b, 0xc9, 0xc4, 0xa7, 0x41, 0x9a, 0x07, 0x68,
559 0x6b, 0x66, 0xfb, 0x6a, 0x4e, 0x32, 0x5d, 0xe4, 0x25, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01,
560 0x00, 0x00, 0x80, 0x03, 0x00, 0x06, 0x80, 0xc1, 0x00, 0x00, 0x00, 0x07, 0x01, 0x38, 0x4b,
561 0x41, 0x4d, 0x45, 0x2d, 0x42, 0x53, 0x44, 0x20, 0x31, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00,
562 0x9c, 0x1e, 0x49, 0x5b, 0x00, 0x00, 0x00, 0x00, 0xd2, 0x42, 0x06, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x60, 0xea, 0x00, 0x00, 0xc4, 0x13, 0x3d, 0xe9, 0x86, 0xb1, 0x85, 0x75, 0xa2, 0x79,
564 0x15, 0xce, 0x9b, 0xd5, 0xb3, 0x6f, 0x20, 0xe0, 0x9f, 0x89, 0xe0, 0x27, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x9f, 0x89,
566 0xe0, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x88, 0x13, 0x88, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01,
568 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x56, 0xce, 0x15, 0x79, 0xa2, 0x00,
569 0x02, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x94, 0x57, 0x95, 0xc0, 0xc0, 0x00, 0x00, 0x04,
570 0x80, 0x08, 0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80, 0x82, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00,
571 0x24, 0xff, 0x5c, 0x49, 0x19, 0x4a, 0x94, 0xe8, 0x2a, 0xec, 0x58, 0x55, 0x62, 0x29, 0x1f,
572 0x8e, 0x23, 0xcd, 0x7c, 0xe8, 0x46, 0xba, 0x58, 0x1b, 0x3d, 0xab, 0xd7, 0x7e, 0x50, 0xf2,
573 0x41, 0xb1, 0x2e, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x80, 0x03, 0x00, 0x06,
574 0x80, 0xc1, 0x00, 0x00, 0x02, 0x00, 0x01, 0x90, 0x9b, 0xd5, 0xb3, 0x6f, 0x00, 0x02, 0x00,
575 0x00, 0x04, 0x00, 0x08, 0x00, 0xef, 0xb4, 0x72, 0x87, 0xc0, 0x00, 0x00, 0x04, 0x80, 0x08,
576 0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80, 0x82, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x24, 0x2e,
577 0xf9, 0x9c, 0x10, 0x63, 0x72, 0xed, 0x0d, 0x33, 0xc2, 0xdc, 0x7f, 0x9f, 0xd7, 0xef, 0x1b,
578 0xc9, 0xc4, 0xa7, 0x41, 0x9a, 0x07, 0x68, 0x6b, 0x66, 0xfb, 0x6a, 0x4e, 0x32, 0x5d, 0xe4,
579 0x25, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x80, 0x03, 0x00, 0x06, 0x80, 0xc1,
580 0x00, 0x00, 0xca, 0x0c, 0x21, 0x11, 0xce, 0xf4, 0xfc, 0xb3, 0x66, 0x99, 0x4f, 0xdb, 0x4f,
581 0x95, 0x6b, 0x6f, 0x3b, 0xb1, 0xdb, 0x5a,
582 ]);
583 let pkt = Packet::unmarshal(&raw_pkt)?;
584 let raw_pkt2 = pkt.marshal()?;
585 assert_eq!(raw_pkt, raw_pkt2);
586 
587 Ok(())
588}
589 
590#[test]
591fn test_init_marshal_unmarshal() -> Result<()> {
592 let mut p = Packet {
593 common_header: CommonHeader {
594 destination_port: 1,
595 source_port: 1,
596 verification_tag: 123,
597 },
598 chunks: vec![],
599 };
600 
601 let mut init_ack = ChunkInit {
602 is_ack: true,
603 initiate_tag: 123,
604 advertised_receiver_window_credit: 1024,
605 num_outbound_streams: 1,
606 num_inbound_streams: 1,
607 initial_tsn: 123,
608 params: vec![],
609 };
610 
611 let cookie = Box::new(ParamStateCookie::new());
612 init_ack.params.push(cookie);
613 
614 p.chunks.push(Box::new(init_ack));
615 
616 let raw_pkt = p.marshal()?;
617 let pkt = Packet::unmarshal(&raw_pkt)?;
618 
619 if let Some(c) = pkt.chunks[0].as_any().downcast_ref::<ChunkInit>() {
620 assert_eq!(
621 c.initiate_tag, 123,
622 "Unmarshal passed for SCTP packet, but got incorrect initiate tag exp: {} act: {}",
623 123, c.initiate_tag
624 );
625 assert_eq!(
626 c.advertised_receiver_window_credit, 1024,
627 "Unmarshal passed for SCTP packet, but got incorrect \
628 advertisedReceiverWindowCredit exp: {} act: {}",
629 1024, c.advertised_receiver_window_credit
630 );
631 assert_eq!(
632 c.num_outbound_streams, 1,
633 "Unmarshal passed for SCTP packet, but got incorrect numOutboundStreams tag exp:{} act: {}",
634 1, c.num_outbound_streams
635 );
636 assert_eq!(
637 c.num_inbound_streams, 1,
638 "Unmarshal passed for SCTP packet, but got incorrect numInboundStreams exp: {} act: {}",
639 1, c.num_inbound_streams
640 );
641 assert_eq!(
642 c.initial_tsn, 123,
643 "Unmarshal passed for SCTP packet, but got incorrect initialTSN exp: {} act: {}",
644 123, c.initial_tsn
645 );
646 } else {
647 panic!("Failed to cast Chunk -> InitAck");
648 }
649 
650 Ok(())
651}
652 
653#[test]
654fn test_payload_data_marshal_unmarshal() -> Result<()> {
655 let raw_pkt = Bytes::from_static(&[
656 0x13, 0x88, 0x13, 0x88, 0xfc, 0xd6, 0x3f, 0xc6, 0xbe, 0xfa, 0xdc, 0x52, 0x0a, 0x00, 0x00,
657 0x24, 0x9b, 0x28, 0x7e, 0x48, 0xa3, 0x7b, 0xc1, 0x83, 0xc4, 0x4b, 0x41, 0x04, 0xa4, 0xf7,
658 0xed, 0x4c, 0x93, 0x62, 0xc3, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1f, 0xa8, 0x79, 0xa1, 0xc7, 0x00, 0x01, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x32, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
661 0x00, 0x66, 0x6f, 0x6f, 0x00,
662 ]);
663 let pkt = Packet::unmarshal(&raw_pkt)?;
664 assert!(
665 pkt.chunks[1]
666 .as_any()
667 .downcast_ref::<ChunkPayloadData>()
668 .is_some(),
669 "Failed to cast Chunk -> PayloadData"
670 );
671 Ok(())
672}
673 
674#[test]
675fn test_select_ack_chunk() -> Result<()> {
676 let raw_pkt = Bytes::from_static(&[
677 0x13, 0x88, 0x13, 0x88, 0xc2, 0x98, 0x98, 0x0f, 0x42, 0x31, 0xea, 0x78, 0x03, 0x00, 0x00,
678 0x14, 0x87, 0x73, 0xbd, 0xa4, 0x00, 0x01, 0xfe, 0x74, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
679 0x00, 0x02,
680 ]);
681 let pkt = Packet::unmarshal(&raw_pkt)?;
682 assert!(
683 pkt.chunks[0]
684 .as_any()
685 .downcast_ref::<ChunkSelectiveAck>()
686 .is_some(),
687 "Failed to cast Chunk -> SelectiveAck"
688 );
689 Ok(())
690}
691 
692#[test]
693fn test_reconfig_chunk() -> Result<()> {
694 let raw_pkt = Bytes::from_static(&[
695 0x13, 0x88, 0x13, 0x88, 0xb6, 0xa5, 0x12, 0xe5, 0x75, 0x3b, 0x12, 0xd3, 0x82, 0x0, 0x0,
696 0x16, 0x0, 0xd, 0x0, 0x12, 0x4e, 0x1c, 0xb9, 0xe6, 0x3a, 0x74, 0x8d, 0xff, 0x4e, 0x1c,
697 0xb9, 0xe6, 0x0, 0x1, 0x0, 0x0,
698 ]);
699 let pkt = Packet::unmarshal(&raw_pkt)?;
700 if let Some(c) = pkt.chunks[0].as_any().downcast_ref::<ChunkReconfig>() {
701 assert!(c.param_a.is_some(), "param_a must not be none");
702 assert_eq!(
703 c.param_a
704 .as_ref()
705 .unwrap()
706 .as_any()
707 .downcast_ref::<ParamOutgoingResetRequest>()
708 .unwrap()
709 .stream_identifiers[0],
710 1,
711 "unexpected stream identifier"
712 );
713 } else {
714 panic!("Failed to cast Chunk -> Reconfig");
715 }
716 
717 Ok(())
718}
719 
720#[test]
721fn test_forward_tsn_chunk() -> Result<()> {
722 let mut raw_pkt = BytesMut::new();
723 raw_pkt.extend(vec![
724 0x13, 0x88, 0x13, 0x88, 0xb6, 0xa5, 0x12, 0xe5, 0x1f, 0x9d, 0xa0, 0xfb,
725 ]);
726 raw_pkt.extend(CHUNK_FORWARD_TSN_BYTES.clone());
727 let raw_pkt = raw_pkt.freeze();
728 let pkt = Packet::unmarshal(&raw_pkt)?;
729 
730 if let Some(c) = pkt.chunks[0].as_any().downcast_ref::<ChunkForwardTsn>() {
731 assert_eq!(
732 c.new_cumulative_tsn, 3,
733 "unexpected New Cumulative TSN: {}",
734 c.new_cumulative_tsn
735 );
736 } else {
737 panic!("Failed to cast Chunk -> Forward TSN");
738 }
739 
740 Ok(())
741}
742 
743#[test]
744fn test_select_ack_chunk_followed_by_a_payload_data_chunk() -> Result<()> {
745 let raw_pkt = Bytes::from_static(&[
746 0x13, 0x88, 0x13, 0x88, 0xc2, 0x98, 0x98, 0x0f, 0x58, 0xcf, 0x38,
747 0xC0, // A SACK chunk follows.
748 0x03, 0x00, 0x00, 0x14, 0x87, 0x73, 0xbd, 0xa4, 0x00, 0x01, 0xfe, 0x74, 0x00, 0x01, 0x00,
749 0x00, 0x00, 0x02, 0x00, 0x02, // A payload data chunk follows.
750 0x00, 0x07, 0x00, 0x3B, 0xA4, 0x50, 0x7B, 0xC5, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
751 0x33, 0x7B, 0x22, 0x65, 0x76, 0x65, 0x6E, 0x74, 0x22, 0x3A, 0x22, 0x72, 0x65, 0x73, 0x69,
752 0x7A, 0x65, 0x22, 0x2C, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3A, 0x36, 0x36, 0x35,
753 0x2C, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3A, 0x34, 0x39, 0x39, 0x7D, 0x00,
754 ]);
755 let pkt = Packet::unmarshal(&raw_pkt)?;
756 assert!(
757 pkt.chunks[0]
758 .as_any()
759 .downcast_ref::<ChunkSelectiveAck>()
760 .is_some(),
761 "Failed to cast Chunk -> SelectiveAck"
762 );
763 assert!(
764 pkt.chunks[1]
765 .as_any()
766 .downcast_ref::<ChunkPayloadData>()
767 .is_some(),
768 "Failed to cast Chunk -> PayloadData"
769 );
770 Ok(())
771}