/__w/smoldot/smoldot/repo/lib/src/libp2p/connection/yamux/header.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Smoldot |
2 | | // Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. |
3 | | // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 |
4 | | |
5 | | // This program is free software: you can redistribute it and/or modify |
6 | | // it under the terms of the GNU General Public License as published by |
7 | | // the Free Software Foundation, either version 3 of the License, or |
8 | | // (at your option) any later version. |
9 | | |
10 | | // This program is distributed in the hope that it will be useful, |
11 | | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | // GNU General Public License for more details. |
14 | | |
15 | | // You should have received a copy of the GNU General Public License |
16 | | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | | |
18 | | //! Decodes Yamux headers. |
19 | | //! |
20 | | //! See <https://github.com/hashicorp/yamux/blob/master/spec.md> |
21 | | |
22 | | use core::num::NonZeroU32; |
23 | | |
24 | | /// A Yamux header in its decoded form. |
25 | | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
26 | | pub enum DecodedYamuxHeader { |
27 | | Data { |
28 | | /// Value of the SYN flag. |
29 | | syn: bool, |
30 | | /// Value of the ACK flag. |
31 | | ack: bool, |
32 | | /// Value of the FIN flag. |
33 | | fin: bool, |
34 | | /// Value of the RST flag. |
35 | | rst: bool, |
36 | | stream_id: NonZeroU32, |
37 | | length: u32, |
38 | | }, |
39 | | Window { |
40 | | /// Value of the SYN flag. |
41 | | syn: bool, |
42 | | /// Value of the ACK flag. |
43 | | ack: bool, |
44 | | /// Value of the FIN flag. |
45 | | fin: bool, |
46 | | /// Value of the RST flag. |
47 | | rst: bool, |
48 | | stream_id: NonZeroU32, |
49 | | length: u32, |
50 | | }, |
51 | | PingRequest { |
52 | | opaque_value: u32, |
53 | | }, |
54 | | PingResponse { |
55 | | opaque_value: u32, |
56 | | }, |
57 | | GoAway { |
58 | | error_code: GoAwayErrorCode, |
59 | | }, |
60 | | } |
61 | | |
62 | | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
63 | | pub enum GoAwayErrorCode { |
64 | | NormalTermination = 0x0, |
65 | | ProtocolError = 0x1, |
66 | | InternalError = 0x2, |
67 | | } |
68 | | |
69 | | /// Encodes a Yamux header. |
70 | 1.07k | pub fn encode(header: &DecodedYamuxHeader) -> [u8; 12] { |
71 | 1.07k | match header { |
72 | | DecodedYamuxHeader::Data { |
73 | 569 | syn, |
74 | 569 | ack, |
75 | 569 | fin, |
76 | 569 | rst, |
77 | 569 | stream_id, |
78 | 569 | length, |
79 | | } |
80 | | | DecodedYamuxHeader::Window { |
81 | 500 | syn, |
82 | 500 | ack, |
83 | 500 | fin, |
84 | 500 | rst, |
85 | 500 | stream_id, |
86 | 500 | length, |
87 | | } => { |
88 | 1.06k | let ty = match header { |
89 | 569 | DecodedYamuxHeader::Data { .. } => 0, |
90 | 500 | DecodedYamuxHeader::Window { .. } => 1, |
91 | 0 | _ => unreachable!(), |
92 | | }; |
93 | | |
94 | 1.06k | let mut flags: u8 = 0; |
95 | 1.06k | if *syn { |
96 | 511 | flags |= 0x1; |
97 | 558 | } |
98 | 1.06k | if *ack { |
99 | 533 | flags |= 0x2; |
100 | 536 | } |
101 | 1.06k | if *fin { |
102 | 517 | flags |= 0x4; |
103 | 552 | } |
104 | 1.06k | if *rst { |
105 | 484 | flags |= 0x8; |
106 | 585 | } |
107 | | |
108 | 1.06k | let stream_id = stream_id.get().to_be_bytes(); |
109 | 1.06k | let length = length.to_be_bytes(); |
110 | 1.06k | |
111 | 1.06k | [ |
112 | 1.06k | 0, |
113 | 1.06k | ty, |
114 | 1.06k | 0, |
115 | 1.06k | flags, |
116 | 1.06k | stream_id[0], |
117 | 1.06k | stream_id[1], |
118 | 1.06k | stream_id[2], |
119 | 1.06k | stream_id[3], |
120 | 1.06k | length[0], |
121 | 1.06k | length[1], |
122 | 1.06k | length[2], |
123 | 1.06k | length[3], |
124 | 1.06k | ] |
125 | | } |
126 | 1 | DecodedYamuxHeader::PingRequest { opaque_value } |
127 | 1 | | DecodedYamuxHeader::PingResponse { opaque_value } => { |
128 | 2 | let flags = match header { |
129 | 1 | DecodedYamuxHeader::PingRequest { .. } => 1, |
130 | 1 | DecodedYamuxHeader::PingResponse { .. } => 2, |
131 | 0 | _ => unreachable!(), |
132 | | }; |
133 | | |
134 | 2 | let opaque_value = opaque_value.to_be_bytes(); |
135 | 2 | |
136 | 2 | [ |
137 | 2 | 0, |
138 | 2 | 2, |
139 | 2 | 0, |
140 | 2 | flags, |
141 | 2 | 0, |
142 | 2 | 0, |
143 | 2 | 0, |
144 | 2 | 0, |
145 | 2 | opaque_value[0], |
146 | 2 | opaque_value[1], |
147 | 2 | opaque_value[2], |
148 | 2 | opaque_value[3], |
149 | 2 | ] |
150 | | } |
151 | 3 | DecodedYamuxHeader::GoAway { error_code } => { |
152 | 3 | let code = match error_code { |
153 | 1 | GoAwayErrorCode::NormalTermination => 0, |
154 | 1 | GoAwayErrorCode::ProtocolError => 1, |
155 | 1 | GoAwayErrorCode::InternalError => 2, |
156 | | }; |
157 | | |
158 | 3 | [0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, code] |
159 | | } |
160 | | } |
161 | 1.07k | } _RNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header6encode Line | Count | Source | 70 | 1.07k | pub fn encode(header: &DecodedYamuxHeader) -> [u8; 12] { | 71 | 1.07k | match header { | 72 | | DecodedYamuxHeader::Data { | 73 | 569 | syn, | 74 | 569 | ack, | 75 | 569 | fin, | 76 | 569 | rst, | 77 | 569 | stream_id, | 78 | 569 | length, | 79 | | } | 80 | | | DecodedYamuxHeader::Window { | 81 | 500 | syn, | 82 | 500 | ack, | 83 | 500 | fin, | 84 | 500 | rst, | 85 | 500 | stream_id, | 86 | 500 | length, | 87 | | } => { | 88 | 1.06k | let ty = match header { | 89 | 569 | DecodedYamuxHeader::Data { .. } => 0, | 90 | 500 | DecodedYamuxHeader::Window { .. } => 1, | 91 | 0 | _ => unreachable!(), | 92 | | }; | 93 | | | 94 | 1.06k | let mut flags: u8 = 0; | 95 | 1.06k | if *syn { | 96 | 511 | flags |= 0x1; | 97 | 558 | } | 98 | 1.06k | if *ack { | 99 | 533 | flags |= 0x2; | 100 | 536 | } | 101 | 1.06k | if *fin { | 102 | 517 | flags |= 0x4; | 103 | 552 | } | 104 | 1.06k | if *rst { | 105 | 484 | flags |= 0x8; | 106 | 585 | } | 107 | | | 108 | 1.06k | let stream_id = stream_id.get().to_be_bytes(); | 109 | 1.06k | let length = length.to_be_bytes(); | 110 | 1.06k | | 111 | 1.06k | [ | 112 | 1.06k | 0, | 113 | 1.06k | ty, | 114 | 1.06k | 0, | 115 | 1.06k | flags, | 116 | 1.06k | stream_id[0], | 117 | 1.06k | stream_id[1], | 118 | 1.06k | stream_id[2], | 119 | 1.06k | stream_id[3], | 120 | 1.06k | length[0], | 121 | 1.06k | length[1], | 122 | 1.06k | length[2], | 123 | 1.06k | length[3], | 124 | 1.06k | ] | 125 | | } | 126 | 1 | DecodedYamuxHeader::PingRequest { opaque_value } | 127 | 1 | | DecodedYamuxHeader::PingResponse { opaque_value } => { | 128 | 2 | let flags = match header { | 129 | 1 | DecodedYamuxHeader::PingRequest { .. } => 1, | 130 | 1 | DecodedYamuxHeader::PingResponse { .. } => 2, | 131 | 0 | _ => unreachable!(), | 132 | | }; | 133 | | | 134 | 2 | let opaque_value = opaque_value.to_be_bytes(); | 135 | 2 | | 136 | 2 | [ | 137 | 2 | 0, | 138 | 2 | 2, | 139 | 2 | 0, | 140 | 2 | flags, | 141 | 2 | 0, | 142 | 2 | 0, | 143 | 2 | 0, | 144 | 2 | 0, | 145 | 2 | opaque_value[0], | 146 | 2 | opaque_value[1], | 147 | 2 | opaque_value[2], | 148 | 2 | opaque_value[3], | 149 | 2 | ] | 150 | | } | 151 | 3 | DecodedYamuxHeader::GoAway { error_code } => { | 152 | 3 | let code = match error_code { | 153 | 1 | GoAwayErrorCode::NormalTermination => 0, | 154 | 1 | GoAwayErrorCode::ProtocolError => 1, | 155 | 1 | GoAwayErrorCode::InternalError => 2, | 156 | | }; | 157 | | | 158 | 3 | [0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, code] | 159 | | } | 160 | | } | 161 | 1.07k | } |
Unexecuted instantiation: _RNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header6encode |
162 | | |
163 | | /// Decodes a Yamux header. |
164 | 1.09k | pub fn decode_yamux_header(bytes: &[u8; 12]) -> Result<DecodedYamuxHeader, YamuxHeaderDecodeError> { |
165 | 1.09k | match nom::combinator::all_consuming(nom::combinator::complete(decode))(bytes) { |
166 | 1.08k | Ok((_, h)) => Ok(h), |
167 | 0 | Err(nom::Err::Incomplete(_)) => unreachable!(), |
168 | 15 | Err(nom::Err::Failure(err0 ) | nom::Err::Error(err)) => Err(YamuxHeaderDecodeError { |
169 | 15 | offset: err.input.as_ptr() as usize - bytes.as_ptr() as usize, |
170 | 15 | }), |
171 | | } |
172 | 1.09k | } _RNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header19decode_yamux_header Line | Count | Source | 164 | 1.09k | pub fn decode_yamux_header(bytes: &[u8; 12]) -> Result<DecodedYamuxHeader, YamuxHeaderDecodeError> { | 165 | 1.09k | match nom::combinator::all_consuming(nom::combinator::complete(decode))(bytes) { | 166 | 1.08k | Ok((_, h)) => Ok(h), | 167 | 0 | Err(nom::Err::Incomplete(_)) => unreachable!(), | 168 | 15 | Err(nom::Err::Failure(err0 ) | nom::Err::Error(err)) => Err(YamuxHeaderDecodeError { | 169 | 15 | offset: err.input.as_ptr() as usize - bytes.as_ptr() as usize, | 170 | 15 | }), | 171 | | } | 172 | 1.09k | } |
Unexecuted instantiation: _RNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header19decode_yamux_header |
173 | | |
174 | | /// Error while decoding a Yamux header. |
175 | 0 | #[derive(Debug, derive_more::Display)] Unexecuted instantiation: _RNvXsb_NtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6headerNtB5_22YamuxHeaderDecodeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXsb_NtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6headerNtB5_22YamuxHeaderDecodeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
176 | | #[display(fmt = "Error at offset {offset}")] |
177 | | pub struct YamuxHeaderDecodeError { |
178 | | offset: usize, |
179 | | } |
180 | | |
181 | 1.09k | fn decode(bytes: &'_ [u8]) -> nom::IResult<&'_ [u8], DecodedYamuxHeader> { |
182 | 1.09k | nom::sequence::preceded( |
183 | 1.09k | nom::bytes::streaming::tag(&[0]), |
184 | 1.09k | nom::branch::alt(( |
185 | 1.09k | nom::combinator::map( |
186 | 1.09k | nom::sequence::tuple(( |
187 | 1.09k | nom::bytes::streaming::tag(&[0]), |
188 | 1.09k | flags, |
189 | 1.09k | nom::combinator::map_opt(nom::number::streaming::be_u32, NonZeroU32::new), |
190 | 1.09k | nom::number::streaming::be_u32, |
191 | 1.09k | )), |
192 | 1.09k | |(_, (syn, ack, fin, rst), stream_id, length)| DecodedYamuxHeader::Data { |
193 | 569 | syn, |
194 | 569 | ack, |
195 | 569 | fin, |
196 | 569 | rst, |
197 | 569 | stream_id, |
198 | 569 | length, |
199 | 1.09k | }, _RNCNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header6decode0Bb_ Line | Count | Source | 192 | 569 | |(_, (syn, ack, fin, rst), stream_id, length)| DecodedYamuxHeader::Data { | 193 | 569 | syn, | 194 | 569 | ack, | 195 | 569 | fin, | 196 | 569 | rst, | 197 | 569 | stream_id, | 198 | 569 | length, | 199 | 569 | }, |
Unexecuted instantiation: _RNCNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header6decode0Bb_ |
200 | 1.09k | ), |
201 | 1.09k | nom::combinator::map( |
202 | 1.09k | nom::sequence::tuple(( |
203 | 1.09k | nom::bytes::streaming::tag(&[1]), |
204 | 1.09k | flags, |
205 | 1.09k | nom::combinator::map_opt(nom::number::streaming::be_u32, NonZeroU32::new), |
206 | 1.09k | nom::number::streaming::be_u32, |
207 | 1.09k | )), |
208 | 1.09k | |(_, (syn, ack, fin, rst), stream_id, length)| DecodedYamuxHeader::Window { |
209 | 500 | syn, |
210 | 500 | ack, |
211 | 500 | fin, |
212 | 500 | rst, |
213 | 500 | stream_id, |
214 | 500 | length, |
215 | 1.09k | }, _RNCNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header6decodes_0Bb_ Line | Count | Source | 208 | 500 | |(_, (syn, ack, fin, rst), stream_id, length)| DecodedYamuxHeader::Window { | 209 | 500 | syn, | 210 | 500 | ack, | 211 | 500 | fin, | 212 | 500 | rst, | 213 | 500 | stream_id, | 214 | 500 | length, | 215 | 500 | }, |
Unexecuted instantiation: _RNCNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header6decodes_0Bb_ |
216 | 1.09k | ), |
217 | 1.09k | nom::combinator::map( |
218 | 1.09k | nom::sequence::tuple(( |
219 | 1.09k | nom::bytes::streaming::tag(&[2]), |
220 | 1.09k | nom::bytes::streaming::tag(&[0x0, 0x1]), |
221 | 1.09k | nom::bytes::streaming::tag(&[0, 0, 0, 0]), |
222 | 1.09k | nom::number::streaming::be_u32, |
223 | 1.09k | )), |
224 | 1.09k | |(_, _, _, opaque_value)| DecodedYamuxHeader::PingRequest { opaque_value }3 , _RNCNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header6decodes0_0Bb_ Line | Count | Source | 224 | 3 | |(_, _, _, opaque_value)| DecodedYamuxHeader::PingRequest { opaque_value }, |
Unexecuted instantiation: _RNCNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header6decodes0_0Bb_ |
225 | 1.09k | ), |
226 | 1.09k | nom::combinator::map( |
227 | 1.09k | nom::sequence::tuple(( |
228 | 1.09k | nom::bytes::streaming::tag(&[2]), |
229 | 1.09k | nom::bytes::streaming::tag(&[0x0, 0x2]), |
230 | 1.09k | nom::bytes::streaming::tag(&[0, 0, 0, 0]), |
231 | 1.09k | nom::number::streaming::be_u32, |
232 | 1.09k | )), |
233 | 1.09k | |(_, _, _, opaque_value)| DecodedYamuxHeader::PingResponse { opaque_value }3 , _RNCNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header6decodes1_0Bb_ Line | Count | Source | 233 | 3 | |(_, _, _, opaque_value)| DecodedYamuxHeader::PingResponse { opaque_value }, |
Unexecuted instantiation: _RNCNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header6decodes1_0Bb_ |
234 | 1.09k | ), |
235 | 1.09k | nom::combinator::map( |
236 | 1.09k | nom::sequence::tuple(( |
237 | 1.09k | nom::bytes::streaming::tag(&[3]), |
238 | 1.09k | nom::bytes::streaming::tag(&[0, 0]), |
239 | 1.09k | nom::bytes::streaming::tag(&[0, 0, 0, 0]), |
240 | 1.09k | nom::branch::alt(( |
241 | 1.09k | nom::combinator::map( |
242 | 1.09k | nom::bytes::streaming::tag(0u32.to_be_bytes()), |
243 | 1.09k | |_| GoAwayErrorCode::NormalTermination2 , _RNCNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header6decodes2_0Bb_ Line | Count | Source | 243 | 2 | |_| GoAwayErrorCode::NormalTermination, |
Unexecuted instantiation: _RNCNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header6decodes2_0Bb_ |
244 | 1.09k | ), |
245 | 1.09k | nom::combinator::map( |
246 | 1.09k | nom::bytes::streaming::tag(1u32.to_be_bytes()), |
247 | 1.09k | |_| GoAwayErrorCode::ProtocolError2 , _RNCNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header6decodes3_0Bb_ Line | Count | Source | 247 | 2 | |_| GoAwayErrorCode::ProtocolError, |
Unexecuted instantiation: _RNCNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header6decodes3_0Bb_ |
248 | 1.09k | ), |
249 | 1.09k | nom::combinator::map( |
250 | 1.09k | nom::bytes::streaming::tag(2u32.to_be_bytes()), |
251 | 1.09k | |_| GoAwayErrorCode::InternalError2 , _RNCNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header6decodes4_0Bb_ Line | Count | Source | 251 | 2 | |_| GoAwayErrorCode::InternalError, |
Unexecuted instantiation: _RNCNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header6decodes4_0Bb_ |
252 | 1.09k | ), |
253 | 1.09k | )), |
254 | 1.09k | )), |
255 | 1.09k | |(_, _, _, error_code)| DecodedYamuxHeader::GoAway { error_code }6 , _RNCNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header6decodes5_0Bb_ Line | Count | Source | 255 | 6 | |(_, _, _, error_code)| DecodedYamuxHeader::GoAway { error_code }, |
Unexecuted instantiation: _RNCNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header6decodes5_0Bb_ |
256 | 1.09k | ), |
257 | 1.09k | )), |
258 | 1.09k | )(bytes) |
259 | 1.09k | } _RNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header6decode Line | Count | Source | 181 | 1.09k | fn decode(bytes: &'_ [u8]) -> nom::IResult<&'_ [u8], DecodedYamuxHeader> { | 182 | 1.09k | nom::sequence::preceded( | 183 | 1.09k | nom::bytes::streaming::tag(&[0]), | 184 | 1.09k | nom::branch::alt(( | 185 | 1.09k | nom::combinator::map( | 186 | 1.09k | nom::sequence::tuple(( | 187 | 1.09k | nom::bytes::streaming::tag(&[0]), | 188 | 1.09k | flags, | 189 | 1.09k | nom::combinator::map_opt(nom::number::streaming::be_u32, NonZeroU32::new), | 190 | 1.09k | nom::number::streaming::be_u32, | 191 | 1.09k | )), | 192 | 1.09k | |(_, (syn, ack, fin, rst), stream_id, length)| DecodedYamuxHeader::Data { | 193 | | syn, | 194 | | ack, | 195 | | fin, | 196 | | rst, | 197 | | stream_id, | 198 | | length, | 199 | 1.09k | }, | 200 | 1.09k | ), | 201 | 1.09k | nom::combinator::map( | 202 | 1.09k | nom::sequence::tuple(( | 203 | 1.09k | nom::bytes::streaming::tag(&[1]), | 204 | 1.09k | flags, | 205 | 1.09k | nom::combinator::map_opt(nom::number::streaming::be_u32, NonZeroU32::new), | 206 | 1.09k | nom::number::streaming::be_u32, | 207 | 1.09k | )), | 208 | 1.09k | |(_, (syn, ack, fin, rst), stream_id, length)| DecodedYamuxHeader::Window { | 209 | | syn, | 210 | | ack, | 211 | | fin, | 212 | | rst, | 213 | | stream_id, | 214 | | length, | 215 | 1.09k | }, | 216 | 1.09k | ), | 217 | 1.09k | nom::combinator::map( | 218 | 1.09k | nom::sequence::tuple(( | 219 | 1.09k | nom::bytes::streaming::tag(&[2]), | 220 | 1.09k | nom::bytes::streaming::tag(&[0x0, 0x1]), | 221 | 1.09k | nom::bytes::streaming::tag(&[0, 0, 0, 0]), | 222 | 1.09k | nom::number::streaming::be_u32, | 223 | 1.09k | )), | 224 | 1.09k | |(_, _, _, opaque_value)| DecodedYamuxHeader::PingRequest { opaque_value }, | 225 | 1.09k | ), | 226 | 1.09k | nom::combinator::map( | 227 | 1.09k | nom::sequence::tuple(( | 228 | 1.09k | nom::bytes::streaming::tag(&[2]), | 229 | 1.09k | nom::bytes::streaming::tag(&[0x0, 0x2]), | 230 | 1.09k | nom::bytes::streaming::tag(&[0, 0, 0, 0]), | 231 | 1.09k | nom::number::streaming::be_u32, | 232 | 1.09k | )), | 233 | 1.09k | |(_, _, _, opaque_value)| DecodedYamuxHeader::PingResponse { opaque_value }, | 234 | 1.09k | ), | 235 | 1.09k | nom::combinator::map( | 236 | 1.09k | nom::sequence::tuple(( | 237 | 1.09k | nom::bytes::streaming::tag(&[3]), | 238 | 1.09k | nom::bytes::streaming::tag(&[0, 0]), | 239 | 1.09k | nom::bytes::streaming::tag(&[0, 0, 0, 0]), | 240 | 1.09k | nom::branch::alt(( | 241 | 1.09k | nom::combinator::map( | 242 | 1.09k | nom::bytes::streaming::tag(0u32.to_be_bytes()), | 243 | 1.09k | |_| GoAwayErrorCode::NormalTermination, | 244 | 1.09k | ), | 245 | 1.09k | nom::combinator::map( | 246 | 1.09k | nom::bytes::streaming::tag(1u32.to_be_bytes()), | 247 | 1.09k | |_| GoAwayErrorCode::ProtocolError, | 248 | 1.09k | ), | 249 | 1.09k | nom::combinator::map( | 250 | 1.09k | nom::bytes::streaming::tag(2u32.to_be_bytes()), | 251 | 1.09k | |_| GoAwayErrorCode::InternalError, | 252 | 1.09k | ), | 253 | 1.09k | )), | 254 | 1.09k | )), | 255 | 1.09k | |(_, _, _, error_code)| DecodedYamuxHeader::GoAway { error_code }, | 256 | 1.09k | ), | 257 | 1.09k | )), | 258 | 1.09k | )(bytes) | 259 | 1.09k | } |
Unexecuted instantiation: _RNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header6decode |
260 | | |
261 | 1.06k | fn flags(bytes: &'_ [u8]) -> nom::IResult<&'_ [u8], (bool, bool, bool, bool)> { |
262 | 1.06k | nom::combinator::map_opt(nom::number::streaming::be_u16, |flags| { |
263 | 1.06k | let syn = (flags & 0x1) != 0; |
264 | 1.06k | let ack = (flags & 0x2) != 0; |
265 | 1.06k | let fin = (flags & 0x4) != 0; |
266 | 1.06k | let rst = (flags & 0x8) != 0; |
267 | 1.06k | if (flags & !0b1111) != 0 { |
268 | 0 | return None; |
269 | 1.06k | } |
270 | 1.06k | Some((syn, ack, fin, rst)) |
271 | 1.06k | })(bytes) _RNCNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header5flags0Bb_ Line | Count | Source | 262 | 1.06k | nom::combinator::map_opt(nom::number::streaming::be_u16, |flags| { | 263 | 1.06k | let syn = (flags & 0x1) != 0; | 264 | 1.06k | let ack = (flags & 0x2) != 0; | 265 | 1.06k | let fin = (flags & 0x4) != 0; | 266 | 1.06k | let rst = (flags & 0x8) != 0; | 267 | 1.06k | if (flags & !0b1111) != 0 { | 268 | 0 | return None; | 269 | 1.06k | } | 270 | 1.06k | Some((syn, ack, fin, rst)) | 271 | 1.06k | })(bytes) |
Unexecuted instantiation: _RNCNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header5flags0Bb_ |
272 | 1.06k | } _RNvNtNtNtNtCsN16ciHI6Qf_7smoldot6libp2p10connection5yamux6header5flags Line | Count | Source | 261 | 1.06k | fn flags(bytes: &'_ [u8]) -> nom::IResult<&'_ [u8], (bool, bool, bool, bool)> { | 262 | 1.06k | nom::combinator::map_opt(nom::number::streaming::be_u16, |flags| { | 263 | | let syn = (flags & 0x1) != 0; | 264 | | let ack = (flags & 0x2) != 0; | 265 | | let fin = (flags & 0x4) != 0; | 266 | | let rst = (flags & 0x8) != 0; | 267 | | if (flags & !0b1111) != 0 { | 268 | | return None; | 269 | | } | 270 | | Some((syn, ack, fin, rst)) | 271 | 1.06k | })(bytes) | 272 | 1.06k | } |
Unexecuted instantiation: _RNvNtNtNtNtCseuYC0Zibziv_7smoldot6libp2p10connection5yamux6header5flags |
273 | | |
274 | | #[cfg(test)] |
275 | | mod tests { |
276 | | use core::num::NonZeroU32; |
277 | | |
278 | | #[test] |
279 | 1 | fn decode_data_frame() { |
280 | 1 | assert_eq!( |
281 | 1 | super::decode_yamux_header(&[0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 2, 65]).unwrap(), |
282 | 1 | super::DecodedYamuxHeader::Data { |
283 | 1 | syn: true, |
284 | 1 | ack: false, |
285 | 1 | fin: false, |
286 | 1 | rst: false, |
287 | 1 | stream_id: NonZeroU32::new(15).unwrap(), |
288 | 1 | length: 577 |
289 | 1 | } |
290 | 1 | ); |
291 | 1 | } |
292 | | |
293 | | #[test] |
294 | 1 | fn decode_ping_frame() { |
295 | 1 | assert_eq!( |
296 | 1 | super::decode_yamux_header(&[0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 1, 12]).unwrap(), |
297 | 1 | super::DecodedYamuxHeader::PingRequest { opaque_value: 268 } |
298 | 1 | ); |
299 | | |
300 | 1 | assert_eq!( |
301 | 1 | super::decode_yamux_header(&[0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 1, 12]).unwrap(), |
302 | 1 | super::DecodedYamuxHeader::PingResponse { opaque_value: 268 } |
303 | 1 | ); |
304 | | |
305 | 1 | assert!(super::decode_yamux_header(&[0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).is_err()); |
306 | | |
307 | 1 | assert!(super::decode_yamux_header(&[0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]).is_ok()); |
308 | 1 | assert!(super::decode_yamux_header(&[0, 2, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0]).is_err()); |
309 | | |
310 | 1 | assert!(super::decode_yamux_header(&[0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]).is_ok()); |
311 | 1 | assert!(super::decode_yamux_header(&[0, 2, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0]).is_err()); |
312 | | |
313 | 1 | assert!(super::decode_yamux_header(&[0, 2, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0]).is_err()); |
314 | 1 | assert!(super::decode_yamux_header(&[0, 2, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0]).is_err()); |
315 | 1 | assert!(super::decode_yamux_header(&[0, 2, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0]).is_err()); |
316 | 1 | assert!(super::decode_yamux_header(&[0, 2, 0, 17, 0, 0, 0, 1, 0, 0, 0, 0]).is_err()); |
317 | 1 | } |
318 | | |
319 | | #[test] |
320 | 1 | fn decode_goaway() { |
321 | 1 | assert_eq!( |
322 | 1 | super::decode_yamux_header(&[0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap(), |
323 | 1 | super::DecodedYamuxHeader::GoAway { |
324 | 1 | error_code: super::GoAwayErrorCode::NormalTermination, |
325 | 1 | } |
326 | 1 | ); |
327 | | |
328 | 1 | assert_eq!( |
329 | 1 | super::decode_yamux_header(&[0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]).unwrap(), |
330 | 1 | super::DecodedYamuxHeader::GoAway { |
331 | 1 | error_code: super::GoAwayErrorCode::ProtocolError, |
332 | 1 | } |
333 | 1 | ); |
334 | | |
335 | 1 | assert_eq!( |
336 | 1 | super::decode_yamux_header(&[0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]).unwrap(), |
337 | 1 | super::DecodedYamuxHeader::GoAway { |
338 | 1 | error_code: super::GoAwayErrorCode::InternalError, |
339 | 1 | } |
340 | 1 | ); |
341 | | |
342 | 1 | assert!(super::decode_yamux_header(&[0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]).is_err()); |
343 | 1 | assert!(super::decode_yamux_header(&[0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]).is_err()); |
344 | 1 | assert!(super::decode_yamux_header(&[0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]).is_err()); |
345 | 1 | assert!(super::decode_yamux_header(&[0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]).is_err()); |
346 | 1 | assert!(super::decode_yamux_header(&[0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]).is_err()); |
347 | 1 | assert!(super::decode_yamux_header(&[0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]).is_err()); |
348 | 1 | assert!(super::decode_yamux_header(&[0, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]).is_err()); |
349 | 1 | } |
350 | | |
351 | | #[test] |
352 | 1 | fn version_check() { |
353 | 1 | assert!(super::decode_yamux_header(&[0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 2, 65]).is_ok()); |
354 | 1 | assert!(super::decode_yamux_header(&[2, 0, 0, 1, 0, 0, 0, 15, 0, 0, 2, 65]).is_err()); |
355 | 1 | } |
356 | | |
357 | | macro_rules! check_encode_redecodes { |
358 | | ($payload:expr) => {{ |
359 | | let payload = $payload; |
360 | | assert_eq!( |
361 | | super::decode_yamux_header(&super::encode(&payload)).unwrap(), |
362 | | payload |
363 | | ); |
364 | | }}; |
365 | | } |
366 | | |
367 | | #[test] |
368 | 1 | fn encode_data() { |
369 | 501 | for _ in 0..500 { |
370 | 500 | check_encode_redecodes!(super::DecodedYamuxHeader::Data { |
371 | 500 | syn: rand::random(), |
372 | 500 | ack: rand::random(), |
373 | 500 | fin: rand::random(), |
374 | 500 | rst: rand::random(), |
375 | 500 | stream_id: rand::random(), |
376 | 500 | length: rand::random() |
377 | 500 | }); |
378 | | } |
379 | 1 | } |
380 | | |
381 | | #[test] |
382 | 1 | fn encode_window() { |
383 | 501 | for _ in 0..500 { |
384 | 500 | check_encode_redecodes!(super::DecodedYamuxHeader::Window { |
385 | 500 | syn: rand::random(), |
386 | 500 | ack: rand::random(), |
387 | 500 | fin: rand::random(), |
388 | 500 | rst: rand::random(), |
389 | 500 | stream_id: rand::random(), |
390 | 500 | length: rand::random() |
391 | 500 | }); |
392 | | } |
393 | 1 | } |
394 | | |
395 | | #[test] |
396 | 1 | fn encode_ping() { |
397 | 1 | check_encode_redecodes!(super::DecodedYamuxHeader::PingRequest { |
398 | 1 | opaque_value: rand::random(), |
399 | 1 | }); |
400 | | |
401 | 1 | check_encode_redecodes!(super::DecodedYamuxHeader::PingResponse { |
402 | 1 | opaque_value: rand::random(), |
403 | 1 | }); |
404 | 1 | } |
405 | | |
406 | | #[test] |
407 | 1 | fn encode_goaway() { |
408 | 1 | check_encode_redecodes!(super::DecodedYamuxHeader::GoAway { |
409 | 1 | error_code: super::GoAwayErrorCode::NormalTermination, |
410 | 1 | }); |
411 | | |
412 | 1 | check_encode_redecodes!(super::DecodedYamuxHeader::GoAway { |
413 | 1 | error_code: super::GoAwayErrorCode::ProtocolError, |
414 | 1 | }); |
415 | | |
416 | 1 | check_encode_redecodes!(super::DecodedYamuxHeader::GoAway { |
417 | 1 | error_code: super::GoAwayErrorCode::InternalError, |
418 | 1 | }); |
419 | 1 | } |
420 | | } |