Skip to content

Commit 5e62f8a

Browse files
committed
Remove BufLen and switch to BufMut::remaining_mut
When writing frames into packets it needs to be known how much space there is in the packets. This used to be done using a max offset into a larger buffer. This now switches this round to use BufMut::remaining_mut, which makes accessing this information easier and also removes carrying this around as an extra parameter.
1 parent 7162c51 commit 5e62f8a

File tree

4 files changed

+48
-89
lines changed

4 files changed

+48
-89
lines changed

quinn-proto/src/connection/datagrams.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use bytes::{BufMut, Bytes};
44
use thiserror::Error;
55
use tracing::{debug, trace};
66

7-
use super::{BufLen, Connection};
7+
use super::Connection;
88
use crate::{
99
TransportError,
1010
frame::{Datagram, FrameStruct},
@@ -163,13 +163,13 @@ impl DatagramState {
163163
///
164164
/// Returns whether a frame was written. At most `max_size` bytes will be written, including
165165
/// framing.
166-
pub(super) fn write(&mut self, buf: &mut (impl BufMut + BufLen), max_size: usize) -> bool {
166+
pub(super) fn write(&mut self, buf: &mut impl BufMut) -> bool {
167167
let datagram = match self.outgoing.pop_front() {
168168
Some(x) => x,
169169
None => return false,
170170
};
171171

172-
if buf.len() + datagram.size(true) > max_size {
172+
if datagram.size(true) > buf.remaining_mut() {
173173
// Future work: we could be more clever about cramming small datagrams into
174174
// mostly-full packets when a larger one is queued first
175175
self.outgoing.push_front(datagram);

quinn-proto/src/connection/mod.rs

Lines changed: 18 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -848,13 +848,11 @@ impl Connection {
848848
}
849849
}
850850

851-
let sent = self.populate_packet(
852-
now,
853-
space_id,
854-
&mut transmit.datagram_mut(),
855-
builder.max_size,
856-
builder.exact_number,
857-
);
851+
let sent = {
852+
let frame_space = builder.max_size - transmit.datagram_mut().len();
853+
let mut buf = transmit.datagram_mut().limit(frame_space);
854+
self.populate_packet(now, space_id, &mut buf, builder.exact_number)
855+
};
858856

859857
// ACK-only packets should only be sent when explicitly allowed. If we write them due to
860858
// any other reason, there is a bug which leads to one component announcing write
@@ -3040,8 +3038,7 @@ impl Connection {
30403038
&mut self,
30413039
now: Instant,
30423040
space_id: SpaceId,
3043-
buf: &mut (impl BufMut + BufLen),
3044-
max_size: usize,
3041+
buf: &mut impl BufMut,
30453042
pn: u64,
30463043
) -> SentFrames {
30473044
let mut sent = SentFrames::default();
@@ -3117,7 +3114,7 @@ impl Connection {
31173114
}
31183115

31193116
// PATH_CHALLENGE
3120-
if buf.len() + 9 < max_size && space_id == SpaceId::Data {
3117+
if 9 < buf.remaining_mut() && space_id == SpaceId::Data {
31213118
// Transmit challenges with every outgoing frame on an unvalidated path
31223119
if let Some(token) = self.path.challenge {
31233120
// But only send a packet solely for that purpose at most once
@@ -3132,7 +3129,7 @@ impl Connection {
31323129
}
31333130

31343131
// PATH_RESPONSE
3135-
if buf.len() + 9 < max_size && space_id == SpaceId::Data {
3132+
if 9 < buf.remaining_mut() && space_id == SpaceId::Data {
31363133
if let Some(token) = self.path_responses.pop_on_path(self.path.remote) {
31373134
sent.non_retransmits = true;
31383135
sent.requires_padding = true;
@@ -3144,7 +3141,7 @@ impl Connection {
31443141
}
31453142

31463143
// CRYPTO
3147-
while buf.len() + frame::Crypto::SIZE_BOUND < max_size && !is_0rtt {
3144+
while frame::Crypto::SIZE_BOUND < buf.remaining_mut() && !is_0rtt {
31483145
let mut frame = match space.pending.crypto.pop_front() {
31493146
Some(x) => x,
31503147
None => break,
@@ -3154,8 +3151,7 @@ impl Connection {
31543151
// Since the offset is known, we can reserve the exact size required to encode it.
31553152
// For length we reserve 2bytes which allows to encode up to 2^14,
31563153
// which is more than what fits into normally sized QUIC frames.
3157-
let max_crypto_data_size = max_size
3158-
- buf.len()
3154+
let max_crypto_data_size = buf.remaining_mut()
31593155
- 1 // Frame Type
31603156
- VarInt::size(unsafe { VarInt::from_u64_unchecked(frame.offset) })
31613157
- 2; // Maximum encoded length for frame size, given we send less than 2^14 bytes
@@ -3191,12 +3187,11 @@ impl Connection {
31913187
&mut space.pending,
31923188
&mut sent.retransmits,
31933189
&mut self.stats.frame_tx,
3194-
max_size,
31953190
);
31963191
}
31973192

31983193
// NEW_CONNECTION_ID
3199-
while buf.len() + 44 < max_size {
3194+
while 44 < buf.remaining_mut() {
32003195
let issued = match space.pending.new_cids.pop() {
32013196
Some(x) => x,
32023197
None => break,
@@ -3218,7 +3213,7 @@ impl Connection {
32183213
}
32193214

32203215
// RETIRE_CONNECTION_ID
3221-
while buf.len() + frame::RETIRE_CONNECTION_ID_SIZE_BOUND < max_size {
3216+
while frame::RETIRE_CONNECTION_ID_SIZE_BOUND < buf.remaining_mut() {
32223217
let seq = match space.pending.retire_cids.pop() {
32233218
Some(x) => x,
32243219
None => break,
@@ -3232,8 +3227,8 @@ impl Connection {
32323227

32333228
// DATAGRAM
32343229
let mut sent_datagrams = false;
3235-
while buf.len() + Datagram::SIZE_BOUND < max_size && space_id == SpaceId::Data {
3236-
match self.datagrams.write(buf, max_size) {
3230+
while Datagram::SIZE_BOUND < buf.remaining_mut() && space_id == SpaceId::Data {
3231+
match self.datagrams.write(buf) {
32373232
true => {
32383233
sent_datagrams = true;
32393234
sent.non_retransmits = true;
@@ -3273,7 +3268,7 @@ impl Connection {
32733268
token: token.encode(&*server_config.token_key).into(),
32743269
};
32753270

3276-
if buf.len() + new_token.size() >= max_size {
3271+
if new_token.size() >= buf.remaining_mut() {
32773272
space.pending.new_tokens.push(remote_addr);
32783273
break;
32793274
}
@@ -3288,9 +3283,9 @@ impl Connection {
32883283

32893284
// STREAM
32903285
if space_id == SpaceId::Data {
3291-
sent.stream_frames =
3292-
self.streams
3293-
.write_stream_frames(buf, max_size, self.config.send_fairness);
3286+
sent.stream_frames = self
3287+
.streams
3288+
.write_stream_frames(buf, self.config.send_fairness);
32943289
self.stats.frame_tx.stream += sent.stream_frames.len() as u64;
32953290
}
32963291

@@ -3976,29 +3971,6 @@ fn negotiate_max_idle_timeout(x: Option<VarInt>, y: Option<VarInt>) -> Option<Du
39763971
}
39773972
}
39783973

3979-
/// A buffer that can tell how much has been written to it already
3980-
///
3981-
/// This is commonly used for when a buffer is passed and the user may not write past a
3982-
/// given size. It allows the user of such a buffer to know the current cursor position in
3983-
/// the buffer. The maximum write size is usually passed in the same unit as
3984-
/// [`BufLen::len`]: bytes since the buffer start.
3985-
pub(crate) trait BufLen {
3986-
/// Returns the number of bytes written into the buffer so far
3987-
fn len(&self) -> usize;
3988-
}
3989-
3990-
impl BufLen for Vec<u8> {
3991-
fn len(&self) -> usize {
3992-
self.len()
3993-
}
3994-
}
3995-
3996-
impl BufLen for bytes::buf::Limit<&mut Vec<u8>> {
3997-
fn len(&self) -> usize {
3998-
self.get_ref().len()
3999-
}
4000-
}
4001-
40023974
#[cfg(test)]
40033975
mod tests {
40043976
use super::*;

quinn-proto/src/connection/streams/state.rs

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use super::{
1515
use crate::{
1616
Dir, MAX_STREAM_COUNT, Side, StreamId, TransportError, VarInt,
1717
coding::BufMutExt,
18-
connection::{BufLen, stats::FrameStats},
18+
connection::stats::FrameStats,
1919
frame::{self, FrameStruct, StreamMetaVec},
2020
transport_parameters::TransportParameters,
2121
};
@@ -411,14 +411,13 @@ impl StreamsState {
411411

412412
pub(in crate::connection) fn write_control_frames(
413413
&mut self,
414-
buf: &mut (impl BufMut + BufLen),
414+
buf: &mut impl BufMut,
415415
pending: &mut Retransmits,
416416
retransmits: &mut ThinRetransmits,
417417
stats: &mut FrameStats,
418-
max_size: usize,
419418
) {
420419
// RESET_STREAM
421-
while buf.len() + frame::ResetStream::SIZE_BOUND < max_size {
420+
while frame::ResetStream::SIZE_BOUND < buf.remaining_mut() {
422421
let (id, error_code) = match pending.reset_stream.pop() {
423422
Some(x) => x,
424423
None => break,
@@ -442,7 +441,7 @@ impl StreamsState {
442441
}
443442

444443
// STOP_SENDING
445-
while buf.len() + frame::StopSending::SIZE_BOUND < max_size {
444+
while frame::StopSending::SIZE_BOUND < buf.remaining_mut() {
446445
let frame = match pending.stop_sending.pop() {
447446
Some(x) => x,
448447
None => break,
@@ -461,7 +460,7 @@ impl StreamsState {
461460
}
462461

463462
// MAX_DATA
464-
if pending.max_data && buf.len() + 9 < max_size {
463+
if pending.max_data && 9 < buf.remaining_mut() {
465464
pending.max_data = false;
466465

467466
// `local_max_data` can grow bigger than `VarInt`.
@@ -484,7 +483,7 @@ impl StreamsState {
484483
}
485484

486485
// MAX_STREAM_DATA
487-
while buf.len() + 17 < max_size {
486+
while 17 < buf.remaining_mut() {
488487
let id = match pending.max_stream_data.iter().next() {
489488
Some(x) => *x,
490489
None => break,
@@ -516,7 +515,7 @@ impl StreamsState {
516515

517516
// MAX_STREAMS
518517
for dir in Dir::iter() {
519-
if !pending.max_stream_id[dir as usize] || buf.len() + 9 >= max_size {
518+
if !pending.max_stream_id[dir as usize] || 9 >= buf.remaining_mut() {
520519
continue;
521520
}
522521

@@ -541,19 +540,11 @@ impl StreamsState {
541540

542541
pub(crate) fn write_stream_frames(
543542
&mut self,
544-
buf: &mut (impl BufMut + BufLen),
545-
max_buf_size: usize,
543+
buf: &mut impl BufMut,
546544
fair: bool,
547545
) -> StreamMetaVec {
548546
let mut stream_frames = StreamMetaVec::new();
549-
while buf.len() + frame::Stream::SIZE_BOUND < max_buf_size {
550-
if max_buf_size
551-
.checked_sub(buf.len() + frame::Stream::SIZE_BOUND)
552-
.is_none()
553-
{
554-
break;
555-
}
556-
547+
while frame::Stream::SIZE_BOUND < buf.remaining_mut() {
557548
// Pop the stream of the highest priority that currently has pending data
558549
// If the stream still has some pending data left after writing, it will be reinserted, otherwise not
559550
let Some(stream) = self.pending.pop() else {
@@ -577,7 +568,7 @@ impl StreamsState {
577568

578569
// Now that we know the `StreamId`, we can better account for how many bytes
579570
// are required to encode it.
580-
let max_buf_size = max_buf_size - buf.len() - 1 - VarInt::size(id.into());
571+
let max_buf_size = buf.remaining_mut() - 1 - VarInt::size(id.into());
581572
let (offsets, encode_length) = stream.pending.poll_transmit(max_buf_size);
582573
let fin = offsets.end == stream.pending.offset()
583574
&& matches!(stream.state, SendState::DataSent { .. });
@@ -1379,8 +1370,8 @@ mod tests {
13791370
high.set_priority(1).unwrap();
13801371
high.write(b"high").unwrap();
13811372

1382-
let mut buf = Vec::with_capacity(40);
1383-
let meta = server.write_stream_frames(&mut buf, 40, true);
1373+
let buf = Vec::with_capacity(40);
1374+
let meta = server.write_stream_frames(&mut buf.limit(40), true);
13841375
assert_eq!(meta[0].id, id_high);
13851376
assert_eq!(meta[1].id, id_mid);
13861377
assert_eq!(meta[2].id, id_low);
@@ -1438,16 +1429,18 @@ mod tests {
14381429
};
14391430
high.set_priority(-1).unwrap();
14401431

1441-
let mut buf = Vec::with_capacity(1000);
1442-
let meta = server.write_stream_frames(&mut buf, 40, true);
1432+
let buf = Vec::with_capacity(1000);
1433+
let mut buf = buf.limit(40);
1434+
let meta = server.write_stream_frames(&mut buf, true);
1435+
let buf = buf.into_inner();
14431436
assert_eq!(meta.len(), 1);
14441437
assert_eq!(meta[0].id, id_high);
14451438

14461439
// After requeuing we should end up with 2 priorities - not 3
14471440
assert_eq!(server.pending.len(), 2);
14481441

14491442
// Send the remaining data. The initial mid priority one should go first now
1450-
let meta = server.write_stream_frames(&mut buf, 1000, true);
1443+
let meta = server.write_stream_frames(&mut buf.limit(1000), true);
14511444
assert_eq!(meta.len(), 2);
14521445
assert_eq!(meta[0].id, id_mid);
14531446
assert_eq!(meta[1].id, id_high);
@@ -1507,8 +1500,9 @@ mod tests {
15071500

15081501
// loop until all the streams are written
15091502
loop {
1510-
let buf_len = buf.len();
1511-
let meta = server.write_stream_frames(&mut buf, buf_len + 40, fair);
1503+
let mut lbuf = buf.limit(40);
1504+
let meta = server.write_stream_frames(&mut lbuf, fair);
1505+
buf = lbuf.into_inner();
15121506
if meta.is_empty() {
15131507
break;
15141508
}
@@ -1575,11 +1569,12 @@ mod tests {
15751569
stream_b.write(&[b'b'; 100]).unwrap();
15761570

15771571
let mut metas = vec![];
1578-
let mut buf = Vec::with_capacity(1024);
1572+
let buf = Vec::with_capacity(1024);
15791573

15801574
// Write the first chunk of stream_a
1581-
let buf_len = buf.len();
1582-
let meta = server.write_stream_frames(&mut buf, buf_len + 40, false);
1575+
let mut buf = buf.limit(40);
1576+
let meta = server.write_stream_frames(&mut buf, false);
1577+
let mut buf = buf.into_inner();
15831578
assert!(!meta.is_empty());
15841579
metas.extend(meta);
15851580

@@ -1595,8 +1590,9 @@ mod tests {
15951590

15961591
// loop until all the streams are written
15971592
loop {
1598-
let buf_len = buf.len();
1599-
let meta = server.write_stream_frames(&mut buf, buf_len + 40, false);
1593+
let mut lbuf = buf.limit(40);
1594+
let meta = server.write_stream_frames(&mut lbuf, false);
1595+
buf = lbuf.into_inner();
16001596
if meta.is_empty() {
16011597
break;
16021598
}

quinn-proto/src/connection/transmit_builder.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ use std::ops::{Deref, DerefMut};
22

33
use bytes::BufMut;
44

5-
use super::BufLen;
6-
75
/// The buffer in which to write datagrams for [`Connection::poll_transmit`]
86
///
97
/// The `poll_transmit` function writes zero or more datagrams to a buffer. Multiple
@@ -254,10 +252,3 @@ impl DatagramBuffer<'_> {
254252
self.max_offset - self.start_offset
255253
}
256254
}
257-
258-
// Temporary compatibility with the BufLen trait. To be removed in follow-up commits.
259-
impl BufLen for DatagramBuffer<'_> {
260-
fn len(&self) -> usize {
261-
self.deref().len()
262-
}
263-
}

0 commit comments

Comments
 (0)