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