diff --git a/sctp/CHANGELOG.md b/sctp/CHANGELOG.md index 84ae2ddd4..4507d2822 100644 --- a/sctp/CHANGELOG.md +++ b/sctp/CHANGELOG.md @@ -3,7 +3,8 @@ ## Unreleased * Performance improvements - * The lock for the internal association was contended badly because marshaling was done while still in a critical section and also tokio was scheduling tasks badly[#363](https://github.com/webrtc-rs/webrtc/pull/363) + * reuse as many allocations as possible when marshaling [#364](https://github.com/webrtc-rs/webrtc/pull/364) + * The lock for the internal association was contended badly because marshaling was done while still in a critical section and also tokio was scheduling tasks badly [#363](https://github.com/webrtc-rs/webrtc/pull/363) ## v0.7.0 diff --git a/sctp/src/chunk/chunk_payload_data.rs b/sctp/src/chunk/chunk_payload_data.rs index 0e4bd39be..5b6ceb3d8 100644 --- a/sctp/src/chunk/chunk_payload_data.rs +++ b/sctp/src/chunk/chunk_payload_data.rs @@ -233,7 +233,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/sctp/src/packet.rs b/sctp/src/packet.rs index 8b3c3e778..fd0b14273 100644 --- a/sctp/src/packet.rs +++ b/sctp/src/packet.rs @@ -20,7 +20,6 @@ use crate::util::*; use crate::chunk::chunk_unknown::ChunkUnknown; 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 @@ -155,30 +154,29 @@ impl Packet { writer.put_u16(self.destination_port); writer.put_u32(self.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; 16][..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/sctp/src/util.rs b/sctp/src/util.rs index 16663924d..9dc730cf9 100644 --- a/sctp/src/util.rs +++ b/sctp/src/util.rs @@ -11,10 +11,11 @@ pub(crate) fn get_padding_size(len: usize) -> usize { /// 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..]);