From 3605e223e978c13979b0473684f5344be8a1bbdf Mon Sep 17 00:00:00 2001 From: Marcus Asteborg Date: Thu, 16 May 2024 06:58:44 -0700 Subject: [PATCH] Port CRC optimizations from webrtc-rs/sctp made by @KillingSpark Changes from https://github.com/webrtc-rs/webrtc/pull/569 and https://github.com/webrtc-rs/webrtc/pull/364 --- Cargo.toml | 2 +- src/chunk/chunk_payload_data.rs | 2 +- src/packet.rs | 24 +++++++++++------------- src/util.rs | 8 ++++---- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6b708ea..6b0d4e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ rand = "0.8.5" slab = "0.4.9" thiserror = "1.0.58" log = "0.4.21" -crc = "3.0.1" +crc = "3.2.1" [dev-dependencies] assert_matches = "1.5.0" diff --git a/src/chunk/chunk_payload_data.rs b/src/chunk/chunk_payload_data.rs index de21adf..2be1ae2 100644 --- a/src/chunk/chunk_payload_data.rs +++ b/src/chunk/chunk_payload_data.rs @@ -224,7 +224,7 @@ impl Chunk for ChunkPayloadData { writer.put_u16(self.stream_identifier); writer.put_u16(self.stream_sequence_number); writer.put_u32(self.payload_type as u32); - writer.extend(self.user_data.clone()); + writer.extend_from_slice(&self.user_data); Ok(writer.len()) } diff --git a/src/packet.rs b/src/packet.rs index 11cb52c..6a1be88 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -18,7 +18,6 @@ use crate::error::{Error, Result}; use crate::util::*; use bytes::{Buf, BufMut, Bytes, BytesMut}; -use crc::{Crc, CRC_32_ISCSI}; use std::fmt; ///Packet represents an SCTP packet, defined in https://tools.ietf.org/html/rfc4960#section-3 @@ -278,30 +277,29 @@ impl Packet { writer.put_u16(self.common_header.destination_port); writer.put_u32(self.common_header.verification_tag); + // This is where the checksum will be written + let checksum_pos = writer.len(); + writer.extend_from_slice(&[0, 0, 0, 0]); + // Populate chunks - let mut raw = BytesMut::new(); for c in &self.chunks { - let chunk_raw = c.marshal()?; - raw.extend(chunk_raw); + c.marshal_to(writer)?; - let padding_needed = get_padding_size(raw.len()); + let padding_needed = get_padding_size(writer.len()); if padding_needed != 0 { - raw.extend(vec![0u8; padding_needed]); + // padding needed if < 4 because we pad to 4 + writer.extend_from_slice(&[0u8; PADDING_MULTIPLE][..padding_needed]); } } - let raw = raw.freeze(); - let hasher = Crc::::new(&CRC_32_ISCSI); - let mut digest = hasher.digest(); + let mut digest = ISCSI_CRC.digest(); digest.update(writer); - digest.update(&FOUR_ZEROES); - digest.update(&raw[..]); let checksum = digest.finalize(); // Checksum is already in BigEndian // Using LittleEndian stops it from being flipped - writer.put_u32_le(checksum); - writer.extend(raw); + let checksum_place = &mut writer[checksum_pos..checksum_pos + 4]; + checksum_place.copy_from_slice(&checksum.to_le_bytes()); Ok(writer.len()) } diff --git a/src/util.rs b/src/util.rs index 8934c76..03c12d0 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,7 +1,7 @@ use crate::shared::AssociationId; use bytes::Bytes; -use crc::{Crc, CRC_32_ISCSI}; +use crc::{Crc, Table, CRC_32_ISCSI}; use std::time::Duration; /// This function is non-inline to prevent the optimizer from looking inside it. @@ -72,7 +72,7 @@ impl AssociationIdGenerator for RandomAssociationIdGenerator { } } -const PADDING_MULTIPLE: usize = 4; +pub(crate) const PADDING_MULTIPLE: usize = 4; pub(crate) fn get_padding_size(len: usize) -> usize { (PADDING_MULTIPLE - (len % PADDING_MULTIPLE)) % PADDING_MULTIPLE @@ -81,11 +81,11 @@ pub(crate) fn get_padding_size(len: usize) -> usize { /// Allocate and zero this data once. /// We need to use it for the checksum and don't want to allocate/clear each time. pub(crate) static FOUR_ZEROES: Bytes = Bytes::from_static(&[0, 0, 0, 0]); +pub(crate) const ISCSI_CRC: Crc> = Crc::>::new(&CRC_32_ISCSI); /// Fastest way to do a crc32 without allocating. pub(crate) fn generate_packet_checksum(raw: &Bytes) -> u32 { - let hasher = Crc::::new(&CRC_32_ISCSI); - let mut digest = hasher.digest(); + let mut digest = ISCSI_CRC.digest(); digest.update(&raw[0..8]); digest.update(&FOUR_ZEROES[..]); digest.update(&raw[12..]);