1 use super::{chunk_header::*, chunk_type::*, *}; 2 3 use bytes::{Buf, BufMut, Bytes, BytesMut}; 4 use std::fmt; 5 6 ///chunkSelectiveAck represents an SCTP Chunk of type SACK 7 /// 8 ///This chunk is sent to the peer endpoint to acknowledge received DATA 9 ///chunks and to inform the peer endpoint of gaps in the received 10 ///subsequences of DATA chunks as represented by their TSNs. 11 ///0 1 2 3 12 ///0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 13 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 14 ///| Type = 3 |Chunk Flags | Chunk Length | 15 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 16 ///| Cumulative TSN Ack | 17 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 18 ///| Advertised Receiver Window Credit (a_rwnd) | 19 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 20 ///| Number of Gap Ack Blocks = N | Number of Duplicate TSNs = X | 21 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 22 ///| Gap Ack Block #1 Start | Gap Ack Block #1 End | 23 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 24 ///| | 25 ///| ... | 26 ///| | 27 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 28 ///| Gap Ack Block #N Start | Gap Ack Block #N End | 29 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 30 ///| Duplicate TSN 1 | 31 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 32 ///| | 33 ///| ... | 34 ///| | 35 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 36 ///| Duplicate TSN X | 37 ///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 38 #[derive(Debug, Default, Copy, Clone)] 39 pub(crate) struct GapAckBlock { 40 pub(crate) start: u16, 41 pub(crate) end: u16, 42 } 43 44 /// makes gapAckBlock printable 45 impl fmt::Display for GapAckBlock { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 47 write!(f, "{} - {}", self.start, self.end) 48 } 49 } 50 51 #[derive(Default, Debug)] 52 pub(crate) struct ChunkSelectiveAck { 53 pub(crate) cumulative_tsn_ack: u32, 54 pub(crate) advertised_receiver_window_credit: u32, 55 pub(crate) gap_ack_blocks: Vec<GapAckBlock>, 56 pub(crate) duplicate_tsn: Vec<u32>, 57 } 58 59 /// makes chunkSelectiveAck printable 60 impl fmt::Display for ChunkSelectiveAck { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 62 let mut res = format!( 63 "SACK cumTsnAck={} arwnd={} dupTsn={:?}", 64 self.cumulative_tsn_ack, self.advertised_receiver_window_credit, self.duplicate_tsn 65 ); 66 67 for gap in &self.gap_ack_blocks { 68 res += format!("\n gap ack: {gap}").as_str(); 69 } 70 71 write!(f, "{res}") 72 } 73 } 74 75 pub(crate) const SELECTIVE_ACK_HEADER_SIZE: usize = 12; 76 77 impl Chunk for ChunkSelectiveAck { header(&self) -> ChunkHeader78 fn header(&self) -> ChunkHeader { 79 ChunkHeader { 80 typ: CT_SACK, 81 flags: 0, 82 value_length: self.value_length() as u16, 83 } 84 } 85 unmarshal(raw: &Bytes) -> Result<Self>86 fn unmarshal(raw: &Bytes) -> Result<Self> { 87 let header = ChunkHeader::unmarshal(raw)?; 88 89 if header.typ != CT_SACK { 90 return Err(Error::ErrChunkTypeNotSack); 91 } 92 93 // validity of value_length is checked in ChunkHeader::unmarshal 94 if header.value_length() < SELECTIVE_ACK_HEADER_SIZE { 95 return Err(Error::ErrSackSizeNotLargeEnoughInfo); 96 } 97 98 let reader = &mut raw.slice(CHUNK_HEADER_SIZE..CHUNK_HEADER_SIZE + header.value_length()); 99 100 let cumulative_tsn_ack = reader.get_u32(); 101 let advertised_receiver_window_credit = reader.get_u32(); 102 let gap_ack_blocks_len = reader.get_u16() as usize; 103 let duplicate_tsn_len = reader.get_u16() as usize; 104 105 // Here we must account for case where the buffer contains another chunk 106 // right after this one. Testing for equality would incorrectly fail the 107 // parsing of this chunk and incorrectly close the transport. 108 109 // validity of value_length is checked in ChunkHeader::unmarshal 110 if header.value_length() 111 < SELECTIVE_ACK_HEADER_SIZE + (4 * gap_ack_blocks_len + 4 * duplicate_tsn_len) 112 { 113 return Err(Error::ErrSackSizeNotLargeEnoughInfo); 114 } 115 116 let mut gap_ack_blocks = vec![]; 117 let mut duplicate_tsn = vec![]; 118 for _ in 0..gap_ack_blocks_len { 119 let start = reader.get_u16(); 120 let end = reader.get_u16(); 121 gap_ack_blocks.push(GapAckBlock { start, end }); 122 } 123 for _ in 0..duplicate_tsn_len { 124 duplicate_tsn.push(reader.get_u32()); 125 } 126 127 Ok(ChunkSelectiveAck { 128 cumulative_tsn_ack, 129 advertised_receiver_window_credit, 130 gap_ack_blocks, 131 duplicate_tsn, 132 }) 133 } 134 marshal_to(&self, writer: &mut BytesMut) -> Result<usize>135 fn marshal_to(&self, writer: &mut BytesMut) -> Result<usize> { 136 self.header().marshal_to(writer)?; 137 138 writer.put_u32(self.cumulative_tsn_ack); 139 writer.put_u32(self.advertised_receiver_window_credit); 140 writer.put_u16(self.gap_ack_blocks.len() as u16); 141 writer.put_u16(self.duplicate_tsn.len() as u16); 142 for g in &self.gap_ack_blocks { 143 writer.put_u16(g.start); 144 writer.put_u16(g.end); 145 } 146 for t in &self.duplicate_tsn { 147 writer.put_u32(*t); 148 } 149 150 Ok(writer.len()) 151 } 152 check(&self) -> Result<()>153 fn check(&self) -> Result<()> { 154 Ok(()) 155 } 156 value_length(&self) -> usize157 fn value_length(&self) -> usize { 158 SELECTIVE_ACK_HEADER_SIZE + self.gap_ack_blocks.len() * 4 + self.duplicate_tsn.len() * 4 159 } 160 as_any(&self) -> &(dyn Any + Send + Sync)161 fn as_any(&self) -> &(dyn Any + Send + Sync) { 162 self 163 } 164 } 165