tokio_util/codec/length_delimited.rs
1//! Frame a stream of bytes based on a length prefix
2//!
3//! Many protocols delimit their frames by prefacing frame data with a
4//! frame head that specifies the length of the frame. The
5//! `length_delimited` module provides utilities for handling the length
6//! based framing. This allows the consumer to work with entire frames
7//! without having to worry about buffering or other framing logic.
8//!
9//! # Getting started
10//!
11//! If implementing a protocol from scratch, using length delimited framing
12//! is an easy way to get started. [`LengthDelimitedCodec::new()`] will
13//! return a length delimited codec using default configuration values.
14//! This can then be used to construct a framer to adapt a full-duplex
15//! byte stream into a stream of frames.
16//!
17//! ```
18//! use tokio::io::{AsyncRead, AsyncWrite};
19//! use tokio_util::codec::{Framed, LengthDelimitedCodec};
20//!
21//! fn bind_transport<T: AsyncRead + AsyncWrite>(io: T)
22//! -> Framed<T, LengthDelimitedCodec>
23//! {
24//! Framed::new(io, LengthDelimitedCodec::new())
25//! }
26//! # pub fn main() {}
27//! ```
28//!
29//! The returned transport implements `Sink + Stream` for `BytesMut`. It
30//! encodes the frame with a big-endian `u32` header denoting the frame
31//! payload length:
32//!
33//! ```text
34//! +----------+--------------------------------+
35//! | len: u32 | frame payload |
36//! +----------+--------------------------------+
37//! ```
38//!
39//! Specifically, given the following:
40//!
41//! ```
42//! use tokio::io::{AsyncRead, AsyncWrite};
43//! use tokio_util::codec::{Framed, LengthDelimitedCodec};
44//!
45//! use futures::SinkExt;
46//! use bytes::Bytes;
47//!
48//! async fn write_frame<T>(io: T) -> Result<(), Box<dyn std::error::Error>>
49//! where
50//! T: AsyncRead + AsyncWrite + Unpin,
51//! {
52//! let mut transport = Framed::new(io, LengthDelimitedCodec::new());
53//! let frame = Bytes::from("hello world");
54//!
55//! transport.send(frame).await?;
56//! Ok(())
57//! }
58//! ```
59//!
60//! The encoded frame will look like this:
61//!
62//! ```text
63//! +---- len: u32 ----+---- data ----+
64//! | \x00\x00\x00\x0b | hello world |
65//! +------------------+--------------+
66//! ```
67//!
68//! # Decoding
69//!
70//! [`FramedRead`] adapts an [`AsyncRead`] into a `Stream` of [`BytesMut`],
71//! such that each yielded [`BytesMut`] value contains the contents of an
72//! entire frame. There are many configuration parameters enabling
73//! [`FramedRead`] to handle a wide range of protocols. Here are some
74//! examples that will cover the various options at a high level.
75//!
76//! ## Example 1
77//!
78//! The following will parse a `u16` length field at offset 0, omitting the
79//! frame head in the yielded `BytesMut`.
80//!
81//! ```
82//! # use tokio_stream::StreamExt;
83//! # use tokio_util::codec::LengthDelimitedCodec;
84//! # #[tokio::main(flavor = "current_thread")]
85//! # async fn main() {
86//! # let io: &[u8] = b"\x00\x0BHello world";
87//! let mut reader = LengthDelimitedCodec::builder()
88//! .length_field_offset(0) // default value
89//! .length_field_type::<u16>()
90//! .length_adjustment(0) // default value
91//! .new_read(io);
92//! # let res = reader.next().await.unwrap().unwrap().to_vec();
93//! # assert_eq!(res, b"Hello world");
94//! # }
95//! ```
96//!
97//! The following frame will be decoded as such:
98//!
99//! ```text
100//! INPUT DECODED
101//! +-- len ---+--- Payload ---+ +--- Payload ---+
102//! | \x00\x0B | Hello world | --> | Hello world |
103//! +----------+---------------+ +---------------+
104//! ```
105//!
106//! The value of the length field is 11 (`\x0B`) which represents the length
107//! of the payload, `hello world`. By default, [`FramedRead`] assumes that
108//! the length field represents the number of bytes that **follows** the
109//! length field. Thus, the entire frame has a length of 13: 2 bytes for the
110//! frame head + 11 bytes for the payload.
111//!
112//! ## Example 2
113//!
114//! The following will parse a `u16` length field at offset 0, including the
115//! frame head in the yielded `BytesMut`.
116//!
117//! ```
118//! # use tokio_stream::StreamExt;
119//! # use tokio_util::codec::LengthDelimitedCodec;
120//! # #[tokio::main(flavor = "current_thread")]
121//! # async fn main() {
122//! # let io: &[u8] = b"\x00\x0BHello world";
123//! let mut reader = LengthDelimitedCodec::builder()
124//! .length_field_offset(0) // default value
125//! .length_field_type::<u16>()
126//! .length_adjustment(2) // Add head size to length
127//! .num_skip(0) // Do NOT skip the head
128//! .new_read(io);
129//! # let res = reader.next().await.unwrap().unwrap().to_vec();
130//! # assert_eq!(res, b"\x00\x0BHello world");
131//! # }
132//! ```
133//!
134//! The following frame will be decoded as such:
135//!
136//! ```text
137//! INPUT DECODED
138//! +-- len ---+--- Payload ---+ +-- len ---+--- Payload ---+
139//! | \x00\x0B | Hello world | --> | \x00\x0B | Hello world |
140//! +----------+---------------+ +----------+---------------+
141//! ```
142//!
143//! This is similar to the first example, the only difference is that the
144//! frame head is **included** in the yielded `BytesMut` value. To achieve
145//! this, we need to add the header size to the length with `length_adjustment`,
146//! and set `num_skip` to `0` to prevent skipping the head.
147//!
148//! ## Example 3
149//!
150//! The following will parse a `u16` length field at offset 0, omitting the
151//! frame head in the yielded `BytesMut`. In this case, the length field
152//! **includes** the frame head length.
153//!
154//! ```
155//! # use tokio_stream::StreamExt;
156//! # use tokio_util::codec::LengthDelimitedCodec;
157//! # #[tokio::main(flavor = "current_thread")]
158//! # async fn main() {
159//! # let io: &[u8] = b"\x00\x0DHello world";
160//! let mut reader = LengthDelimitedCodec::builder()
161//! .length_field_offset(0) // default value
162//! .length_field_type::<u16>()
163//! .length_adjustment(-2) // size of head
164//! .new_read(io);
165//! # let res = reader.next().await.unwrap().unwrap().to_vec();
166//! # assert_eq!(res, b"Hello world");
167//! # }
168//! ```
169//!
170//! The following frame will be decoded as such:
171//!
172//! ```text
173//! INPUT DECODED
174//! +-- len ---+--- Payload ---+ +--- Payload ---+
175//! | \x00\x0D | Hello world | --> | Hello world |
176//! +----------+---------------+ +---------------+
177//! ```
178//!
179//! In most cases, the length field represents the length of the payload
180//! only, as shown in the previous examples. However, in some protocols the
181//! length field represents the length of the whole frame, including the
182//! head. In such cases, we specify a negative `length_adjustment` to adjust
183//! the value provided in the frame head to represent the payload length.
184//!
185//! ## Example 4
186//!
187//! The following will parse a 3 byte length field at offset 0 in a 5 byte
188//! frame head, including the frame head in the yielded `BytesMut`.
189//!
190//! ```
191//! # use tokio_stream::StreamExt;
192//! # use tokio_util::codec::LengthDelimitedCodec;
193//! # #[tokio::main(flavor = "current_thread")]
194//! # async fn main() {
195//! # let io: &[u8] = b"\x00\x00\x0B\xCA\xFEHello world";
196//! let mut reader = LengthDelimitedCodec::builder()
197//! .length_field_offset(0) // default value
198//! .length_field_length(3)
199//! .length_adjustment(3 + 2) // len field and remaining head
200//! .num_skip(0)
201//! .new_read(io);
202//! # let res = reader.next().await.unwrap().unwrap().to_vec();
203//! # assert_eq!(res, b"\x00\x00\x0B\xCA\xFEHello world");
204//! # }
205//! ```
206//!
207//! The following frame will be decoded as such:
208//!
209//! ```text
210//! INPUT
211//! +---- len -----+- head -+--- Payload ---+
212//! | \x00\x00\x0B | \xCAFE | Hello world |
213//! +--------------+--------+---------------+
214//!
215//! DECODED
216//! +---- len -----+- head -+--- Payload ---+
217//! | \x00\x00\x0B | \xCAFE | Hello world |
218//! +--------------+--------+---------------+
219//! ```
220//!
221//! A more advanced example that shows a case where there is extra frame
222//! head data between the length field and the payload. In such cases, it is
223//! usually desirable to include the frame head as part of the yielded
224//! `BytesMut`. This lets consumers of the length delimited framer to
225//! process the frame head as needed.
226//!
227//! The positive `length_adjustment` value lets `FramedRead` factor in the
228//! additional head into the frame length calculation.
229//!
230//! ## Example 5
231//!
232//! The following will parse a `u16` length field at offset 1 of a 4 byte
233//! frame head. The first byte and the length field will be omitted from the
234//! yielded `BytesMut`, but the trailing 2 bytes of the frame head will be
235//! included.
236//!
237//! ```
238//! # use tokio_stream::StreamExt;
239//! # use tokio_util::codec::LengthDelimitedCodec;
240//! # #[tokio::main(flavor = "current_thread")]
241//! # async fn main() {
242//! # let io: &[u8] = b"\xCA\x00\x0B\xFEHello world";
243//! let mut reader = LengthDelimitedCodec::builder()
244//! .length_field_offset(1) // length of hdr1
245//! .length_field_type::<u16>()
246//! .length_adjustment(1) // length of hdr2
247//! .num_skip(3) // length of hdr1 + LEN
248//! .new_read(io);
249//! # let res = reader.next().await.unwrap().unwrap().to_vec();
250//! # assert_eq!(res, b"\xFEHello world");
251//! # }
252//! ```
253//!
254//! The following frame will be decoded as such:
255//!
256//! ```text
257//! INPUT
258//! +- hdr1 -+-- len ---+- hdr2 -+--- Payload ---+
259//! | \xCA | \x00\x0B | \xFE | Hello world |
260//! +--------+----------+--------+---------------+
261//!
262//! DECODED
263//! +- hdr2 -+--- Payload ---+
264//! | \xFE | Hello world |
265//! +--------+---------------+
266//! ```
267//!
268//! The length field is situated in the middle of the frame head. In this
269//! case, the first byte in the frame head could be a version or some other
270//! identifier that is not needed for processing. On the other hand, the
271//! second half of the head is needed.
272//!
273//! `length_field_offset` indicates how many bytes to skip before starting
274//! to read the length field. `length_adjustment` is the number of bytes to
275//! skip starting at the end of the length field. In this case, it is the
276//! second half of the head.
277//!
278//! ## Example 6
279//!
280//! The following will parse a `u16` length field at offset 1 of a 4 byte
281//! frame head. The first byte and the length field will be omitted from the
282//! yielded `BytesMut`, but the trailing 2 bytes of the frame head will be
283//! included. In this case, the length field **includes** the frame head
284//! length.
285//!
286//! ```
287//! # use tokio_stream::StreamExt;
288//! # use tokio_util::codec::LengthDelimitedCodec;
289//! # #[tokio::main(flavor = "current_thread")]
290//! # async fn main() {
291//! # let io: &[u8] = b"\xCA\x00\x0F\xFEHello world";
292//! let mut reader = LengthDelimitedCodec::builder()
293//! .length_field_offset(1) // length of hdr1
294//! .length_field_type::<u16>()
295//! .length_adjustment(-3) // length of hdr1 + LEN, negative
296//! .num_skip(3)
297//! .new_read(io);
298//! # let res = reader.next().await.unwrap().unwrap().to_vec();
299//! # assert_eq!(res, b"\xFEHello world");
300//! # }
301//! ```
302//!
303//! The following frame will be decoded as such:
304//!
305//! ```text
306//! INPUT
307//! +- hdr1 -+-- len ---+- hdr2 -+--- Payload ---+
308//! | \xCA | \x00\x0F | \xFE | Hello world |
309//! +--------+----------+--------+---------------+
310//!
311//! DECODED
312//! +- hdr2 -+--- Payload ---+
313//! | \xFE | Hello world |
314//! +--------+---------------+
315//! ```
316//!
317//! Similar to the example above, the difference is that the length field
318//! represents the length of the entire frame instead of just the payload.
319//! The length of `hdr1` and `len` must be counted in `length_adjustment`.
320//! Note that the length of `hdr2` does **not** need to be explicitly set
321//! anywhere because it already is factored into the total frame length that
322//! is read from the byte stream.
323//!
324//! ## Example 7
325//!
326//! The following will parse a 3 byte length field at offset 0 in a 4 byte
327//! frame head, excluding the 4th byte from the yielded `BytesMut`.
328//!
329//! ```
330//! # use tokio_stream::StreamExt;
331//! # use tokio_util::codec::LengthDelimitedCodec;
332//! # #[tokio::main(flavor = "current_thread")]
333//! # async fn main() {
334//! # let io: &[u8] = b"\x00\x00\x0B\xFFHello world";
335//! let mut reader = LengthDelimitedCodec::builder()
336//! .length_field_offset(0) // default value
337//! .length_field_length(3)
338//! .length_adjustment(0) // default value
339//! .num_skip(4) // skip the first 4 bytes
340//! .new_read(io);
341//! # let res = reader.next().await.unwrap().unwrap().to_vec();
342//! # assert_eq!(res, b"Hello world");
343//! # }
344//! ```
345//!
346//! The following frame will be decoded as such:
347//!
348//! ```text
349//! INPUT DECODED
350//! +------- len ------+--- Payload ---+ +--- Payload ---+
351//! | \x00\x00\x0B\xFF | Hello world | => | Hello world |
352//! +------------------+---------------+ +---------------+
353//! ```
354//!
355//! A simple example where there are unused bytes between the length field
356//! and the payload.
357//!
358//! # Encoding
359//!
360//! [`FramedWrite`] adapts an [`AsyncWrite`] into a `Sink` of [`BytesMut`],
361//! such that each submitted [`BytesMut`] is prefaced by a length field.
362//! There are fewer configuration options than [`FramedRead`]. Given
363//! protocols that have more complex frame heads, an encoder should probably
364//! be written by hand using [`Encoder`].
365//!
366//! Here is a simple example, given a `FramedWrite` with the following
367//! configuration:
368//!
369//! ```
370//! # use tokio::io::AsyncWrite;
371//! # use tokio_util::codec::LengthDelimitedCodec;
372//! # fn write_frame<T: AsyncWrite>(io: T) {
373//! # let _ =
374//! LengthDelimitedCodec::builder()
375//! .length_field_type::<u16>()
376//! .new_write(io);
377//! # }
378//! # pub fn main() {}
379//! ```
380//!
381//! A payload of `hello world` will be encoded as:
382//!
383//! ```text
384//! +- len: u16 -+---- data ----+
385//! | \x00\x0b | hello world |
386//! +------------+--------------+
387//! ```
388//!
389//! [`LengthDelimitedCodec::new()`]: method@LengthDelimitedCodec::new
390//! [`FramedRead`]: struct@FramedRead
391//! [`FramedWrite`]: struct@FramedWrite
392//! [`AsyncRead`]: trait@tokio::io::AsyncRead
393//! [`AsyncWrite`]: trait@tokio::io::AsyncWrite
394//! [`Encoder`]: trait@Encoder
395//! [`BytesMut`]: bytes::BytesMut
396
397use crate::codec::{Decoder, Encoder, Framed, FramedRead, FramedWrite};
398
399use tokio::io::{AsyncRead, AsyncWrite};
400
401use bytes::{Buf, BufMut, Bytes, BytesMut};
402use std::error::Error as StdError;
403use std::io::{self, Cursor};
404use std::{cmp, fmt, mem};
405
406/// Configure length delimited `LengthDelimitedCodec`s.
407///
408/// `Builder` enables constructing configured length delimited codecs. Note
409/// that not all configuration settings apply to both encoding and decoding. See
410/// the documentation for specific methods for more detail.
411///
412/// Note that the if the value of [`Builder::max_frame_length`] becomes larger than
413/// what can actually fit in [`Builder::length_field_length`], it will be clipped to
414/// the maximum value that can fit.
415#[derive(Debug, Clone, Copy)]
416pub struct Builder {
417 // Maximum frame length
418 max_frame_len: usize,
419
420 // Number of bytes representing the field length
421 length_field_len: usize,
422
423 // Number of bytes in the header before the length field
424 length_field_offset: usize,
425
426 // Adjust the length specified in the header field by this amount
427 length_adjustment: isize,
428
429 // Total number of bytes to skip before reading the payload, if not set,
430 // `length_field_len + length_field_offset`
431 num_skip: Option<usize>,
432
433 // Length field byte order (little or big endian)
434 length_field_is_big_endian: bool,
435}
436
437/// An error when the number of bytes read is more than max frame length.
438pub struct LengthDelimitedCodecError {
439 _priv: (),
440}
441
442/// A codec for frames delimited by a frame head specifying their lengths.
443///
444/// This allows the consumer to work with entire frames without having to worry
445/// about buffering or other framing logic.
446///
447/// See [module level] documentation for more detail.
448///
449/// [module level]: index.html
450#[derive(Debug, Clone)]
451pub struct LengthDelimitedCodec {
452 // Configuration values
453 builder: Builder,
454
455 // Read state
456 state: DecodeState,
457}
458
459#[derive(Debug, Clone, Copy)]
460enum DecodeState {
461 Head,
462 Data(usize),
463}
464
465// ===== impl LengthDelimitedCodec ======
466
467impl LengthDelimitedCodec {
468 /// Creates a new `LengthDelimitedCodec` with the default configuration values.
469 pub fn new() -> Self {
470 Self {
471 builder: Builder::new(),
472 state: DecodeState::Head,
473 }
474 }
475
476 /// Creates a new length delimited codec builder with default configuration
477 /// values.
478 pub fn builder() -> Builder {
479 Builder::new()
480 }
481
482 /// Returns the current max frame setting
483 ///
484 /// This is the largest size this codec will accept from the wire. Larger
485 /// frames will be rejected.
486 pub fn max_frame_length(&self) -> usize {
487 self.builder.max_frame_len
488 }
489
490 /// Updates the max frame setting.
491 ///
492 /// The change takes effect the next time a frame is decoded. In other
493 /// words, if a frame is currently in process of being decoded with a frame
494 /// size greater than `val` but less than the max frame length in effect
495 /// before calling this function, then the frame will be allowed.
496 ///
497 /// If `val` is larger than what the length field can represent, it is
498 /// clipped to the maximum representable value.
499 pub fn set_max_frame_length(&mut self, val: usize) {
500 self.builder.max_frame_length(val);
501 self.builder.adjust_max_frame_len();
502 }
503
504 fn decode_head(&mut self, src: &mut BytesMut) -> io::Result<Option<usize>> {
505 let head_len = self.builder.num_head_bytes();
506 let field_len = self.builder.length_field_len;
507
508 if src.len() < head_len {
509 // Not enough data
510 return Ok(None);
511 }
512
513 let n = {
514 let mut src = Cursor::new(&mut *src);
515
516 // Skip the required bytes
517 src.advance(self.builder.length_field_offset);
518
519 // match endianness
520 let n = if self.builder.length_field_is_big_endian {
521 src.get_uint(field_len)
522 } else {
523 src.get_uint_le(field_len)
524 };
525
526 if n > self.builder.max_frame_len as u64 {
527 return Err(io::Error::new(
528 io::ErrorKind::InvalidData,
529 LengthDelimitedCodecError { _priv: () },
530 ));
531 }
532
533 // The check above ensures there is no overflow
534 let n = n as usize;
535
536 // Adjust `n` with bounds checking
537 let n = if self.builder.length_adjustment < 0 {
538 n.checked_sub(-self.builder.length_adjustment as usize)
539 } else {
540 n.checked_add(self.builder.length_adjustment as usize)
541 };
542
543 // Error handling
544 match n {
545 Some(n) => n,
546 None => {
547 return Err(io::Error::new(
548 io::ErrorKind::InvalidInput,
549 "provided length would overflow after adjustment",
550 ));
551 }
552 }
553 };
554
555 src.advance(self.builder.get_num_skip());
556
557 // Ensure that the buffer has enough space to read the incoming
558 // payload
559 src.reserve(n.saturating_sub(src.len()));
560
561 Ok(Some(n))
562 }
563
564 fn decode_data(&self, n: usize, src: &mut BytesMut) -> Option<BytesMut> {
565 // At this point, the buffer has already had the required capacity
566 // reserved. All there is to do is read.
567 if src.len() < n {
568 return None;
569 }
570
571 Some(src.split_to(n))
572 }
573}
574
575impl Decoder for LengthDelimitedCodec {
576 type Item = BytesMut;
577 type Error = io::Error;
578
579 fn decode(&mut self, src: &mut BytesMut) -> io::Result<Option<BytesMut>> {
580 let n = match self.state {
581 DecodeState::Head => match self.decode_head(src)? {
582 Some(n) => {
583 self.state = DecodeState::Data(n);
584 n
585 }
586 None => return Ok(None),
587 },
588 DecodeState::Data(n) => n,
589 };
590
591 match self.decode_data(n, src) {
592 Some(data) => {
593 // Update the decode state
594 self.state = DecodeState::Head;
595
596 // Make sure the buffer has enough space to read the next head
597 src.reserve(self.builder.num_head_bytes().saturating_sub(src.len()));
598
599 Ok(Some(data))
600 }
601 None => Ok(None),
602 }
603 }
604}
605
606impl Encoder<&[u8]> for LengthDelimitedCodec {
607 type Error = io::Error;
608
609 fn encode(&mut self, data: &[u8], dst: &mut BytesMut) -> Result<(), io::Error> {
610 let n = data.len();
611
612 if n > self.builder.max_frame_len {
613 return Err(io::Error::new(
614 io::ErrorKind::InvalidInput,
615 LengthDelimitedCodecError { _priv: () },
616 ));
617 }
618
619 // Adjust `n` with bounds checking
620 let n = if self.builder.length_adjustment < 0 {
621 n.checked_add(-self.builder.length_adjustment as usize)
622 } else {
623 n.checked_sub(self.builder.length_adjustment as usize)
624 };
625
626 let n = n.ok_or_else(|| {
627 io::Error::new(
628 io::ErrorKind::InvalidInput,
629 "provided length would overflow after adjustment",
630 )
631 })?;
632
633 // Reserve capacity in the destination buffer to fit the frame and
634 // length field.
635 dst.reserve(self.builder.length_field_len + data.len());
636
637 if self.builder.length_field_is_big_endian {
638 dst.put_uint(n as u64, self.builder.length_field_len);
639 } else {
640 dst.put_uint_le(n as u64, self.builder.length_field_len);
641 }
642
643 // Write the frame to the buffer
644 dst.extend_from_slice(data);
645
646 Ok(())
647 }
648}
649
650impl Encoder<Bytes> for LengthDelimitedCodec {
651 type Error = io::Error;
652
653 fn encode(&mut self, data: Bytes, dst: &mut BytesMut) -> Result<(), io::Error> {
654 Encoder::<&[u8]>::encode(self, data.as_ref(), dst)
655 }
656}
657
658impl Default for LengthDelimitedCodec {
659 fn default() -> Self {
660 Self::new()
661 }
662}
663
664// ===== impl Builder =====
665
666mod builder {
667 /// Types that can be used with `Builder::length_field_type`.
668 pub trait LengthFieldType {}
669
670 impl LengthFieldType for u8 {}
671 impl LengthFieldType for u16 {}
672 impl LengthFieldType for u32 {}
673 impl LengthFieldType for u64 {}
674
675 #[cfg(any(
676 target_pointer_width = "16",
677 target_pointer_width = "32",
678 target_pointer_width = "64",
679 ))]
680 impl LengthFieldType for usize {}
681}
682
683impl Builder {
684 /// Creates a new length delimited codec builder with default configuration
685 /// values.
686 ///
687 /// # Examples
688 ///
689 /// ```
690 /// use tokio_util::codec::LengthDelimitedCodec;
691 /// use tokio_stream::StreamExt;
692 ///
693 /// # #[tokio::main(flavor = "current_thread")]
694 /// # async fn main() {
695 /// let io: &[u8] = b"\x00\x0bhello world";
696 /// let mut reader = LengthDelimitedCodec::builder()
697 /// .length_field_offset(0)
698 /// .length_field_type::<u16>()
699 /// .length_adjustment(0)
700 /// .new_read(io);
701 ///
702 /// let frame = reader.next().await.unwrap().unwrap();
703 /// assert_eq!(&frame[..], b"hello world");
704 /// # }
705 /// ```
706 pub fn new() -> Builder {
707 Builder {
708 // Default max frame length of 8MB
709 max_frame_len: 8 * 1_024 * 1_024,
710
711 // Default byte length of 4
712 length_field_len: 4,
713
714 // Default to the header field being at the start of the header.
715 length_field_offset: 0,
716
717 length_adjustment: 0,
718
719 // Total number of bytes to skip before reading the payload, if not set,
720 // `length_field_len + length_field_offset`
721 num_skip: None,
722
723 // Default to reading the length field in network (big) endian.
724 length_field_is_big_endian: true,
725 }
726 }
727
728 /// Read the length field as a big endian integer
729 ///
730 /// This is the default setting.
731 ///
732 /// This configuration option applies to both encoding and decoding.
733 ///
734 /// # Examples
735 ///
736 /// ```
737 /// # use tokio::io::AsyncRead;
738 /// use tokio_util::codec::LengthDelimitedCodec;
739 ///
740 /// # fn bind_read<T: AsyncRead>(io: T) {
741 /// LengthDelimitedCodec::builder()
742 /// .big_endian()
743 /// .new_read(io);
744 /// # }
745 /// # pub fn main() {}
746 /// ```
747 pub fn big_endian(&mut self) -> &mut Self {
748 self.length_field_is_big_endian = true;
749 self
750 }
751
752 /// Read the length field as a little endian integer
753 ///
754 /// The default setting is big endian.
755 ///
756 /// This configuration option applies to both encoding and decoding.
757 ///
758 /// # Examples
759 ///
760 /// ```
761 /// # use tokio::io::AsyncRead;
762 /// use tokio_util::codec::LengthDelimitedCodec;
763 ///
764 /// # fn bind_read<T: AsyncRead>(io: T) {
765 /// LengthDelimitedCodec::builder()
766 /// .little_endian()
767 /// .new_read(io);
768 /// # }
769 /// # pub fn main() {}
770 /// ```
771 pub fn little_endian(&mut self) -> &mut Self {
772 self.length_field_is_big_endian = false;
773 self
774 }
775
776 /// Read the length field as a native endian integer
777 ///
778 /// The default setting is big endian.
779 ///
780 /// This configuration option applies to both encoding and decoding.
781 ///
782 /// # Examples
783 ///
784 /// ```
785 /// # use tokio::io::AsyncRead;
786 /// use tokio_util::codec::LengthDelimitedCodec;
787 ///
788 /// # fn bind_read<T: AsyncRead>(io: T) {
789 /// LengthDelimitedCodec::builder()
790 /// .native_endian()
791 /// .new_read(io);
792 /// # }
793 /// # pub fn main() {}
794 /// ```
795 pub fn native_endian(&mut self) -> &mut Self {
796 if cfg!(target_endian = "big") {
797 self.big_endian()
798 } else {
799 self.little_endian()
800 }
801 }
802
803 /// Sets the max frame length in bytes
804 ///
805 /// This configuration option applies to both encoding and decoding. The
806 /// default value is 8MB.
807 ///
808 /// When decoding, the length field read from the byte stream is checked
809 /// against this setting **before** any adjustments are applied. When
810 /// encoding, the length of the submitted payload is checked against this
811 /// setting.
812 ///
813 /// When frames exceed the max length, an `io::Error` with the custom value
814 /// of the `LengthDelimitedCodecError` type will be returned.
815 ///
816 /// # Examples
817 ///
818 /// ```
819 /// # use tokio::io::AsyncRead;
820 /// use tokio_util::codec::LengthDelimitedCodec;
821 ///
822 /// # fn bind_read<T: AsyncRead>(io: T) {
823 /// LengthDelimitedCodec::builder()
824 /// .max_frame_length(8 * 1024 * 1024)
825 /// .new_read(io);
826 /// # }
827 /// # pub fn main() {}
828 /// ```
829 pub fn max_frame_length(&mut self, val: usize) -> &mut Self {
830 self.max_frame_len = val;
831 self
832 }
833
834 /// Sets the unsigned integer type used to represent the length field.
835 ///
836 /// The default type is [`u32`]. The max type is [`u64`] (or [`usize`] on
837 /// 64-bit targets).
838 ///
839 /// # Examples
840 ///
841 /// ```
842 /// # use tokio::io::AsyncRead;
843 /// use tokio_util::codec::LengthDelimitedCodec;
844 ///
845 /// # fn bind_read<T: AsyncRead>(io: T) {
846 /// LengthDelimitedCodec::builder()
847 /// .length_field_type::<u32>()
848 /// .new_read(io);
849 /// # }
850 /// # pub fn main() {}
851 /// ```
852 ///
853 /// Unlike [`Builder::length_field_length`], this does not fail at runtime
854 /// and instead produces a compile error:
855 ///
856 /// ```compile_fail
857 /// # use tokio::io::AsyncRead;
858 /// # use tokio_util::codec::LengthDelimitedCodec;
859 /// # fn bind_read<T: AsyncRead>(io: T) {
860 /// LengthDelimitedCodec::builder()
861 /// .length_field_type::<u128>()
862 /// .new_read(io);
863 /// # }
864 /// # pub fn main() {}
865 /// ```
866 pub fn length_field_type<T: builder::LengthFieldType>(&mut self) -> &mut Self {
867 self.length_field_length(mem::size_of::<T>())
868 }
869
870 /// Sets the number of bytes used to represent the length field
871 ///
872 /// The default value is `4`. The max value is `8`.
873 ///
874 /// This configuration option applies to both encoding and decoding.
875 ///
876 /// # Examples
877 ///
878 /// ```
879 /// # use tokio::io::AsyncRead;
880 /// use tokio_util::codec::LengthDelimitedCodec;
881 ///
882 /// # fn bind_read<T: AsyncRead>(io: T) {
883 /// LengthDelimitedCodec::builder()
884 /// .length_field_length(4)
885 /// .new_read(io);
886 /// # }
887 /// # pub fn main() {}
888 /// ```
889 pub fn length_field_length(&mut self, val: usize) -> &mut Self {
890 assert!(val > 0 && val <= 8, "invalid length field length");
891 self.length_field_len = val;
892 self
893 }
894
895 /// Sets the number of bytes in the header before the length field
896 ///
897 /// This configuration option only applies to decoding.
898 ///
899 /// # Examples
900 ///
901 /// ```
902 /// # use tokio::io::AsyncRead;
903 /// use tokio_util::codec::LengthDelimitedCodec;
904 ///
905 /// # fn bind_read<T: AsyncRead>(io: T) {
906 /// LengthDelimitedCodec::builder()
907 /// .length_field_offset(1)
908 /// .new_read(io);
909 /// # }
910 /// # pub fn main() {}
911 /// ```
912 pub fn length_field_offset(&mut self, val: usize) -> &mut Self {
913 self.length_field_offset = val;
914 self
915 }
916
917 /// Delta between the payload length specified in the header and the real
918 /// payload length
919 ///
920 /// # Examples
921 ///
922 /// ```
923 /// # use tokio::io::AsyncRead;
924 /// use tokio_util::codec::LengthDelimitedCodec;
925 ///
926 /// # fn bind_read<T: AsyncRead>(io: T) {
927 /// LengthDelimitedCodec::builder()
928 /// .length_adjustment(-2)
929 /// .new_read(io);
930 /// # }
931 /// # pub fn main() {}
932 /// ```
933 pub fn length_adjustment(&mut self, val: isize) -> &mut Self {
934 self.length_adjustment = val;
935 self
936 }
937
938 /// Sets the number of bytes to skip before reading the payload
939 ///
940 /// Default value is `length_field_len + length_field_offset`
941 ///
942 /// This configuration option only applies to decoding
943 ///
944 /// # Examples
945 ///
946 /// ```
947 /// # use tokio::io::AsyncRead;
948 /// use tokio_util::codec::LengthDelimitedCodec;
949 ///
950 /// # fn bind_read<T: AsyncRead>(io: T) {
951 /// LengthDelimitedCodec::builder()
952 /// .num_skip(4)
953 /// .new_read(io);
954 /// # }
955 /// # pub fn main() {}
956 /// ```
957 pub fn num_skip(&mut self, val: usize) -> &mut Self {
958 self.num_skip = Some(val);
959 self
960 }
961
962 /// Create a configured length delimited `LengthDelimitedCodec`
963 ///
964 /// # Examples
965 ///
966 /// ```
967 /// use bytes::{Bytes, BytesMut};
968 /// use tokio_util::codec::{Decoder, Encoder, LengthDelimitedCodec};
969 ///
970 /// # pub fn main() {
971 /// let mut codec = LengthDelimitedCodec::builder()
972 /// .length_field_offset(0)
973 /// .length_field_type::<u16>()
974 /// .length_adjustment(0)
975 /// .new_codec();
976 ///
977 /// let mut buf = BytesMut::new();
978 /// codec.encode(Bytes::from_static(b"hello world"), &mut buf).unwrap();
979 /// let frame = codec.decode(&mut buf).unwrap().unwrap();
980 /// assert_eq!(&frame[..], b"hello world");
981 /// # }
982 /// ```
983 pub fn new_codec(&self) -> LengthDelimitedCodec {
984 let mut builder = *self;
985
986 builder.adjust_max_frame_len();
987
988 LengthDelimitedCodec {
989 builder,
990 state: DecodeState::Head,
991 }
992 }
993
994 /// Create a configured length delimited `FramedRead`
995 ///
996 /// # Examples
997 ///
998 /// ```
999 /// use tokio_util::codec::LengthDelimitedCodec;
1000 /// use tokio_stream::StreamExt;
1001 ///
1002 /// # #[tokio::main(flavor = "current_thread")]
1003 /// # async fn main() {
1004 /// let io: &[u8] = b"\x00\x0bhello world";
1005 /// let mut reader = LengthDelimitedCodec::builder()
1006 /// .length_field_offset(0)
1007 /// .length_field_type::<u16>()
1008 /// .length_adjustment(0)
1009 /// .new_read(io);
1010 ///
1011 /// let frame = reader.next().await.unwrap().unwrap();
1012 /// assert_eq!(&frame[..], b"hello world");
1013 /// # }
1014 /// ```
1015 pub fn new_read<T>(&self, upstream: T) -> FramedRead<T, LengthDelimitedCodec>
1016 where
1017 T: AsyncRead,
1018 {
1019 FramedRead::new(upstream, self.new_codec())
1020 }
1021
1022 /// Create a configured length delimited `FramedWrite`
1023 ///
1024 /// # Examples
1025 ///
1026 /// ```
1027 /// # use tokio::io::AsyncWrite;
1028 /// # use tokio_util::codec::LengthDelimitedCodec;
1029 /// # fn write_frame<T: AsyncWrite>(io: T) {
1030 /// LengthDelimitedCodec::builder()
1031 /// .length_field_type::<u16>()
1032 /// .new_write(io);
1033 /// # }
1034 /// # pub fn main() {}
1035 /// ```
1036 pub fn new_write<T>(&self, inner: T) -> FramedWrite<T, LengthDelimitedCodec>
1037 where
1038 T: AsyncWrite,
1039 {
1040 FramedWrite::new(inner, self.new_codec())
1041 }
1042
1043 /// Create a configured length delimited `Framed`
1044 ///
1045 /// # Examples
1046 ///
1047 /// ```
1048 /// # use tokio::io::{AsyncRead, AsyncWrite};
1049 /// # use tokio_util::codec::LengthDelimitedCodec;
1050 /// # fn write_frame<T: AsyncRead + AsyncWrite>(io: T) {
1051 /// # let _ =
1052 /// LengthDelimitedCodec::builder()
1053 /// .length_field_type::<u16>()
1054 /// .new_framed(io);
1055 /// # }
1056 /// # pub fn main() {}
1057 /// ```
1058 pub fn new_framed<T>(&self, inner: T) -> Framed<T, LengthDelimitedCodec>
1059 where
1060 T: AsyncRead + AsyncWrite,
1061 {
1062 Framed::new(inner, self.new_codec())
1063 }
1064
1065 fn num_head_bytes(&self) -> usize {
1066 let num = self.length_field_offset + self.length_field_len;
1067 cmp::max(num, self.num_skip.unwrap_or_default())
1068 }
1069
1070 fn get_num_skip(&self) -> usize {
1071 self.num_skip
1072 .unwrap_or(self.length_field_offset + self.length_field_len)
1073 }
1074
1075 fn adjust_max_frame_len(&mut self) {
1076 let max_allowed_len = self.max_allowed_frame_len();
1077
1078 if self.max_frame_len > max_allowed_len {
1079 self.max_frame_len = max_allowed_len;
1080 }
1081 }
1082
1083 fn max_allowed_frame_len(&self) -> usize {
1084 let max_allowed_len = self
1085 .max_length_field_value()
1086 .saturating_add_signed(self.length_adjustment as i64);
1087
1088 usize::try_from(max_allowed_len).unwrap_or(usize::MAX)
1089 }
1090
1091 fn max_length_field_value(&self) -> u64 {
1092 match 1u64.checked_shl((8 * self.length_field_len) as u32) {
1093 Some(shl) => shl - 1,
1094 None => u64::MAX,
1095 }
1096 }
1097}
1098
1099impl Default for Builder {
1100 fn default() -> Self {
1101 Self::new()
1102 }
1103}
1104
1105// ===== impl LengthDelimitedCodecError =====
1106
1107impl fmt::Debug for LengthDelimitedCodecError {
1108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1109 f.debug_struct("LengthDelimitedCodecError").finish()
1110 }
1111}
1112
1113impl fmt::Display for LengthDelimitedCodecError {
1114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1115 f.write_str("frame size too big")
1116 }
1117}
1118
1119impl StdError for LengthDelimitedCodecError {}