-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(s2n-quic-core): use scatter buffers for encryption
- Loading branch information
Showing
30 changed files
with
428 additions
and
164 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
|
||
pub mod buffer; | ||
pub mod estimator; | ||
pub mod scatter; | ||
pub mod value; | ||
|
||
pub use buffer::*; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use crate::{Encoder, EncoderBuffer}; | ||
|
||
pub struct Buffer<'a> { | ||
inner: EncoderBuffer<'a>, | ||
#[cfg(feature = "bytes")] | ||
extra: Option<bytes::Bytes>, | ||
} | ||
|
||
impl<'a> Buffer<'a> { | ||
/// Ensures an extra bytes are written into the main EncoderBuffer. | ||
#[inline] | ||
pub fn flatten(&mut self) -> &mut EncoderBuffer<'a> { | ||
self.flush(); | ||
&mut self.inner | ||
} | ||
|
||
/// Resets the encoder to its initial state while also dropping any extra bytes at the end | ||
#[inline] | ||
pub fn clear(&mut self) { | ||
self.inner.set_position(0); | ||
self.extra = None; | ||
Check failure on line 24 in common/s2n-codec/src/encoder/scatter.rs GitHub Actions / crates (quic/s2n-quic-core/Cargo.toml)
Check failure on line 24 in common/s2n-codec/src/encoder/scatter.rs GitHub Actions / crates (quic/s2n-quic-platform/Cargo.toml)
Check failure on line 24 in common/s2n-codec/src/encoder/scatter.rs GitHub Actions / crates (quic/s2n-quic-crypto/Cargo.toml)
Check failure on line 24 in common/s2n-codec/src/encoder/scatter.rs GitHub Actions / crates (quic/s2n-quic-tls/Cargo.toml)
Check failure on line 24 in common/s2n-codec/src/encoder/scatter.rs GitHub Actions / crates (quic/s2n-quic-rustls/Cargo.toml)
|
||
} | ||
} | ||
|
||
/// Implement a version with `bytes` enabled | ||
#[cfg(feature = "bytes")] | ||
impl<'a> Buffer<'a> { | ||
/// Initializes a buffer without any extra bytes at the end | ||
#[inline] | ||
pub fn new(inner: EncoderBuffer<'a>) -> Self { | ||
Self { inner, extra: None } | ||
} | ||
|
||
/// Initializes the buffer with extra bytes | ||
/// | ||
/// NOTE the EncoderBuffer position should not include the extra bytes. This ensures the bytes | ||
/// can be "flushed" into the EncoderBuffer if another write happens or `flatten` is called. | ||
#[inline] | ||
pub fn new_with_extra(inner: EncoderBuffer<'a>, extra: Option<bytes::Bytes>) -> Self { | ||
Self { inner, extra } | ||
} | ||
|
||
/// Converts the buffer into its inner parts | ||
/// | ||
/// NOTE: the EncoderBuffer position will not include the extra bytes. The caller will need to | ||
/// account for this data. | ||
#[inline] | ||
pub fn into_inner(self) -> (EncoderBuffer<'a>, Option<bytes::Bytes>) { | ||
(self.inner, self.extra) | ||
} | ||
|
||
/// Returns the inner EncoderBuffer, along with the current extra bytes | ||
#[inline] | ||
pub fn inner_mut(&mut self) -> (&mut EncoderBuffer<'a>, &Option<bytes::Bytes>) { | ||
(&mut self.inner, &self.extra) | ||
} | ||
|
||
#[inline] | ||
fn flush(&mut self) { | ||
// move the extra bytes into the main buffer | ||
if let Some(extra) = self.extra.take() { | ||
self.inner.write_slice(&extra); | ||
} | ||
} | ||
} | ||
|
||
/// Include a functional implementation when `bytes` is not available | ||
#[cfg(not(feature = "bytes"))] | ||
impl<'a> Buffer<'a> { | ||
#[inline] | ||
pub fn new(inner: EncoderBuffer<'a>) -> Self { | ||
Self { inner } | ||
} | ||
|
||
#[inline] | ||
pub fn new_with_extra(inner: EncoderBuffer<'a>, extra: Option<&'static [u8]>) -> Self { | ||
debug_assert!(extra.is_none()); | ||
Self { inner } | ||
} | ||
|
||
#[inline] | ||
pub fn into_inner(self) -> (EncoderBuffer<'a>, Option<&'static [u8]>) { | ||
(self.inner, None) | ||
} | ||
|
||
#[inline] | ||
pub fn inner_mut(&mut self) -> (&mut EncoderBuffer<'a>, &Option<&'static [u8]>) { | ||
(&mut self.inner, &None) | ||
} | ||
|
||
#[inline(always)] | ||
fn flush(&mut self) {} | ||
} | ||
|
||
impl<'a> Encoder for Buffer<'a> { | ||
/// We have special handling for writes that include `Bytes` so signal that | ||
#[cfg(feature = "bytes")] | ||
const SPECIALIZES_BYTES: bool = true; | ||
|
||
#[inline] | ||
fn write_sized<F: FnOnce(&mut [u8])>(&mut self, len: usize, write: F) { | ||
// we need to flush the extra bytes if we have them | ||
self.flush(); | ||
self.inner.write_sized(len, write) | ||
} | ||
|
||
#[inline] | ||
fn write_slice(&mut self, slice: &[u8]) { | ||
// we need to flush the extra bytes if we have them | ||
self.flush(); | ||
self.inner.write_slice(slice); | ||
} | ||
|
||
#[inline] | ||
#[cfg(feature = "bytes")] | ||
fn write_bytes(&mut self, bytes: bytes::Bytes) { | ||
// we need to flush the extra bytes if we have them and replace them with the new one | ||
self.flush(); | ||
// ensure the underlying buffer is big enough for the write | ||
self.inner.assert_capacity(bytes.len()); | ||
// store the extra bytes and defer the copy | ||
self.extra = Some(bytes); | ||
} | ||
|
||
#[inline] | ||
fn write_zerocopy< | ||
T: zerocopy::AsBytes + zerocopy::FromBytes + zerocopy::Unaligned, | ||
F: FnOnce(&mut T), | ||
>( | ||
&mut self, | ||
write: F, | ||
) { | ||
// we need to flush the extra bytes if we have them | ||
self.flush(); | ||
self.inner.write_zerocopy(write); | ||
} | ||
|
||
#[inline] | ||
fn write_repeated(&mut self, count: usize, value: u8) { | ||
// we need to flush the extra bytes if we have them | ||
self.flush(); | ||
self.inner.write_repeated(count, value) | ||
} | ||
|
||
#[inline] | ||
fn capacity(&self) -> usize { | ||
self.inner.capacity() | ||
} | ||
|
||
#[inline] | ||
fn len(&self) -> usize { | ||
let mut len = self.inner.len(); | ||
|
||
// make sure our len includes the extra bytes if we have them | ||
#[cfg(feature = "bytes")] | ||
if let Some(extra) = self.extra.as_ref() { | ||
len += extra.len(); | ||
} | ||
|
||
len | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.