Skip to content

Commit 603330a

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 c380db1 commit 603330a

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
@@ -850,13 +850,11 @@ impl Connection {
850850
}
851851
}
852852

853-
let sent = self.populate_packet(
854-
now,
855-
space_id,
856-
&mut transmits.datagram_mut(),
857-
builder.max_size,
858-
builder.exact_number,
859-
);
853+
let sent = {
854+
let frame_space = builder.max_size - transmits.datagram_mut().len();
855+
let mut buf = transmits.datagram_mut().limit(frame_space);
856+
self.populate_packet(now, space_id, &mut buf, builder.exact_number)
857+
};
860858

861859
// ACK-only packets should only be sent when explicitly allowed. If we write them due to
862860
// any other reason, there is a bug which leads to one component announcing write
@@ -3045,8 +3043,7 @@ impl Connection {
30453043
&mut self,
30463044
now: Instant,
30473045
space_id: SpaceId,
3048-
buf: &mut (impl BufMut + BufLen),
3049-
max_size: usize,
3046+
buf: &mut impl BufMut,
30503047
pn: u64,
30513048
) -> SentFrames {
30523049
let mut sent = SentFrames::default();
@@ -3122,7 +3119,7 @@ impl Connection {
31223119
}
31233120

31243121
// PATH_CHALLENGE
3125-
if buf.len() + 9 < max_size && space_id == SpaceId::Data {
3122+
if 9 < buf.remaining_mut() && space_id == SpaceId::Data {
31263123
// Transmit challenges with every outgoing frame on an unvalidated path
31273124
if let Some(token) = self.path.challenge {
31283125
// But only send a packet solely for that purpose at most once
@@ -3137,7 +3134,7 @@ impl Connection {
31373134
}
31383135

31393136
// PATH_RESPONSE
3140-
if buf.len() + 9 < max_size && space_id == SpaceId::Data {
3137+
if 9 < buf.remaining_mut() && space_id == SpaceId::Data {
31413138
if let Some(token) = self.path_responses.pop_on_path(self.path.remote) {
31423139
sent.non_retransmits = true;
31433140
sent.requires_padding = true;
@@ -3149,7 +3146,7 @@ impl Connection {
31493146
}
31503147

31513148
// CRYPTO
3152-
while buf.len() + frame::Crypto::SIZE_BOUND < max_size && !is_0rtt {
3149+
while frame::Crypto::SIZE_BOUND < buf.remaining_mut() && !is_0rtt {
31533150
let mut frame = match space.pending.crypto.pop_front() {
31543151
Some(x) => x,
31553152
None => break,
@@ -3159,8 +3156,7 @@ impl Connection {
31593156
// Since the offset is known, we can reserve the exact size required to encode it.
31603157
// For length we reserve 2bytes which allows to encode up to 2^14,
31613158
// which is more than what fits into normally sized QUIC frames.
3162-
let max_crypto_data_size = max_size
3163-
- buf.len()
3159+
let max_crypto_data_size = buf.remaining_mut()
31643160
- 1 // Frame Type
31653161
- VarInt::size(unsafe { VarInt::from_u64_unchecked(frame.offset) })
31663162
- 2; // Maximum encoded length for frame size, given we send less than 2^14 bytes
@@ -3196,12 +3192,11 @@ impl Connection {
31963192
&mut space.pending,
31973193
&mut sent.retransmits,
31983194
&mut self.stats.frame_tx,
3199-
max_size,
32003195
);
32013196
}
32023197

32033198
// NEW_CONNECTION_ID
3204-
while buf.len() + 44 < max_size {
3199+
while 44 < buf.remaining_mut() {
32053200
let issued = match space.pending.new_cids.pop() {
32063201
Some(x) => x,
32073202
None => break,
@@ -3223,7 +3218,7 @@ impl Connection {
32233218
}
32243219

32253220
// RETIRE_CONNECTION_ID
3226-
while buf.len() + frame::RETIRE_CONNECTION_ID_SIZE_BOUND < max_size {
3221+
while frame::RETIRE_CONNECTION_ID_SIZE_BOUND < buf.remaining_mut() {
32273222
let seq = match space.pending.retire_cids.pop() {
32283223
Some(x) => x,
32293224
None => break,
@@ -3237,8 +3232,8 @@ impl Connection {
32373232

32383233
// DATAGRAM
32393234
let mut sent_datagrams = false;
3240-
while buf.len() + Datagram::SIZE_BOUND < max_size && space_id == SpaceId::Data {
3241-
match self.datagrams.write(buf, max_size) {
3235+
while Datagram::SIZE_BOUND < buf.remaining_mut() && space_id == SpaceId::Data {
3236+
match self.datagrams.write(buf) {
32423237
true => {
32433238
sent_datagrams = true;
32443239
sent.non_retransmits = true;
@@ -3278,7 +3273,7 @@ impl Connection {
32783273
token: token.encode(&*server_config.token_key).into(),
32793274
};
32803275

3281-
if buf.len() + new_token.size() >= max_size {
3276+
if new_token.size() >= buf.remaining_mut() {
32823277
space.pending.new_tokens.push(remote_addr);
32833278
break;
32843279
}
@@ -3293,9 +3288,9 @@ impl Connection {
32933288

32943289
// STREAM
32953290
if space_id == SpaceId::Data {
3296-
sent.stream_frames =
3297-
self.streams
3298-
.write_stream_frames(buf, max_size, self.config.send_fairness);
3291+
sent.stream_frames = self
3292+
.streams
3293+
.write_stream_frames(buf, self.config.send_fairness);
32993294
self.stats.frame_tx.stream += sent.stream_frames.len() as u64;
33003295
}
33013296

@@ -3981,29 +3976,6 @@ fn negotiate_max_idle_timeout(x: Option<VarInt>, y: Option<VarInt>) -> Option<Du
39813976
}
39823977
}
39833978

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